My Gitea instance was originally spun up using SQLite — as this was easiest at the time. Over the years I’ve tried several times to switch to PostgreSQL and been unsuccessful until now.
Most of the steps are taken from this issue on Github and the Database Preparation page of the Gitea docs. Before you proceed please read both and take onboard this nugget of wisdom.
“Switching DBs is always hard, no matter what application you are running.” — delvh
With that said make full backups and prepare to fail.
I’m running Gitea in a docker container using the rootless image, so the app.ini location maybe different. /etc/gitea/app.ini refers to the config Gitea is currently using.
Instructions Link to heading
Mount a volume shared between the Gitea container and Postgresql container. For ease I mounted it at /opt/import in both containers.
1version: '3.8'
2services:
3 git:
4 image: gitea/gitea
5 volumes:
6 - "git_import:/opt/import"
7 …
8 db:
9 image: postgres:16.4-alpine
10 environment:
11 POSTGRES_DB: gitea
12 POSTGRES_USER: gitea
13 POSTGRES_PASSWORD: itsasecret
14 volumes:
15 - "git_import:/opt/import"
16 …
17volumes:
18 git_import:
19 driver: local
Docker exec into the running Gitea container and execute gitea doctor check --all --fix and gitea doctor recreate-table to make sure the SQLite database is in a good starting condition. If you run into errors here do not proceed until you have fixed them.
Stop the Gitea container and copy the database file to /opt/import1.
I did this on the docker host
1$ cp /var/lib/docker/volumes/gitea_gitea_data/_data/gitea.db \
2> /var/lib/docker/volumes/gitea_git_import/_data/gitea.db
This step avoids accidentally working on a database that is in use.
Restart the Gitea container and run the following in the container to dump the current database to a file that Postgresql should be able to import.
1$ cd /opt/import
2$ cp /etc/gitea/app.ini /opt/import/app.ini
Edit the path option of the database section in /opt/import/app.ini to point to /opt/import/gitea.db
1$ gitea --config /opt/import/app.ini dump \
2> --database postgres --skip-repository --skip-custom-dir \
3> --skip-attachment-data --skip-package-data --skip-index \
4> --file gitea-dump.zip
5$ unzip gitea-dump.zip
Switch to the Postgres container and follow all the steps on Database Preparation for PostgreSQL
Edit
/var/lib/postgresql/data/postgresql.confmake surepassword_encryption = scram-sha-256in the file and not commented out.Restart Postgres container.
Make sure the database role (user) exists
1CREATE ROLE gitea WITH LOGIN PASSWORD 'itsasecret';Create the database
1CREATE DATABASE gitea WITH OWNER gitea TEMPLATE template0 ENCODING UTF8 LC_COLLATE 'en_US.UTF-8' LC_CTYPE 'en_US.UTF-8';Make sure
/var/lib/postgresql/data/pg_hba.confhas the following linehost gitea gitea 192.0.2.10/32 scram-sha-256which has the formatCONNECTION_TYPEDATABASE_NAMEUSERADDRESSMETHODall of which should be documented in the file itself.Restart Postgres container
Import the exported database.
1$ cd /opt/import 2$ psql -U gitea1\i gitea-db.sqlWait for the import to complete.
Restart Postgres container
Switch back to the Gitea container
Edit /opt/import/app.ini with your new database settings.
1[database]
2DB_TYPE = postgres
3HOST = db:5432
4NAME = gitea
5USER = gitea
6PASSWD = itsasecret
7SSL_MODE = disable
1$ gitea doctor --config /opt/import/app.ini check --all --fix
2$ gitea doctor --config /opt/import/app.ini recreate-table
Edit /etc/gitea/app.ini with the same database configuration as above and add the following
1[log]
2LEVEL = Debug
Restart both containers and watch the Gitea startup logs while praying. Finally as is Gitea tradition, login to the Site Administration interface and ‘Resynchronize pre-receive, update and post-receive hooks of all repositories.’
I ran into permissions issues — due to the rootless image — a quick
chown -R 1000:1000 /var/lib/docker/volumes/git_import/_dataon the docker host system worked a treat. ↩︎