Easily hosting GIT repos on forgejo


This is a fourth post in the High Altitude Water Aerosols series with the aim to get “cloud native” work for internal (web-)services.

We already have a container service running on Alpine, a somewhat reasonable reverse proxy config, and web server serving CA certificates.

It’s time to spin up some useful service.

Problem statement

I want to host GIT repositories. Obviously I could use github, codeberg, sr.ht, or a myriad of other providers.

But, what would it take to spin up my own Forgejo1 instance on the HAWA stack?

Let’s find out…


Forgejo publishes rootless docker images and provides Installation with Docker documentation.

So spinning it up on HAWA is actually super easy, barely an inconvenience.

Let’s give it a user, a few directories:

useradd -M -d /nonexistent -s /sbin/nologin -G int -p '*' int-forgejo
mkdir -p /mnt/ssdtank/containers/int/forgejo
mkdir -p /mnt/ssdtank/containers/int/forgejo/conf
mkdir -p /mnt/ssdtank/containers/int/forgejo/data
mkdir -p /mnt/ssdtank/containers/int/forgejo/vlg
chown int-forgejo:int-forgejo /mnt/ssdtank/containers/int/forgejo
chown int-forgejo:int-forgejo /mnt/ssdtank/containers/int/forgejo/conf
chown int-forgejo:int-forgejo /mnt/ssdtank/containers/int/forgejo/data
chown int-forgejo:int-forgejo /mnt/ssdtank/containers/int/forgejo/vlg
chmod o= /mnt/ssdtank/containers/int/forgejo

entry in compose.yml:

  # [...]
    image: codeberg.org/forgejo/forgejo:7-rootless
    container_name: forgejo
    #user: "int-forgejo:int-forgejo"
    user: "10xx:10xx" # FIXME
      - USER_UID=10xx # FIXME
      - USER_GID=10xx # FIXME
      - SSH_DOMAIN=git.int.wejn.org
      - DOMAIN=git.int.wejn.org
      - GITEA_WORK_DIR=/data/forgejo
      # requires bunch of manual config -- admin, smtp settings, etc
    restart: always
      - /mnt/ssdtank/containers/int/forgejo/data:/data
      - /mnt/ssdtank/containers/int/forgejo/vlg:/var/lib/gitea
      - /mnt/ssdtank/containers/int/forgejo/conf:/etc/gitea
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
      - "10.X.Y.Z:2222:2222"
      - "traefik.enable=true"
      - "traefik.http.routers.git-http.rule=Host(`git.int.wejn.org`)"
      - "traefik.http.routers.git-http.entrypoints=http"
      - "traefik.http.routers.git-http.middlewares=redirect-https@file"
      - "traefik.http.routers.git-http.service=git"
      - "traefik.http.routers.git-https.rule=Host(`git.int.wejn.org`)"
      - "traefik.http.routers.git-https.entrypoints=https"
      - "traefik.http.routers.git-https.service=git"
      - "traefik.http.services.git.loadbalancer.server.port=3000"

… and Bob’s your uncle2.


There are a few things to figure out:

Manual steps

The post-installation manual config is kinda annoying. I understand the need to specify admin password, smtp settings, etc. And some of it can be supplied via the environment. But not all.


Backup is another issue. Right now it’s basically rsync of the entire /mnt/ssdtank/containers/int/forgejo to a remote. Which works well because I’m using sqlite as a db, so there’s no annoyance with mysqldump etc.

But I can see how taking explicit point-in-time snaps and replicating those3 would be a great step up in reliability (and integrity of the backups).

Closing words

There you have it, the dream of my very own high altitude water aerosols setup realized: Adding new internal service is as easy as a new directory and a short stanza in podman-compose.

So far I’m liking this a lot.

  1. Forgejo is basically Gitea with some tweaks. But they have nicer documentation and I like their docker images better.

  2. Short for podman-compose up forgejo -d

  3. as opposed to running backup software against the directory