Somehow, the official documentation for restoring Gitea from dump did not work for me. Roughly, the following command for the original rootful Docker image could look like this:

/app/gitea/gitea dump --file gitea-dump.zip -c /data/gitea/conf/app.ini --skip-lfs-data --skip-repository

Restoring to postgres according to the official docs failed:

psql -U $USER -d $DATABASE < gitea-db.sql

The problem was many missing repositories, missing organizations and many server 500 errors on issues, pull requests and repositories page.

Restoring this failed also for SQLite, according to the official docs above. This was done just as a confirmation:

sqlite3 $DATABASE_PATH < gitea-db.sql

Here the failure was even slightly worse, as the GPG key was not showing in the UI, although the commits appeared to be signed by a valid signature. Adding the same GPG key was not possible, stating the key already exists, yet was not shown anywhere.

I have found one single comment over the Internet about how to do it properly. Dumping:

docker exec -i gitea-db-1 /bin/bash -c "export PGPASSWORD=gitea && /usr/bin/pg_dump -U gitea gitea"  > dump_DB.sql

And restoring:

cat dump_DB.sql | docker exec -i gitea-db-1 psql -Ugitea

Rsync or copy all the folders containing repositories and other files manually and restart the container. This worked!

Issue with DNS resolution

This was a part of migration from rootful Gitea to rootless Gitea server. Rootles image uses alpine, which is probably the culprit for this error for Mirrors in the System Notices administration menu:

Migrate repository from https://github.com/peterbabic/repository-XXX failed: Clone: exit status 128 - fatal: unable to access 'https://github.com/peterbabic/repository-XXX.git/': Could not resolve host: github.com

It can also be seen as:

Failed to update mirror repository '/var/lib/gitea/git/repositories/peter.babic/repository-XXX.git': fatal: unable to access 'https://github.com/peterbabic/repository-XXX.git/': Could not resolve host: github.com
error: Could not fetch origin

The above message is different depending on the source of synchronization - if it is a cron job or a manually pressing Synchronize button in the repository settings. Manually mirroring any new repository fails as well.

Entering the container and trying ping confirms the issue:

$ ping github.com
ping: bad address 'github.com'

However pinging some other domains was possible:

$ ping google.sk
PING google.sk (142.251.39.99): 56 data bytes
ping: permission denied (are you root?)

And pinging any kind of reachable IP address from the Internet worked, underpinning the DNS issues. The problem can be further confirmed by the contents of the resolv.conf file inside that container:

$ cat /etc/resolv.conf
nameserver 127.0.0.11
options ndots:0

The contents of the file are obviously different on the host machine, containing at least one other real DNS server address apart from the internal Docker one of 127.0.0.1.

Docker JSON configuration

I was able to resolve the DNS issue by editing ~/.config/docker/daemon.json and inserting there the following:

{
  "dns": ["8.8.8.8"],
  "dns-opts": ["ndots:1"]
}

And then restarting the rootless Docker:

systemctl --user restart docker.service

Accessing the container now makes ping to github.com possible. Mirror synchronization in Gitea now works. The resolv.conf file now looks just a little bit different, I expected to find the 8.8.8.8 IP address there as well:

$ cat /etc/resolv.conf
nameserver 127.0.0.11
options ndots:1

Never mind, this setting will probably be reflected in some other output. I was able to add this configuration as an ansible task:

- name: Edit container 'resolv.conf' options
  ansble.builtin.blockinfile:
    path: ~/.config/docker/daemon.json
    validate: "python -mjson.tool %s > /dev/null"
    marker: "{mark}"
    marker_begin: "{"
    marker_end: "}"
    create: true
    block: |
      "dns": ["8.8.8.8"],
      "dns-opts": ["ndots:1"]

I found the above works, but might not be bulletproof. Note the validation part - it should work on most systems without the need to install other packages. Should the file exist and have some valid JSON inside before running this task, it will even append the contents into the JSON structure, but in this case the validation fails as there would be a missing comma , before the "dns" part. This bit could be solved by some other task, so leaving it here, in case anyone finds it interesting.

The task definitely works if the file is not existent or contains only braces on separate lines, which could happen as well. The task also works if the target daemon.json file is empty, in which case however such configuration makes Docker fail to start, because an empty file is not a valid JSON. The error is following:

$ journalctl --user -xeu docker
dockerd-rootless.sh[5125]: unable to configure the Docker daemon with file /home/user/.config/docker/daemon.json: EOF

But the daemon.json file could just be empty during the time you run your playbook, even before starting the Docker service, so I think the task is still useful. Note that the task also fails when the contents of the file are just {}, without a newline in between. This is a valid for Docker to start and can be common though. Enjoy!