How to Install Gitea (Your Own GitHub on a Linux Server)

Gitea is a Git server with a web interface that looks and works like GitHub — repositories, issues, pull requests, wikis, even CI runners — in a single small container. Good for private code you'd rather not put on someone else's servers, for keeping a mirror of your GitHub projects, or for a family's shared notes and configs under version control.
Quick reference
| Task | What |
|---|---|
| Folder | ~/docker/gitea/compose.yaml |
| Web | http://server-ip:3000 |
| SSH for git push | port 2222 on the server |
| Clone | git clone ssh://git@server-ip:2222/john/repo.git |
| Registration | Site administration → Settings or DISABLE_REGISTRATION |
1. The compose file
mkdir -p ~/docker/gitea && cd ~/docker/gitea
nano compose.yaml
services:
gitea:
image: gitea/gitea:1
container_name: gitea
environment:
USER_UID: 1000
USER_GID: 1000
GITEA__database__DB_TYPE: postgres
GITEA__database__HOST: db:5432
GITEA__database__NAME: gitea
GITEA__database__USER: gitea
GITEA__database__PASSWD: change-this
GITEA__server__SSH_PORT: 2222
GITEA__service__DISABLE_REGISTRATION: "false"
ports:
- "3000:3000"
- "2222:22"
volumes:
- ./data:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
depends_on:
- db
restart: unless-stopped
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: gitea
POSTGRES_PASSWORD: change-this
POSTGRES_DB: gitea
volumes:
- ./postgres:/var/lib/postgresql/data
restart: unless-stopped
Port 2222 is for git push over SSH — it can't be 22 because the server's own SSH is there.
docker compose up -d
sudo ufw allow 3000/tcp
sudo ufw allow 2222/tcp
2. First run
Open http://192.168.1.50:3000. The database fields are already filled from the environment. Set Server domain to the server's IP or name and Gitea base URL to match. Open Administrator account settings at the bottom and create your admin user now — otherwise the first person to register becomes admin. Install Gitea.
3. Close registration
Once you (and anyone else who needs an account) are in:
GITEA__service__DISABLE_REGISTRATION: "true"
docker compose up -d. Add future users from Site administration → User accounts.
4. Push your first repository
Add your SSH public key in Settings → SSH / GPG keys (the same key from tutorial 3). Create a repository with the + button. Then on your computer:
git remote add origin ssh://git@192.168.1.50:2222/john/my-project.git
git push -u origin main
Or clone a new one: git clone ssh://git@192.168.1.50:2222/john/my-project.git.
5. Mirror your GitHub repositories
+ → New migration → GitHub, paste the repository URL, tick This repository will be a mirror. Gitea pulls changes every few hours, so you always have a copy even if the original disappears. Use a GitHub token for private ones.
Behind Nginx
Proxy git.example.com to 127.0.0.1:3000 (tutorial 28) and set ROOT_URL to https://git.example.com/ in the environment. SSH stays on 2222 regardless.
Gitea Actions
Gitea can run GitHub-style workflows. Site administration → Actions → Runners gives you a token; run the gitea/act_runner container alongside with that token and your .github/workflows files mostly work unchanged.
Troubleshooting
"Permission denied (publickey)" on push. Key not added in Gitea, or you're pushing to port 22 instead of 2222.
Web page loads but links point to the wrong address. ROOT_URL is wrong. Edit ./data/gitea/conf/app.ini → [server] → ROOT_URL, restart.
"The repository is too large to push." Raise client_max_body_size in Nginx, or push over SSH, which has no limit.
Database errors on first start. The db container wasn't ready. docker compose restart gitea.
Wrapping up
Two containers, SSH on 2222, create the admin at install time, turn registration off, add your key. You have a private GitHub that mirrors your public one, with issues and pull requests for projects that will never leave the house.
