169 lines
5.3 KiB
Markdown
169 lines
5.3 KiB
Markdown
# Gitea on Dokploy
|
|
|
|
## [Gitea](https://gitea.routinedevelopment.ca/DaveanandMannie/gitea)
|
|
## [Github mirror](https://github.com/DaveanandMannie/gitea)
|
|
|
|
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:
|
|
|
|
```bash
|
|
curl -sSL https://dokploy.com/install.sh | sh
|
|
```
|
|
|
|
2. Create a new Project in Dokploy called "Gitea".
|
|
|
|
3. Create a Docker Compose service inside the project. Paste the contents of `docker-compose.yml`.
|
|
|
|
4. Add the environment variable in Dokploy's UI:
|
|
|
|
```
|
|
POSTGRES_PASSWORD=your_strong_password
|
|
```
|
|
|
|
5. Deploy. Let it complete the first boot.
|
|
|
|
6. Point your DNS A record for `gitea.routinedevelopment.ca` to the server IP.
|
|
|
|
7. 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.
|
|
|
|
8. 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:
|
|
|
|
```bash
|
|
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
|
|
```
|
|
|
|
2. SSH into the server and run the restore script:
|
|
|
|
```bash
|
|
chmod +x restore.sh
|
|
./restore.sh
|
|
```
|
|
|
|
3. Verify at `https://gitea.routinedevelopment.ca` — all repos, users, and orgs should be present.
|
|
|
|
## Backup
|
|
|
|
Run from the Dokploy server:
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
./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:
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
docker exec gitea ls /data/git/.ssh/id_ed25519.pub
|
|
```
|
|
|
|
If not, generate one:
|
|
|
|
```bash
|
|
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
|
|
```
|
|
|
|
2. Add the public key as a deploy key (with write access) on your GitHub repo.
|
|
|
|
3. 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:
|
|
|
|
```bash
|
|
docker volume ls | grep gitea
|
|
docker volume inspect <volume_name>
|
|
```
|