Self-host
Run your own.
One release and a Postgres. Pick how you'd like to run it, tell it where it will live, and paste the steps in order.
-
1 Start a database
Postgres on a private network the forge joins; nothing is published to the host.
podman network create gitgud podman run -d --restart unless-stopped --network gitgud --name gitgud-db \ -e POSTGRES_USER=gitgud -e POSTGRES_PASSWORD=change-me -e POSTGRES_DB=gitgud \ -v gitgud-db:/var/lib/postgresql/data \ docker.io/library/postgres:16-alpine -
2 Write the configuration
Run this once: it generates the secrets. Keep a copy of gitgud.env somewhere safe — GITGUD_SECRETS_MASTER_KEY encrypts CI secrets and two-factor keys, and without it they're gone.
(umask 077; cat > gitgud.env <<EOF PHX_HOST=git.example.com DATABASE_URL=ecto://gitgud:change-me@gitgud-db/gitgud SECRET_KEY_BASE=$(openssl rand -base64 48 | tr -d '\n') GITGUD_RUNNER_JWT_SECRET=$(openssl rand -base64 48 | tr -d '\n') GITGUD_SECRETS_MASTER_KEY=$(openssl rand -base64 32) GIT_REPOS_PATH=/data/repos STORAGE_DISK_ROOT=/data/storage SSH_SERVER_ENABLED=true SSH_PORT=2222 SSH_HOST_KEY_DIR=/data/ssh REGISTRATION_MODE=open EOF ) -
3 Migrate and start
The image runs as nobody, so the data volume is handed to it first. Git over SSH is on port 2222; the web side stays on localhost for the proxy below.
podman run --rm --user root -v gitgud-data:/data ggr.neiam.co/neiam/gitgud:latest chown nobody /data podman run --rm --network gitgud --env-file gitgud.env -v gitgud-data:/data ggr.neiam.co/neiam/gitgud:latest /app/bin/migrate podman run -d --restart unless-stopped --network gitgud --name gitgud --env-file gitgud.env -v gitgud-data:/data \ -p 127.0.0.1:4000:4000 -p 2222:2222 \ ggr.neiam.co/neiam/gitgud:latest -
4 Put HTTPS in front
The forge serves plain HTTP on port 4000 and expects to be reached as https://git.example.com. Any reverse proxy works; Caddy gets the certificate itself.
caddy reverse-proxy --from git.example.com --to 127.0.0.1:4000 -
5 Make yourself the admin
Register at https://git.example.com/users/register as you@example.com. With no SMTP_RELAY configured, mail is written to the log instead of sent — the sign-in link is in `podman logs gitgud`. Then:
podman exec gitgud /app/bin/git_gud eval 'GitGud.Release.promote_admin("you@example.com")' -
6 Close registration
Sign-ups were open for you. Back to the default — invite only — and restart:
sed -i '/^REGISTRATION_MODE=/d' gitgud.env && podman rm -f gitgud && \ podman run -d --restart unless-stopped --network gitgud --name gitgud --env-file gitgud.env -v gitgud-data:/data \ -p 127.0.0.1:4000:4000 -p 2222:2222 ggr.neiam.co/neiam/gitgud:latest
From here
-
Mail: set
SMTP_RELAY,SMTP_USERNAME,SMTP_PASSWORDandMAIL_FROM_ADDRESSso sign-in links reach people instead of the log — where anyone who can read it can use them. -
CI: register a
forgejo-runnerfrom a repository's or organization's Actions settings — the page has a snippet per runtime. -
Behind a proxy that isn't on a private address, set
GITGUD_TRUSTED_PROXIESso rate limits see clients rather than the proxy. - Everything else — storage backends, federation, package registries, Kubernetes — is in the README.