Forgejo is a really cool git forge that you can self-host as an alternative to github. That’s exactly why I decided to install it on my VPS.
If you’re here for the migration guide, skip to Installing forgejo the correct way
The official installation guide lists 2 options for installation:
Now at the time I didn’t have dockge set up, and didn’t want to deal with docker containers, but downloading straight binaries seemed way worse. At the bottom, they also list a third option:
Ah that’s exactly what I want! Since my VPS runs debian, let’s go install the community maintained debian package and setup forgejo
Quick Disclaimer: I don’t blame any of this on the people packaging forgejo for debian. These are issues i had with my personal workflow and it’s not the average admin experience. I also didn’t talk to them about any of this, so if anything I’m at fault here.
Now I had forgejo up and running, but there was still something i wasnt satisfied with.
When you clone a git repository, you can choose between 2 download options: HTTP(S) or SSH. With HTTP(S), you create an access token and log in when cloning or pushing using your username and the access token. With SSH, you generate (or already have) an SSH keypair, add the public key to your account, and use the SSH key in git when interacting with the remote. The clone URLs differ slightly when using either method:
git clone https://git.ixhby.dev/ixhbinphoenix/flake.git # HTTP(S)
git clone git@git.ixhby.dev/ixhbinphoenix/flake # SSH
Now there’s a slight annoyance when using the forgejo debian package:
The SSH user actually isn’t git
by default, it’s forgejo
.
# User @ server /repo owner /repo
git clone forgejo@git.ixhby.dev/ixhbinphoenix/flake
Granted, this is a small nitpick, but it annoys me enough that I wanted to change it. So how do you do that? You change the user that runs forgejo. You’ll need to edit the systemd service installed by the package and change the owner of all forgejo-related things from forgejo:forgejo
to git:git
. This all works fine until you see a new forgejo release, update the package, and reset all your file permissions and the systemd service. This leads to every update taking about 30 mins extra time, because you forgot the changes you did, wonder why everything is broken, and finally realize what’s wrong and fix it.
This is a somewhat recent problem, but after the announcement of Forgejo v8, I of course wanted to stay up to date, so I ran apt update
aaaaand… nothing. Now this isn’t a problem, even 5 days after the release. What is a problem however, is that after checking my current version, I was still on 1.21.11-2, which was 2 months old at this point. This was the last push to bring me away from the debian package, and I sure as hell wouldn’t go to straight binaries (way too gay for straight binaries :3)
As I’ve mentioned before, I’ve transitioned all my service to run through dockge, which is bascially just a managment tool for docker-compose. Sidenote: I really need to make some kind of pre-processor or css class to put the trans flag on all words that start with trans. So, to make things quick this is basically my setup:
services:
forgejo:
restart: unless-stopped
image: codeberg.org/forgejo/forgejo:7 # yes i know v8 is out, didn't get to it yet
environment:
- USER_UID=106 # UID of `git` on host
- USER_GID=113 # GID of `git` on host
volumes:
- ./forgejo:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- 3000:3000
networks:
- forgejo
depends_on:
- postgres
postgres:
restart: unless-stopped
image: postgres:14
environment:
- POSTGRES_USER=gitea # legacy reasons lol
- POSTGRES_PASSWORD=gitea
- POSTGRES_DB=gitea
networks:
- forgejo
volumes:
- ./postgres:/var/lib/postgresql/data
networks:
forgejo:
external: false
This is almost a 1:1 copy of the forgejo install guide example, which is also why I won’t go into it much. It’s just a container running forgejo and a container running postgres. Note that the postgres URI will now be postgres
instead of localhost
.
Migrating PostgreSQL databases is suprisingly easy, but changes slightly depending on when you installed forgejo and if you made changes regarding the database config.
Run pg_dump -U gitea -W -F t gitea > dump.psql
on the host, then start your postgres container and run cat dump.psql | docker exec -it postgres pg_restore -U gitea -d gitea -F t
.
This assumes your database was previously named gitea, with the gitea user, and that your container is named postgres.
What is the t for? No fucking clue! But it works.
The new data location is in /forgejo
relative to the compose.yaml. In there are 3 directories: git
gitea
ssh
. git
contains the git repositories and LFS, gitea
contains all other data related to forgejo and ssh
contains the SSH host keys.
So, you can basically copy /var/lib/forgejo/data/forgejo-repositories
to ./forgejo/git/repositories
, and everything else from /var/lib/forgejo/data
to ./forgejo/gitea/
If you have a custom folder, copy all of it’s contents into ./forgejo/gitea
.
DO NOT JUST COPY THE CONFIG FILE!
You’ll need to at least change the paths defined in it. I recommend putting your old config file as old-app.ini
into ./forgejo/gitea/conf/
and comparing the new and old config side-by-side and changing stuff that doesn’t match. I’d also recommend (re-)reading the configuration cheatsheet since they seem to add new stuff between versions (who could’ve thought?)
Now you should be up and running with your forgejo in docker! Well for the most part
Unfortunately, forgejo doesn’t have a guide for this (yet! i may be contributing one) so i’ll rely on the gitea guide for this. Since the first three methods (Shim, SSH/Docker shell with authorized_keys) didn’t work for me for whatever reason, i’ll be focussing on the Docker Shell with AuthorizedKeysCommand method. You should probably look into the other methods first!
(if it does not already exist) create a git user on the host using useradd -m --system git
(if you used the git
user with the debian package) change the user’s home to /home/git
using usermod -d /home/git git
Also, add the user into the docker
group using usermod -aG docker git
(This is why I advise you to look into other methods first lol)
Create the following docker-shell
script in the git user’s home directory and make it executable. Replace <container_name>
with the name of your forgejo container.
#!/bin/bash
/usr/bin/docker exec -i -u git --env SSH_ORIGINAL_COMMAND="$SSH_ORIGINAL_COMMAND" <container_name> sh "$@"
Set this script as the git user’s login shell using usermod -s /home/git/docker-shell git
Add the following entry to your sshd_config, once again replacing <container_name>
with the name of your forgejo container.
Match User git
AuthorizedKeysCommandUser git
AuthorizedKeysCommand /usr/bin/docker exec -i -u git <container_name> /usr/local/bin/gitea keys -c /data/gitea/conf/app.ini -e git -u %u -t %t -k %k
Now systemctl restart sshd
and you’re done!
What’s happening here is when a user connects using SSH, the AuthorizedKeysCommand gets executed to get the authorized_keys of the container. The authorized_keys contains a command="" that’s executed by the git user on the host.
Because the git user on the host has the docker-shell
login shell, it gets executed inside of the docker container, emulating the normal behavior.
And that’s it! Now you’re running forgejo inside docker, with SSH support using the git
user.
Anyways, if you have any questions, contact me on email, fedi or xmpp and have a good day :3