For years, I have hosted my personal git repositories on a self-hosted Gogs server. While some minor gliches have persisted for some time, I lived with them until recently. After yet another 500 error during a
push, I finally decided it was time to migrate to a more reliable platform.
I decided to try Gitea, which I hoped could bring some stability and the code search feature that I had longed desired.
Although I didn’t use features like issues and merge requests, Migration is not easy, I managed to migrate most of my repositories with a modified version of a migration script in Perl. Other repositories had to be migrated in very manual ways due to various errors from Gitea during the migration.
When I finally migrated all of them I found that some repositories on Gitea were empty while their originals on Gogs were not, These repositories were in the first migration batch that Gitea claimed had succeeded, I figured out the issues and successfully migrated those empty repositories.
At this point, my migration was fully completed, Gitea was working with all my previous repositories. However the false positives1 that Gitea gave to me were unacceptable, which could have cost me data loss if I had believed them, for git forges, data integrity always comes first.
Finally, I destroied the Gitea instance that I had just migrated to, and migrated all the repositoried to an raw OpenBSD server via SSH, it’s simple, effective and rock solid, here’s how.
doas.conf(5)) or modify the commands to not use it
Setup the server
Create git user
Even if you are the only one who access the repositories, a separate user provides more security and isolation, which is usually desired.
# mkdir -p /home/git # user add git # chown -R git:git /home/git
Restrict the user
git-shell(1) comes with
git(1), is a restricted login shell for git-only SSH access.
Make this the default shell of the git user:
# chsh git -s $(which git-shell)
Append the following to
/etc/ssh/sshd_config to restrict certain SSH capabilities for the git user, ensuring that it cannot do potentially risky actions via SSH.
Match User git AllowAgentForwarding no AllowTcpForwarding no X11Forwarding no PermitTTY no
Create a repository
doas -u git git init --bare /home/git/test.git
This initialize git config values so maintenance tasks will be scheduled for this repository.
doas -u git GIT_DIR=/home/git/test.git git maintanence register
The result is in
[maintenance] repo = /home/git/test.git
Start maintenance tasks
Run this once so the periodical maintanence tasks could be installed as cronjobs
# doas -u git GIT_DIR=/home/git/test.git git maintanence start
Check the tasks with:
# doas -u git crontab -l
They will look like this:
# BEGIN GIT MAINTENANCE SCHEDULE # The following schedule was created by Git # Any edits made in this region might be # replaced in the future by a Git command. 0 1-23 * * * "/usr/local/libexec/git/git" --exec-path="/usr/local/libexec/git" for-each-repo --config=maintenance.repo maintenance run --schedule=hourly 0 0 * * 1-6 "/usr/local/libexec/git/git" --exec-path="/usr/local/libexec/git" for-each-repo --config=maintenance.repo maintenance run --schedule=daily 0 0 * * 0 "/usr/local/libexec/git/git" --exec-path="/usr/local/libexec/git" for-each-repo --config=maintenance.repo maintenance run --schedule=weekly # END GIT MAINTENANCE SCHEDULE
On the client side
Clone the repository
# git clone email@example.com:test.git
For a repository under
# git clone firstname.lastname@example.org:folder/repo.git
You know the rest
ssh:// to the URL might lead to failure.
- Setup backup for
/home/gitif you haven’t already
- Create custom scripts3 under
/home/git/git-shell-commandsfor common tasks like repository CRUD
git-daemon(1)if you need public access, or
gitweb(1), cgit for a web UI
Git official documentation had changed the recommended protocol multiple times, alternating between SSH and HTTPS. To me SSH is easier to setup, more secure and performant. ↩
I currently have
mkrepo(with maintenance task registration) and
rm(on top of