These notes cover a binary-to-binary migration from Gogs to Gitea or Forgejo on one host. A Docker deployment needs different steps, so start from the official upgrade guide if that is your setup.
Why the built-in migration failed
The Create -> New Migration -> Gogs screen in Gitea and Forgejo failed every time, even with both instances on the same machine. It rejected the Git URL, failed on authentication, or exited with code 128.
Copying the binaries and moving folders from Gogs v0.11 or newer onto Gitea or Forgejo did not work either. The reliable route is a mirror clone from Gogs and a mirror push into the new instance.
Set the SSH ports
Gogs already held port 22, so I moved the new instance to 2222 and tested both connections from an external machine:
ssh -T git@example.com
ssh -T git@example.com -p 2222
With a non-standard port, the clone URL needs the ssh:// form:
The scp-style form git@example.com:2222/my_name/test.git fails, because SSH reads 2222 as a path.
ssh://git@example.com:2222/my_name/test.git
Configure app.ini
In /etc/gitea/app.ini, under [server], set the port and turn on the built-in SSH server:
SSH_PORT = 2222
SSH_ALLOW_UNEXPECTED_AUTHORIZED_KEYS = true
START_SSH_SERVER = true
Forgejo refuses to start its SSH server when authorized_keys already holds entries, and that setting clears the objection. Without START_SSH_SERVER, nothing listens on 2222.
Migrate each repository
The process is manual. Mirror-clone from Gogs, create the repository on the new instance with the same default branch, then mirror-push:
git clone --mirror git@example.com:username/reponame.git
cd reponame.git
git push --mirror ssh://git@example.com:2222/username/reponame.git
Repeat for every repository, and plan a window: this is not a zero-downtime deployment.
Forgejo runners
Forgejo runs a GitHub Actions-compatible system, so workflows reuse the existing action ecosystem and actions/checkout replaces a bespoke clone step. Point the runner at Forgejo’s mirror:
[actions]
ENABLED = true
DEFAULT_ACTIONS_URL = https://data.forgejo.org
What to check afterwards
- Every repository appears with the correct default branch.
- SSH works for a normal user, not only the administrator.
- Webhooks and deploy keys are recreated, because they live in the application rather than in the Git repository.
