7.8 KiB
Gitea Migration: SQLite → PostgreSQL
Overview
Migrating Gitea from:
- Old:
git.infra.nkode.tech(SQLite, Dokploy on 191.101.0.153) - New:
git.infra.donovankelly.xyz(PostgreSQL, Dokploy on 191.101.0.153)
This is a destructive migration — back up everything before proceeding.
Prerequisites
- DNS: Point
git.infra.donovankelly.xyz→191.101.0.153 - Old Gitea export at
/home/clawdbot/clawd/gitea-export/on the VPS - Docker and docker-compose available on the Dokploy server
- The new compose service deployed via Dokploy (but NOT yet migrated)
Step-by-Step Migration
Step 1: DNS Setup
Add an A record:
git.infra.donovankelly.xyz → 191.101.0.153
Wait for propagation (check with dig git.infra.donovankelly.xyz).
Step 2: Stop the Old Gitea Instance
In Dokploy, stop the old Gitea application (nkode-giteasqlite).
# Or via CLI on 191.101.0.153:
docker stop <old-gitea-container>
Step 3: Deploy the New Stack (Fresh, No Data Yet)
Deploy the compose service from Dokploy. This will start:
- PostgreSQL 16 (empty database)
- Gitea (fresh install, connected to Postgres)
- Act Runner (will fail until token is set — that's OK)
Wait for Gitea to be healthy:
docker logs -f gitea
# Look for "Starting new Web server"
Step 4: Stop Gitea (Keep Postgres Running)
docker stop gitea
We need Gitea stopped to safely import data.
Step 5: Migrate the SQLite Database to PostgreSQL
Option A: Using gitea dump and restore (Recommended)
The export already has gitea-dump.zip. We'll use Gitea's built-in migration:
# Copy the SQLite database into the Gitea container's volume
docker cp /home/clawdbot/clawd/gitea-export/gitea.db gitea:/data/gitea/gitea.db
# Start gitea temporarily to run the migration
docker start gitea
# Run the database migration from SQLite to Postgres
docker exec -u git gitea gitea doctor convert --type sqlite --database /data/gitea/gitea.db
# If `doctor convert` isn't available in your version, use dump/restore:
# First, generate a SQL dump from SQLite using the gitea binary:
docker exec -u git gitea gitea dump --type postgres --database /data/gitea/gitea.db --file /tmp/gitea-pg-dump.sql
# Then import it into Postgres:
docker exec -i gitea-postgres psql -U gitea -d gitea < /tmp/gitea-pg-dump.sql
Option B: Using gitea migrate on fresh start
If the above doesn't work cleanly, use pgloader to convert SQLite → Postgres directly:
# Install pgloader (on the host or in a container)
docker run --rm --network gitea-net \
-v /home/clawdbot/clawd/gitea-export/gitea.db:/data/gitea.db \
dimitri/pgloader:latest \
pgloader /data/gitea.db \
postgresql://gitea:YOUR_POSTGRES_PASSWORD@postgres:5432/gitea
Option C: Manual approach using Gitea's dump file
# Extract the dump
cd /tmp
unzip /home/clawdbot/clawd/gitea-export/gitea-dump.zip
# The dump contains gitea-db.sql (SQLite format)
# Convert using pgloader or sqlite3 + sed for Postgres compatibility
Recommended approach: Option A with doctor convert
Step 6: Copy Repository Data and LFS
The git repositories, LFS objects, avatars, and other data files need to be copied into the new volume:
# Find the new gitea-data volume mount point
VOLUME_PATH=$(docker volume inspect gitea-data --format '{{ .Mountpoint }}')
# Stop gitea first
docker stop gitea
# Copy the data directory contents
sudo cp -a /home/clawdbot/clawd/gitea-export/data/git/* ${VOLUME_PATH}/git/
sudo cp -a /home/clawdbot/clawd/gitea-export/data/gitea/avatars ${VOLUME_PATH}/gitea/
sudo cp -a /home/clawdbot/clawd/gitea-export/data/gitea/repo-avatars ${VOLUME_PATH}/gitea/
sudo cp -a /home/clawdbot/clawd/gitea-export/data/gitea/attachments ${VOLUME_PATH}/gitea/
sudo cp -a /home/clawdbot/clawd/gitea-export/data/gitea/uploads ${VOLUME_PATH}/gitea/ 2>/dev/null || true
sudo cp -a /home/clawdbot/clawd/gitea-export/data/ssh/* ${VOLUME_PATH}/ssh/ 2>/dev/null || true
# Fix ownership (Gitea runs as UID 1000 / git user)
sudo chown -R 1000:1000 ${VOLUME_PATH}/
# Start gitea again
docker start gitea
Step 7: Verify the Migration
# Check Gitea logs for errors
docker logs gitea --tail 100
# Test the web UI
curl -s https://git.infra.donovankelly.xyz/api/v1/version
# Log in with your existing credentials
# Check that repos, users, orgs, webhooks are all present
Checklist:
- Can log in with existing user accounts
- All repositories are visible and cloneable
- LFS objects are accessible
- Webhooks are configured
- Organizations and teams are intact
- Avatars display correctly
- SSH keys work (
ssh -T git@git.infra.donovankelly.xyz -p 22222)
Step 8: Set Up Gitea Actions Runner
# Generate a runner registration token
docker exec -u git gitea gitea actions generate-runner-token
# Copy the token output, then update .env:
# RUNNER_REGISTRATION_TOKEN=<paste-token-here>
# Restart the runner
docker restart gitea-act-runner
# Verify the runner is connected
docker logs gitea-act-runner
You can also register the runner via the Gitea web UI:
- Go to Site Administration → Runners
- Click Create new runner
- Copy the token
Step 9: Configure Dokploy Domain / SSL
In Dokploy, configure the compose service's domain:
- Go to the "Infrastructure" project → compose service
- Add domain
git.infra.donovankelly.xyzpointing to the gitea service on port 3000 - Enable HTTPS (Let's Encrypt)
Step 10: Update Git Remotes
On all machines that had the old remote:
git remote set-url origin https://git.infra.donovankelly.xyz/<user>/<repo>.git
# or for SSH:
git remote set-url origin ssh://git@git.infra.donovankelly.xyz:22222/<user>/<repo>.git
Step 11: Clean Up
- Remove the old Gitea application from Dokploy
- Remove old Docker volumes
- Update any CI/CD webhooks pointing to the old domain
- Update any OAuth apps using the old domain
- Remove DNS record for
git.infra.nkode.tech(optional, keep for redirect)
Rollback Plan
If migration fails:
- Stop the new stack:
docker compose down - Restart the old Gitea container in Dokploy
- The old data is untouched in
/home/clawdbot/clawd/gitea-export/
Architecture
┌─────────────────────────────────────┐
│ Dokploy (Traefik) │
│ git.infra.donovankelly.xyz:443 │
│ ↓ :3000 │
│ ┌─────────────────────────────┐ │
│ │ Gitea 1.24 │ │
│ │ (Actions enabled) │ │
│ │ SSH :222 → external :22222 │ │
│ └──────────┬──────────────────┘ │
│ │ │
│ ┌──────────▼──────────────────┐ │
│ │ PostgreSQL 16 │ │
│ │ (gitea database) │ │
│ └─────────────────────────────┘ │
│ │
│ ┌─────────────────────────────┐ │
│ │ Act Runner │ │
│ │ (CI/CD workflows) │ │
│ └─────────────────────────────┘ │
└─────────────────────────────────────┘
Files
| File | Purpose |
|---|---|
docker-compose.yml |
Service definitions |
.env |
Secret values (DO NOT commit) |
.env.example |
Template for secrets |
MIGRATION.md |
This document |