5.2 KiB
#+title [20jun2026] setting up container registry on forgejo
#
#
#
#
#
#
Problem
I want to setup a forgejo runner using a custom docker container. Have done something similar on github; I understand the forgejo works similarly.
See forgejo-at-digital-ocean for initial forgejo setup.
Container
We have docker-xo-builder added to xo-umbrella2 at xo-umbrella2/pkgs/docker-xo-builer.nix.
To establish nix store location:
$ cd ~/proj/xo-umbrella2
$ nix-build -A xo.docker-xo-builder
/home/roland/nixroot/nix/store/3qw6x1vhcry4v1zs18n8hcqab5mwbmjs-docker-xo-builder.tar.gz
$ ls -l $(readlink -f result)
/home/roland/nixroot/nix/store/3qw6x1vhcry4v1zs18n8hcqab5mwbmjs-docker-xo-builder.tar.gz
We will be uploading this container to docker, and pushing it to forgejo
Nginx
Configure
There's a constraint around how the container registry presents. Forgejo insists that this appears at the domain root, so containers appear under https://conybeare.us/v2/, not https://conybeare.us/git/v2 (even though forgejo itself is proxied via nginx from https://conybeare.us/git)
Additional /etc/nginx/nginx.conf setup:
http {
...
# forgejo
location /git/ { ... } # existing
# forgejo container registry
location /v2 {
client_max_body_size 0;
proxy_request_buffering off;
proxy_pass https://127.0.0.1:3000;
proxy_set_header Host $host
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Omitting the trailing slash in location /v2 causes /v2/...
to reach forgejo unaltered. This works because forgejo mounts its container-registry
at /v2 instead of at /git/v2.
Test
Ask nginx to verify configuration:
sudo bash
nix run /etc/nginx/nix@nginx -- -t
Then restart:
sudo systemctl reload nginx
Verify routing
$ curl -i https://conybeare.us/v2
HTTP/2 401
server: nginx/1.30.1
date: Sun, 21 Jun 2026 22:47:31 GMT
content-type: application/json
content-length: 50
docker-distribution-api-version: registry/2.0
www-authenticate: Bearer realm="https://conybeare.us/git/v2/token",service="container_registry",scope="*"
{"errors":[{"code":"UNAUTHORIZED","message":""}]}
Here:
- HTTP/2 401
- "who are you?"
- docker-distribution-api-version
- forgejo is answering, and it's at the root
- https://conybeare.us/git/v2/token
- tells docker where to fetch a token. Now under git
Forgejo
Create token (visit https://conybeare.us/git | Settings | Applications | Generate Token).
We need the token to have write:package permission
We need to give that token to docker:
Docker (roly-chicago-24)
(on roly-chicago-24, not vpn1):
$ docker login conybeare.us -u roland
Password: <token per forgejo above>
WARNING! Your credentials are stored unencrypted in '/home/roland/.docker/config.json'.
Configure a credential helper to remove this warning. See
https://docs.docker.com/go/credential-store/
Login Succeeded
$
Next add the docker-xo-builder image
# roly-chicago-24
$ cd ~/proj/xo-umbrella2
$ docker load < $(readlink -f result)
$ docker tag docker-xo-builder:v1 conybeare.us/roland/docker-xo-builder:v1
$ docker push conybeare.us/roland/docker-xo-builder:v1
The last step runs for a while, it has ~331MB of layers to upload.
Once this is done, we can see uploaded package here: https://conybeare.us/git/roland/-/packages
Docker (vpn1)
We want docker on vpn1 itself
# vpn1
$ sudo apt-get install docker.io
...
We also need to add the forgejo-runner account to the docker group
# vpn1
$ sudo usermod -aG docker forgejo-runner
$ sudo systemctl restart forgejo-runner
The updated forgejo-runner can open docker.sock to spawn job containers,
but we need to give it a label for our new image:
# /etc/forgejo-runner/config.yaml
runner:
labels:
- "host:host"
- "xo-builder:docker://conybeare.us/roland/docker-xo-builder:v1"
and restart
$ sudo systemctl restart forgejo-runner