ENG | Upgrading Forgejo 11 to Forgejo 15
Article needs polishing such as links, maybe images, diff of compose file. Task for tomorrow I guess…
Today I found that new Forgejo 15.0 LTS was released, but I’m running Forgejo 11.0.x I backed up container volumes (database, config, data) using years old script [TODO:LINK], run podman-compose -f ...yml pull, podman-compose -f ...yml up. There was something about database update. I tried. Then I tried to log in via web page and was greeted by Forgejo installation. Weird. I certainly messed up something. In retrospect there were several problems
- Database update needed some manual intervention
- Forgejo’s config file changed location
- Wrong file permissions that previously did not matter
Issue 1: Restoring state from backup and retry
Hopefully I have some instructions how to migrate Gitea to Forgejo, which have backup and restoration procedure for testing [TODO:LINK]
Maybe start with database and return to forgejo-11 - we want to isolate if this was database upgrade problem or Forgejo update problem:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
###################################################
# Stop running Forgejo server and database
podman-compose -f ~/docker/docker-compose-forgejo.yml stop
#gitea
#gitea-mariadb
####################################################
# Remove containers
$ podman ps -a
#CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
#d53a1a86d4e8 lscr.io/linuxserver/mariadb:latest 40 minutes ago Exited (0) 2 minutes ago 3306/tcp gitea-mariadb
#c3f6d9311f6b codeberg.org/forgejo/forgejo:15.0-rootless 40 minutes ago Exited (1) 2 minutes ago 0.0.0.0:2222->2222/tcp, 0.0.0.0:8082->3000/tcp gitea
podman container rm d53a1a86d4e8
#Error: container d53a1a86d4e82c348dc9e3080e3bc5d2d7690843a6828a70085226c3c6563f5c has dependent containers which must be removed before it: c3f6d9311f6b4da0adf387854da2e13b965a03ce7cca51bce88165008f187212: container already exists
podman container rm c3f6d9311f6b
# c3f6d9311f6b
podman container rm d53a1a86d4e8
# d53a1a86d4e8
#############################################
# Remove and recreate volume, import data
podman volume remove docker_gitea-db
# docker_gitea-db
podman volume create docker_gitea-db
# docker_gitea-db
zstd -d < ~/backup/gitea-db-2026-04-21.tar.zst | podman volume import docker_gitea-db -
##############################################
# Pull containers
podman-compose -f docker-compose-forgejo.yml pull
Trying to pull lscr.io/linuxserver/mariadb:latest...
Trying to pull codeberg.org/forgejo/forgejo:15.0-rootless...
Getting image source signatures
Copying blob 622689a91c5c skipped: already exists
Copying blob b154e1a656ce skipped: already exists
Copying blob cf176656ebd6 skipped: already exists
Copying blob 3dd72f43f028 skipped: already exists
Copying blob 03cb7c4c8bca skipped: already exists
Copying blob 4ad52f698c1f skipped: already exists
Copying blob 5e0d54eacab6 skipped: already exists
Copying blob f310d650979a skipped: already exists
Copying blob d725f44b74ba skipped: already exists
Copying blob 43030eae6df4 skipped: already exists
Copying blob 4f4fb700ef54 skipped: already exists
Copying blob 6a0ac1617861 skipped: already exists
Copying config 57255a0094 done |
Writing manifest to image destination
57255a00947a43e3601ca15d6424debb1b08b15739c9638c2a2e02c74c1c70cc
Getting image source signatures
Copying blob 6198b5aa21c4 skipped: already exists
Copying blob f6a4c3e338ed skipped: already exists
Copying blob 635ce22f57a1 skipped: already exists
Copying blob ddd86d26b0ed skipped: already exists
Copying blob b48116483664 skipped: already exists
Copying blob 5dba32312827 skipped: already exists
Copying blob b35290be8052 skipped: already exists
Copying blob f472500d88c7 skipped: already exists
Copying blob f9f5923cad0b skipped: already exists
Copying config 8d6058b2df done |
Writing manifest to image destination
8d6058b2df0f0908d980d61bf59d76a7bd075791951b80bec56828336b04ccd2
###################################################
## Run database only
podman-compose -f docker-compose-forgejo.yml up gitea-db
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
825ad34a2b5eb9268c59580a860ba78d01e3f241515b85ebf62960f4e0e9808f
d2db6f02ce10ae127c0615659b023725983eadd005c2640d6e84ce54be57e03a
[gitea-db] | [migrations] started
[gitea-db] | [migrations] no migrations found
[gitea-db] | ───────────────────────────────────────
[gitea-db] |
[gitea-db] | ██╗ ███████╗██╗ ██████╗
[gitea-db] | ██║ ██╔════╝██║██╔═══██╗
[gitea-db] | ██║ ███████╗██║██║ ██║
[gitea-db] | ██║ ╚════██║██║██║ ██║
[gitea-db] | ███████╗███████║██║╚██████╔╝
[gitea-db] | ╚══════╝╚══════╝╚═╝ ╚═════╝
[gitea-db] |
[gitea-db] | Brought to you by linuxserver.io
[gitea-db] | ───────────────────────────────────────
[gitea-db] |
[gitea-db] | To support LSIO projects visit:
[gitea-db] | https://www.linuxserver.io/donate/
[gitea-db] |
[gitea-db] | ───────────────────────────────────────
[gitea-db] | GID/UID
[gitea-db] | ───────────────────────────────────────
[gitea-db] |
[gitea-db] | User UID: 1000
[gitea-db] | User GID: 911
[gitea-db] | ───────────────────────────────────────
[gitea-db] | Linuxserver.io version: 11.4.10-r0-ls213
[gitea-db] | Build-date: 2026-04-20T04:01:28+00:00
[gitea-db] | ───────────────────────────────────────
[gitea-db] |
[gitea-db] | [custom-init] No custom files found, skipping...
[gitea-db] | 260421 21:58:17 mysqld_safe Logging to '/config/databases/d2db6f02ce10.err'.
[gitea-db] | 260421 21:58:18 mysqld_safe Starting mariadbd daemon with databases from /config/databases
[gitea-db] | Connection to localhost (::1) 3306 port [tcp/mysql] succeeded!
[gitea-db] |
[gitea-db] | #####################################################################################
[gitea-db] | # #
[gitea-db] | # Logrotate Instructions #
[gitea-db] | # #
[gitea-db] | # Add the following to /config/custom.cnf under [mysqld]: #
[gitea-db] | # log_error = /config/log/mysql/mariadb-error.log #
[gitea-db] | # #
[gitea-db] | # Login to the SQL shell inside the container using: #
[gitea-db] | # mariadb -uroot -p<PASSWORD> #
[gitea-db] | # And run the following command: #
[gitea-db] | # GRANT ALL ON *.* TO root@localhost IDENTIFIED VIA unix_socket WITH GRANT OPTION ; #
[gitea-db] | # #
[gitea-db] | # Restart the container to apply the changes. #
[gitea-db] | # #
[gitea-db] | # You can read more about root@localhost permissions here: #
[gitea-db] | # https://mariadb.com/kb/en/authentication-from-mariadb-10-4/ #
[gitea-db] | # #
[gitea-db] | #####################################################################################
[gitea-db] |
[gitea-db] | #################################################################
[gitea-db] | # #
[gitea-db] | # An upgrade is required on your databases. #
[gitea-db] | # #
[gitea-db] | # Stop any services that are accessing databases #
[gitea-db] | # in this container, and then run the command #
[gitea-db] | # #
[gitea-db] | # mariadb-upgrade -u root #
[gitea-db] | # #
[gitea-db] | #################################################################
[gitea-db] |
[gitea-db] | [ls.io-init] done.
In 2nd terminal window (password might be in your ~/docker/.env file or somewhere)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[pavel@marten -=- ~]$ podman exec -it gitea-mariadb bash
root@d2db6f02ce10:/# vi /config/custom.cnf
root@d2db6f02ce10:/# mariadb -uroot -p
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 7
Server version: 11.4.10-MariaDB-log Alpine Linux
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> GRANT ALL ON *.* TO root@localhost IDENTIFIED VIA unix_socket WITH GRANT OPTION ;
Query OK, 0 rows affected (0.002 sec)
MariaDB [(none)]> /quit
-> \quit
Bye
root@d2db6f02ce10:/# exit
exit
In 1st terminal window Ctrl+C Ctrl+C to shutdown container. Now it should be slighly different
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[gitea-db] | Logrotate is enabled
[gitea-db] |
[gitea-db] |
[gitea-db] |
[gitea-db] | #################################################################
[gitea-db] | # #
[gitea-db] | # An upgrade is required on your databases. #
[gitea-db] | # #
[gitea-db] | # Stop any services that are accessing databases #
[gitea-db] | # in this container, and then run the command #
[gitea-db] | # #
[gitea-db] | # mariadb-upgrade -u root #
[gitea-db] | # #
[gitea-db] | #################################################################
[gitea-db] |
[gitea-db] |
[gitea-db] |
[gitea-db] | [ls.io-init] done.
In 2nd terminal window:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[pavel@marten -=- ~]$ podman exec -it gitea-mariadb bash
root@d2db6f02ce10:/# mariadb-upgrade -u root
Phase 1/8: Checking and upgrading mysql database
Processing databases
mysql
mysql.column_stats OK
mysql.columns_priv OK
mysql.db OK
...
gitea.watch OK
gitea.webauthn_credential OK
gitea.webhook OK
information_schema
performance_schema
sys
sys.sys_config OK
Phase 7/8: uninstalling plugins
Phase 8/8: Running 'FLUSH PRIVILEGES'
OK
root@d2db6f02ce10:/# exit
exit
Now start everything and try
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
[pavel@marten -=- ~/docker]$ podman-compose -f docker-compose-forgejo.yml up
dbf730f8bf83f59525e120fa8025c9dc9073b9762e42111065ae28da86c8114f
[gitea-db] | [migrations] started
[gitea-db] | [migrations] no migrations found
[gitea-db] | usermod: no changes
[gitea-db] | ───────────────────────────────────────
[gitea-db] |
[gitea-db] | ██╗ ███████╗██╗ ██████╗
[gitea-db] | ██║ ██╔════╝██║██╔═══██╗
[gitea-db] | ██║ ███████╗██║██║ ██║
[gitea-db] | ██║ ╚════██║██║██║ ██║
[gitea-db] | ███████╗███████║██║╚██████╔╝
[gitea-db] | ╚══════╝╚══════╝╚═╝ ╚═════╝
[gitea-db] |
[gitea-db] | Brought to you by linuxserver.io
[gitea-db] | ───────────────────────────────────────
[gitea-db] |
[gitea-db] | To support LSIO projects visit:
[gitea-db] | https://www.linuxserver.io/donate/
[gitea-db] |
[gitea-db] | ───────────────────────────────────────
[gitea-db] | GID/UID
[gitea-db] | ───────────────────────────────────────
[gitea-db] |
[gitea-db] | User UID: 1000
[gitea-db] | User GID: 911
[gitea-db] | ───────────────────────────────────────
[gitea-db] | Linuxserver.io version: 11.4.10-r0-ls213
[gitea-db] | Build-date: 2026-04-20T04:01:28+00:00
[gitea-db] | ───────────────────────────────────────
[gitea-db] |
[gitea-db] | [custom-init] No custom files found, skipping...
[gitea-server] | WARNING: detected configuration file in deprecated default path /etc/gitea/app.ini. The new default is /var/lib/gitea/custom/conf/app.ini. To remove this warning, choose one of the options:
[gitea-server] | * Move /etc/gitea/app.ini to /var/lib/gitea/custom/conf/app.ini (or to $GITEA_APP_INI if you want to override this variable)
[gitea-server] | * Explicitly override GITEA_APP_INI=/etc/gitea/app.ini in the container environment
[gitea-db] | 260421 22:08:17 mysqld_safe Logging to '/config/databases/d2db6f02ce10.err'.
[gitea-server] | 2026/04/21 22:08:17 cmd/web.go:253:runWeb() [I] Starting Forgejo on PID: 2
[gitea-server] | 2026/04/21 22:08:17 cmd/web.go:112:showWebStartupMessage() [I] Forgejo version: 11.0.12+gitea-1.22.0 built with GNU Make 4.4.1, go1.25.9 : bindata, timetzdata, sqlite, sqlite_unlock_notify
[gitea-server] | 2026/04/21 22:08:17 cmd/web.go:113:showWebStartupMessage() [I] * RunMode: prod
[gitea-server] | 2026/04/21 22:08:17 cmd/web.go:114:showWebStartupMessage() [I] * AppPath: /usr/local/bin/gitea
[gitea-server] | 2026/04/21 22:08:17 cmd/web.go:115:showWebStartupMessage() [I] * WorkPath: /var/lib/gitea
[gitea-server] | 2026/04/21 22:08:17 cmd/web.go:116:showWebStartupMessage() [I] * CustomPath: /var/lib/gitea/custom
[gitea-server] | 2026/04/21 22:08:17 cmd/web.go:117:showWebStartupMessage() [I] * ConfigFile: /etc/gitea/app.ini
[gitea-server] | 2026/04/21 22:08:17 cmd/web.go:118:showWebStartupMessage() [I] Prepare to run web server
[gitea-db] | 260421 22:08:17 mysqld_safe Starting mariadbd daemon with databases from /config/databases
[gitea-server] | 2026/04/21 22:08:17 routers/init.go:114:InitWebInstalled() [I] Git version: 2.49.1, Wire Protocol Version 2 Enabled (home: /var/lib/gitea/home)
[gitea-server] | 2026/04/21 22:08:17 ...s/storage/storage.go:157:initAttachments() [I] Initialising Attachment storage with type: local
[gitea-server] | 2026/04/21 22:08:17 ...les/storage/local.go:33:NewLocalStorage() [I] Creating new Local Storage at /var/lib/gitea/data/attachments
[gitea-server] | 2026/04/21 22:08:17 ...s/storage/storage.go:147:initAvatars() [I] Initialising Avatar storage with type: local
[gitea-server] | 2026/04/21 22:08:17 ...les/storage/local.go:33:NewLocalStorage() [I] Creating new Local Storage at /var/lib/gitea/data/avatars
[gitea-server] | 2026/04/21 22:08:17 ...s/storage/storage.go:173:initRepoAvatars() [I] Initialising Repository Avatar storage with type: local
[gitea-server] | 2026/04/21 22:08:17 ...les/storage/local.go:33:NewLocalStorage() [I] Creating new Local Storage at /var/lib/gitea/data/repo-avatars
[gitea-server] | 2026/04/21 22:08:17 ...s/storage/storage.go:167:initLFS() [I] Initialising LFS storage with type: local
[gitea-server] | 2026/04/21 22:08:17 ...les/storage/local.go:33:NewLocalStorage() [I] Creating new Local Storage at /var/lib/gitea/git/lfs
[gitea-server] | 2026/04/21 22:08:17 ...s/storage/storage.go:179:initRepoArchives() [I] Initialising Repository Archive storage with type: local
[gitea-server] | 2026/04/21 22:08:17 ...les/storage/local.go:33:NewLocalStorage() [I] Creating new Local Storage at /var/lib/gitea/repo-archive
[gitea-server] | 2026/04/21 22:08:17 ...s/storage/storage.go:189:initPackages() [I] Initialising Packages storage with type: local
[gitea-server] | 2026/04/21 22:08:17 ...les/storage/local.go:33:NewLocalStorage() [I] Creating new Local Storage at /var/lib/gitea/packages
[gitea-server] | 2026/04/21 22:08:17 ...s/storage/storage.go:200:initActions() [I] Initialising Actions storage with type: local
[gitea-server] | 2026/04/21 22:08:17 ...les/storage/local.go:33:NewLocalStorage() [I] Creating new Local Storage at /var/lib/gitea/actions_log
[gitea-server] | 2026/04/21 22:08:17 ...s/storage/storage.go:204:initActions() [I] Initialising ActionsArtifacts storage with type: local
[gitea-server] | 2026/04/21 22:08:17 ...les/storage/local.go:33:NewLocalStorage() [I] Creating new Local Storage at /var/lib/gitea/actions_artifacts
[gitea-server] | 2026/04/21 22:08:17 routers/init.go:133:InitWebInstalled() [I] SQLite3 support is enabled
[gitea-server] | 2026/04/21 22:08:17 routers/common/db.go:23:InitDBEngine() [I] Beginning ORM engine initialization.
[gitea-server] | 2026/04/21 22:08:17 routers/common/db.go:30:InitDBEngine() [I] ORM engine initialization attempt #1/10...
[gitea-server] | 2026/04/21 22:08:17 cmd/web.go:205:serveInstalled() [I] PING DATABASE mysql
[gitea-server] | 2026/04/21 22:08:17 routers/common/db.go:36:InitDBEngine() [E] ORM engine initialization attempt #1/10 failed. Error: dial tcp 10.89.0.34:3306: connect: connection refused
[gitea-server] | 2026/04/21 22:08:17 routers/common/db.go:37:InitDBEngine() [I] Backing off for 3 seconds
[gitea-db] | Connection to localhost (::1) 3306 port [tcp/mysql] succeeded!
[gitea-db] | Logrotate is enabled
[gitea-db] | [ls.io-init] done.
[gitea-server] | 2026/04/21 22:08:20 routers/common/db.go:30:InitDBEngine() [I] ORM engine initialization attempt #2/10...
[gitea-server] | 2026/04/21 22:08:20 cmd/web.go:205:serveInstalled() [I] PING DATABASE mysql
[gitea-server] | 2026/04/21 22:08:21 ...dels/db/collation.go:153:preprocessDatabaseCollation() [W] Current database is using a case-insensitive collation "utf8mb4_general_ci", although Forgejo could work with it, there might be some rare cases which don't work as expected.
[gitea-server] | 2026/04/21 22:08:21 cmd/web.go:205:serveInstalled() [W] Table project column board_type db type is INT(10) UNSIGNED, struct type is INT UNSIGNED
[gitea-server] | 2026/04/21 22:08:21 cmd/web.go:205:serveInstalled() [W] Table project column card_type db type is INT(10) UNSIGNED, struct type is INT UNSIGNED
[gitea-server] | 2026/04/21 22:08:21 cmd/web.go:205:serveInstalled() [W] Table project column type db type is INT(10) UNSIGNED, struct type is INT UNSIGNED
[gitea-server] | 2026/04/21 22:08:21 routers/init.go:139:InitWebInstalled() [I] ORM engine initialization successful!
[gitea-server] | 2026/04/21 22:08:21 ...er/issues/indexer.go:78:func1() [I] PID 2: Initializing Issue Indexer: bleve
[gitea-server] | 2026/04/21 22:08:21 ...xer/stats/indexer.go:41:populateRepoIndexer() [I] Populating the repo stats indexer with existing repositories
[gitea-server] | 2026/04/21 22:08:21 ...xer/stats/indexer.go:87:populateRepoIndexer() [I] Done (re)populating the repo stats indexer with existing repositories
[gitea-server] | 2026/04/21 22:08:21 ...er/issues/indexer.go:155:func2() [I] Issue Indexer Initialization took 2.405544ms
[gitea-server] | 2026/04/21 22:08:21 modules/ssh/ssh.go:332:Listen() [I] Adding SSH host key: /var/lib/gitea/ssh/gitea.rsa
[gitea-server] | 2026/04/21 22:08:21 modules/ssh/init.go:26:Init() [I] SSH server started on :2222. Cipher list ([[email protected] aes128-ctr aes192-ctr aes256-ctr [email protected] [email protected]]), key exchange algorithms ([curve25519-sha256 ecdh-sha2-nistp256 ecdh-sha2-nistp384 ecdh-sha2-nistp521 diffie-hellman-group14-sha256 diffie-hellman-group14-sha1]), MACs ([[email protected] hmac-sha2-256 hmac-sha1])
[gitea-server] | 2026/04/21 22:08:21 ...s/graceful/server.go:50:NewServer() [I] Starting new SSH server: tcp::2222 on PID: 2
[gitea-server] | 2026/04/21 22:08:21 ...er/cleanup_sha256.go:27:CleanupSHA256() [I] Start to cleanup dangling images with a sha256:* version
[gitea-server] | 2026/04/21 22:08:21 ...er/cleanup_sha256.go:106:cleanupSHA256() [I] Nothing to cleanup
[gitea-server] | 2026/04/21 22:08:21 ...er/cleanup_sha256.go:29:CleanupSHA256() [I] Finished to cleanup dangling images with a sha256:* version
[gitea-server] | 2026/04/21 22:08:21 cmd/web.go:315:listen() [I] Listen: http://0.0.0.0:3000
[gitea-server] | 2026/04/21 22:08:21 cmd/web.go:319:listen() [I] AppURL(ROOT_URL): https://git.pavelp.cz/
[gitea-server] | 2026/04/21 22:08:21 cmd/web.go:322:listen() [I] LFS server enabled
[gitea-server] | 2026/04/21 22:08:21 ...s/graceful/server.go:50:NewServer() [I] Starting new Web server: tcp:0.0.0.0:3000 on PID: 2
[gitea-server] | 2026/04/21 22:08:32 ...eb/routing/logger.go:102:func1() [I] router: completed GET / for 89.102.37.225:0, 200 OK in 6.2ms @ web/home.go:32(web.Home)
[gitea-server] | 2026/04/21 22:08:37 ...eb/routing/logger.go:102:func1() [I] router: completed GET /user/login?redirect_to=%2f for 89.102.37.225:0, 200 OK in 7.7ms @ auth/auth.go:145(auth.SignIn)
[gitea-server] | 2026/04/21 22:08:39 ...eb/routing/logger.go:102:func1() [I] router: completed POST /user/login for 89.102.37.225:0, 303 See Other in 71.0ms @ auth/auth.go:179(auth.SignInPost)
[gitea-server] | 2026/04/21 22:08:40 ...eb/routing/logger.go:102:func1() [I] router: completed GET / for 89.102.37.225:0, 200 OK in 59.1ms @ web/home.go:32(web.Home)
[gitea-server] | 2026/04/21 22:08:40 ...eb/routing/logger.go:102:func1() [I] router: completed GET /avatar/b20f8607faa9ee279794ba4c56ba2dd9?size=56 for 89.102.37.225:0, 303 See Other in 29.8ms @ user/avatar.go:48(user.AvatarByEmailHash)
[gitea-server] | 2026/04/21 22:08:40 ...eb/routing/logger.go:102:func1() [I] router: completed GET /avatar/b20f8607faa9ee279794ba4c56ba2dd9?size=48 for 89.102.37.225:0, 303 See Other in 29.6ms @ user/avatar.go:48(user.AvatarByEmailHash)
[gitea-server] | 2026/04/21 22:08:40 ...eb/routing/logger.go:102:func1() [I] router: completed GET /repo/search?count_only=1&uid=1&team_id=undefined&q=&page=1&mode= for 89.102.37.225:0, 200 OK in 6.8ms @ repo/repo.go:593(repo.SearchRepo)
[gitea-server] | 2026/04/21 22:08:40 ...eb/routing/logger.go:102:func1() [I] router: completed GET /avatar/cf6b7f76993d737ca8f70880b830e13c?size=56 for 89.102.37.225:0, 303 See Other in 57.1ms @ user/avatar.go:48(user.AvatarByEmailHash)
[gitea-server] | 2026/04/21 22:08:40 ...eb/routing/logger.go:102:func1() [I] router: completed GET /repo/search?sort=updated&order=desc&uid=1&team_id=undefined&q=&page=1&limit=15&mode=&archived=false for 89.102.37.225:0, 200 OK in 27.3ms @ repo/repo.go:593(repo.SearchRepo)
[gitea-server] | 2026/04/21 22:08:43 ...eb/routing/logger.go:68:func1() [I] router: polling GET /user/events for 89.102.37.225:0, elapsed 3525.4ms @ events/events.go:18(events.Events)
[gitea-server] | 2026/04/21 22:09:40 ...eb/routing/logger.go:102:func1() [I] router: completed GET /user/events for 89.102.37.225:0, 200 OK in 60020.5ms @ events/events.go:18(events.Events)
Issue #2: Config file location
WAIT! THIS IS INTERESTING
1
2
3
[gitea-server] | WARNING: detected configuration file in deprecated default path /etc/gitea/app.ini. The new default is /var/lib/gitea/custom/conf/app.ini. To remove this warning, choose one of the options:
[gitea-server] | * Move /etc/gitea/app.ini to /var/lib/gitea/custom/conf/app.ini (or to $GITEA_APP_INI if you want to override this variable)
[gitea-server] | * Explicitly override GITEA_APP_INI=/etc/gitea/app.ini in the container environment
Nonetheless Forgejo works. Well. Stop it, backup updated database, just in case we will need it again:
1
podman volume export docker_gitea-db | zstd -11 > ~/backup/gitea-db-2026-04-21-newdb.tar.zst
Now I see. Current config uses volume - gitea-config:/etc/gitea which contains only app.ini file
Now black magic podman unshare command to access data inside volumes. Note output of ID commands:
1
2
3
4
5
6
7
8
9
10
id
# uid=1000(pavel) gid=1000(pavel) groups=1000(pavel),10(wheel),18(dialout) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
podman unshare bash
id
# uid=0(root) gid=0(root) groups=0(root),65534(nobody) context=unconfined_u:unconfined_r:container_runtime_t:s0-s0:c0.c1023
cd /home/pavel/.local/share/containers/storage/volumes
diff -y docker_gitea-config/_data/app.ini docker_gitea-data/_data/custom/conf/app.ini
cp docker_gitea-config/_data/app.ini docker_gitea-data/_data/custom/conf/app.ini
exit
This copies old file to new one (which might have been created by new version of Forgejo) Now we can remove mounting gitea-config volume and switch version. Honestly maybe we should restore data volume and copy this file again. Let’s do it. So again, restore last Forgejo 11:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Remove containers and volumes
podman container rm b34071ff5d2a 45a23d11b349
podman volume rm docker_gitea-db docker_gitea-data
podman volume create docker_gitea-db
podman volume create docker_gitea-data
# Restore backup (updated Forgejo11 database and data prior to the very first attempt to run Forgejo 15)
zstd -d < ~/backup/gitea-db-2026-04-21-newdb.tar.zst | podman volume import docker_gitea-db -
zstd -d < ~/backup/gitea-data-2026-04-21.tar.zst | podman volume import docker_gitea-data -
# Copy config to the new location
podman unshare bash
# Here we do not have conf directory, it was obviously created by Forgejo 15
cd /home/pavel/.local/share/containers/storage/volumes
mkdir -p docker_gitea-data/_data/custom/conf/
cp docker_gitea-config/_data/app.ini docker_gitea-data/_data/custom/conf/app.ini
# Leave shell with container root user
exit
# Download containers
podman-compose -f docker-compose-forgejo.yml pull
# Run in foreground (add -d for background)
podman-compose -f docker-compose-forgejo.yml up
Issue 3: File permissions
1
[gitea-server] | 2026/04/21 22:56:08 ...s/setting/setting.go:94:InitCfgProvider() [F] Unable to init config provider from "/var/lib/gitea/custom/conf/app.ini": failed to load config file "/var/lib/gitea/custom/conf/app.ini": open /var/lib/gitea/custom/conf/app.ini: permission denied
1
2
[gitea-server] | 2026/04/21 22:58:47 ...g/config_provider.go:349:deprecatedSettingWarning() [E] Deprecated config option `[log]` `logger.router.MODE` present. Use `[log]` `LOGGER_ROUTER_MODE` instead.
[gitea-server] | 2026/04/21 22:58:47 ...odules/setting/f3.go:39:loadF3From() [F] Failed to create F3 path /var/lib/gitea/f3: mkdir /var/lib/gitea/f3: permission denied
Now I needed to fix permissions: podman unshare bash, change directory chown pavel:pavel app.ini and cd /home/pavel/.local/share/containers/storage/volumes/docker_gitea-data/_data && chown pavel.pavel . to change /var/lib/gitea.
Next start hopefully worked.