2026-02-21 21:44:09 -05:00
2026-02-21 21:40:20 -05:00
2026-02-21 21:44:09 -05:00
2026-02-21 21:40:20 -05:00
2026-02-21 21:40:20 -05:00
2026-02-21 21:40:20 -05:00

Gitea on Dokploy

Self-hosted Gitea deployment running on Dokploy with a local Postgres database.

  • Domain: gitea.routinedevelopment.ca
  • SSH: Port 2222 (built-in SSH server, HTTP git disabled)
  • Database: Local Postgres 16 (container gitea-db)
  • Volumes: gitea-data (repos, LFS, avatars, SSH keys), db-data (Postgres)

Setup (Fresh Install)

  1. Install Dokploy on a clean Ubuntu server:
curl -sSL https://dokploy.com/install.sh | sh
  1. Create a new Project in Dokploy called "Gitea".

  2. Create a Docker Compose service inside the project. Paste the contents of docker-compose.yml.

  3. Add the environment variable in Dokploy's UI:

POSTGRES_PASSWORD=your_strong_password
  1. Deploy. Let it complete the first boot.

  2. Point your DNS A record for gitea.routinedevelopment.ca to the server IP.

  3. In Dokploy's UI, go to the Gitea compose service → Domains tab. Add gitea.routinedevelopment.ca with container port 3000, HTTPS enabled, and Let's Encrypt certificate. The docs say Traefik labels alone should work, but in practice you may need to also add the domain via the UI.

  4. Redeploy so Traefik picks up the domain and issues the Let's Encrypt certificate.

Domain Troubleshooting

If the domain doesn't work after deploying:

  • DNS must resolve first: Let's Encrypt needs to reach the server. Make sure your DNS/reserved IP points to the server before adding the domain in Dokploy. If added too early, recreate the domain or restart Traefik.
  • dokploy-network is required: Traefik runs on dokploy-network. If your compose service isn't on that network, Traefik can't reach it even if the labels are correct. The compose file in this repo already handles this.
  • Reserved IP mismatch: If using a DigitalOcean reserved IP, Dokploy may complain that the domain resolves to the reserved IP instead of the droplet's direct IP. This is fine — traffic still reaches the server. Deploy anyway.
  • Redeploy after any domain change: Unlike Applications, Docker Compose services require a redeploy for domain changes to take effect.

Restore from Backup

If restoring onto a fresh Dokploy instance after the initial deploy:

  1. SCP the backup files to the server:
scp gitea_db_backup.dump user@server:~/
scp gitea_files_backup.tar.gz user@server:~/
scp app.ini user@server:~/    # the REAL one with secrets, not the template
  1. SSH into the server and run the restore script:
chmod +x restore.sh
./restore.sh
  1. Verify at https://gitea.routinedevelopment.ca — all repos, users, and orgs should be present.

Backup

Run from the Dokploy server:

chmod +x backup.sh
./backup.sh

Backups are saved to ~/gitea-backups/ with timestamps. Each backup creates three files:

  • gitea_db_YYYYMMDD_HHMMSS.dump — Postgres database dump
  • gitea_files_YYYYMMDD_HHMMSS.tar.gz — Repositories, LFS, avatars, attachments, SSH keys
  • app_YYYYMMDD_HHMMSS.ini — Current app.ini config (contains secrets)

You can specify a custom backup directory:

./backup.sh /path/to/backups

Recommended: Push backups offsite (S3, DigitalOcean Spaces, etc.). Don't rely solely on the same disk.

Automated Backups (Optional)

Add a cron job on the server to run backups daily:

crontab -e
0 3 * * * /path/to/backup.sh /home/user/gitea-backups >> /var/log/gitea-backup.log 2>&1

Secrets

The app.ini in this repo has <CHANGE_ME> placeholders. The real values you need to set:

Key Location Description
LFS_JWT_SECRET [server] JWT secret for LFS
INTERNAL_TOKEN [security] Internal API token
JWT_SECRET [oauth2] OAuth2 JWT secret
PASSWD [database] Must match POSTGRES_PASSWORD env var

Keep your real app.ini as app.ini.local (gitignored) or in a password manager.

SSH Remotes

Since HTTP git is disabled, all clones use SSH on port 2222:

git clone ssh://git@gitea.routinedevelopment.ca:2222/org/repo.git

Note: The container user is git, not gitea. If migrating from baremetal, update your remotes:

git remote set-url origin ssh://git@gitea.routinedevelopment.ca:2222/YourOrg/your-repo.git

GitHub Mirror

To push-mirror a repo to GitHub:

  1. Ensure the container has an SSH key:
docker exec gitea ls /data/git/.ssh/id_ed25519.pub

If not, generate one:

docker exec gitea ssh-keygen -t ed25519 -f /data/git/.ssh/id_ed25519 -N ""
docker exec gitea chown git:git /data/git/.ssh/id_ed25519
  1. Add the public key as a deploy key (with write access) on your GitHub repo.

  2. Set up a post-receive hook or cron to push.

The SSH key lives in the gitea-data volume and persists across redeploys.

Volume Info

Volume Contents Path in container
gitea-data Repos, LFS, avatars, config, SSH keys /data
db-data Postgres data /var/lib/postgresql/data

Volumes persist across redeploys. They are only destroyed by docker compose down -v or docker volume rm. Never run down -v in production.

Inspect volumes:

docker volume ls | grep gitea
docker volume inspect <volume_name>
Description
No description provided
Readme 34 KiB
Languages
Shell 100%