detached b6b40b9

docs(readme): point links to the public mirror and drop private infrastructure details (#41)

commit
b6b40b9f456d210c09a2aa5b443e7144b080ccb7
author
brice · · 2026-10-18 15:15 UTC
committer
bnema · · 2026-10-18 15:15 UTC
parent
bdc41cd
signature
SSH UnverifiedSHA256:VOCA5lYARHcbKDZ7GhTV45VmcjWnJ6ZQIBazj17LivA The key is unknown
5 files · +13 -13
M .forgejo/workflows/ci.yml +2 -4
@@ -16,8 +16,7 @@ jobs:
1616 runs-on: ubuntu-latest
1717 steps:
1818 - uses: actions/checkout@v6
19- # Job containers reach Forgejo through the Gordon edge on the host loopback,
20- # in plain HTTP on :8088 (see vps-infra homelab/igor/ci-runner).
19+ # Job containers reach the forge over plain HTTP on the host loopback.
2120 - name: Fetch bnema.dev/ermite* modules through the runner's Forgejo route
2221 run: git config --global url."http://git.bnema.dev:8088/".insteadOf "https://git.bnema.dev/"
2322 - uses: actions/setup-go@v5
@@ -33,8 +32,7 @@ jobs:
3332 runs-on: ubuntu-latest
3433 steps:
3534 - uses: actions/checkout@v6
36- # Job containers reach Forgejo through the Gordon edge on the host loopback,
37- # in plain HTTP on :8088 (see vps-infra homelab/igor/ci-runner).
35+ # Job containers reach the forge over plain HTTP on the host loopback.
3836 - name: Fetch bnema.dev/ermite* modules through the runner's Forgejo route
3937 run: git config --global url."http://git.bnema.dev:8088/".insteadOf "https://git.bnema.dev/"
4038 - uses: actions/setup-go@v5
@@ -16,8 +16,7 @@ jobs:
16 runs-on: ubuntu-latest16 runs-on: ubuntu-latest
17 steps:17 steps:
18 - uses: actions/checkout@v618 - uses: actions/checkout@v6
19- # Job containers reach Forgejo through the Gordon edge on the host loopback,19+ # Job containers reach the forge over plain HTTP on the host loopback.
20- # in plain HTTP on :8088 (see vps-infra homelab/igor/ci-runner).
21 - name: Fetch bnema.dev/ermite* modules through the runner's Forgejo route20 - name: Fetch bnema.dev/ermite* modules through the runner's Forgejo route
22 run: git config --global url."http://git.bnema.dev:8088/".insteadOf "https://git.bnema.dev/"21 run: git config --global url."http://git.bnema.dev:8088/".insteadOf "https://git.bnema.dev/"
23 - uses: actions/setup-go@v522 - uses: actions/setup-go@v5
@@ -33,8 +32,7 @@ jobs:
33 runs-on: ubuntu-latest32 runs-on: ubuntu-latest
34 steps:33 steps:
35 - uses: actions/checkout@v634 - uses: actions/checkout@v6
36- # Job containers reach Forgejo through the Gordon edge on the host loopback,35+ # Job containers reach the forge over plain HTTP on the host loopback.
37- # in plain HTTP on :8088 (see vps-infra homelab/igor/ci-runner).
38 - name: Fetch bnema.dev/ermite* modules through the runner's Forgejo route36 - name: Fetch bnema.dev/ermite* modules through the runner's Forgejo route
39 run: git config --global url."http://git.bnema.dev:8088/".insteadOf "https://git.bnema.dev/"37 run: git config --global url."http://git.bnema.dev:8088/".insteadOf "https://git.bnema.dev/"
40 - uses: actions/setup-go@v538 - uses: actions/setup-go@v5
M README.md +6 -4
@@ -1,6 +1,8 @@
11 # ermite-runner
22
3-The CI runner of [ermite](https://git.bnema.dev/bnema/ermite). It runs workflows compatible with GitHub Actions (`.github/workflows/*.yml`), one job per sandbox:
3+> Read-only mirror. Development happens at git.bnema.dev; issues and pull requests are closed here.
4+
5+The CI runner of [ermite](https://github.com/bnema/ermite). It runs workflows compatible with GitHub Actions (`.github/workflows/*.yml`), one job per sandbox:
46
57 - **`vm`**: a Firecracker micro-VM per job, destroyed at the end. Needs `/dev/kvm`.
68 - **`container`**: a container per job with its own Docker daemon, for hosts without KVM. Uses the sysbox runtime when available, else a privileged container.
@@ -64,7 +66,7 @@ One nftables table, `inet ermite_runner`, replaced atomically (`nft -f -`) and d
6466
6567 ### Guest forge access (opt-in, staging only)
6668
67-Off by default. `ERMITE_RUNNER_GUEST_FORGE=1` lets sandboxes reach the forge **the way the runner does**, for a staging host where ermite is only reachable through an overlay (NetBird) and the runner itself uses a local route, e.g. `/etc/hosts` `ermite.bnema.dev -> 127.0.0.1` and a reverse proxy (Gordon) on `*:8088` with `ERMITE_RUNNER_URL=http://ermite.bnema.dev:8088`. Jobs otherwise cannot `git clone ${{ github.server_url }}/...`: the public URL (`https://ermite.bnema.dev`) is TLS-terminated off-host, and the private ranges are denied.
69+Off by default. `ERMITE_RUNNER_GUEST_FORGE=1` lets sandboxes reach the forge **the way the runner does**, for a staging host where ermite is only reachable through an overlay network and the runner itself uses a local route, e.g. `/etc/hosts` `forge.example -> 127.0.0.1` and a reverse proxy on `*:8088` with `ERMITE_RUNNER_URL=http://forge.example:8088`. Jobs otherwise cannot `git clone ${{ github.server_url }}/...`: the public URL (`https://forge.example`) is TLS-terminated off-host, and the private ranges are denied.
6870
6971 The host name and port come from `ERMITE_RUNNER_URL` (port defaulted from the scheme: 443 or 80). The runner **refuses to start** when the URL host is an IP literal (sandboxes are pointed at the host by DNS), when the URL has a path, when the name does not resolve on the host, or when the URL is plain `http://` without `ERMITE_RUNNER_INSECURE_HTTP=1` (same rule as for the runner itself: tokens then travel in clear). Then, for every sandbox in both modes:
7072
@@ -73,7 +75,7 @@ The host name and port come from `ERMITE_RUNNER_URL` (port defaulted from the sc
7375 - the `github.server_url`, `github.api_url` and `github.graphql_url` of the job's contexts, and so `GITHUB_SERVER_URL`, `GITHUB_API_URL` and `GITHUB_GRAPHQL_URL`, are rewritten to the origin of `ERMITE_RUNNER_URL` when their origin is the server's public one (`github.server_url`); paths are kept (`/-/github/api`). Other values, and the URLs inside `github.event`, stay as the server recorded them;
7476 - `guest forge access: sandboxes may reach <origin> on the host` is logged at start and at the start of every job, like the privileged-container warning.
7577
76-**The runner does not proxy.** The traffic reaches the host's own listener on that port, so a service must listen on it on an address the gateway reaches (`*`, as Gordon does; a listener bound to `127.0.0.1` receives nothing). A shared reverse proxy on that port routes by `Host` header, so **a job can reach every app that proxy serves on that port**, not only the forge, by sending another `Host` header: use this on staging hosts only, with a proxy whose other apps you accept to expose to job code. That traffic comes from a private address (`10.200.x.x`), so anything behind the proxy that trusts private sources (admin pages, metrics, rate-limit exemptions) trusts job code too. Jobs also see the forge over plain HTTP in that setup.
78+**The runner does not proxy.** The traffic reaches the host's own listener on that port, so a service must listen on it on an address the gateway reaches (`*`; a listener bound to `127.0.0.1` receives nothing). A shared reverse proxy on that port routes by `Host` header, so **a job can reach every app that proxy serves on that port**, not only the forge, by sending another `Host` header: use this on staging hosts only, with a proxy whose other apps you accept to expose to job code. That traffic comes from a private address (`10.200.x.x`), so anything behind the proxy that trusts private sources (admin pages, metrics, rate-limit exemptions) trusts job code too. Jobs also see the forge over plain HTTP in that setup.
7779
7880 ### Cache (GitHub Actions cache, API v1)
7981
@@ -182,7 +184,7 @@ sudo install -m 0644 contrib/ermite-runner.service /etc/systemd/system/
182184 sudo install -d -m 0700 /etc/ermite-runner
183185 sudo install -m 0600 /dev/stdin /etc/ermite-runner/env <<'ENV'
184186 ERMITE_RUNNER_URL=https://ermite.example.org
185-ERMITE_RUNNER_NAME=igor
187+ERMITE_RUNNER_NAME=runner-1
186188 ERMITE_RUNNER_LABELS=ubuntu-latest,ubuntu-24.04
187189 ERMITE_RUNNER_ISOLATION=auto
188190 ERMITE_RUNNER_CAPACITY=2
@@ -1,6 +1,8 @@
1 # ermite-runner1 # ermite-runner
2 2
3-The CI runner of [ermite](https://git.bnema.dev/bnema/ermite). It runs workflows compatible with GitHub Actions (`.github/workflows/*.yml`), one job per sandbox:3+> Read-only mirror. Development happens at git.bnema.dev; issues and pull requests are closed here.
4+
5+The CI runner of [ermite](https://github.com/bnema/ermite). It runs workflows compatible with GitHub Actions (`.github/workflows/*.yml`), one job per sandbox:
4 6
5 - **`vm`**: a Firecracker micro-VM per job, destroyed at the end. Needs `/dev/kvm`.7 - **`vm`**: a Firecracker micro-VM per job, destroyed at the end. Needs `/dev/kvm`.
6 - **`container`**: a container per job with its own Docker daemon, for hosts without KVM. Uses the sysbox runtime when available, else a privileged container.8 - **`container`**: a container per job with its own Docker daemon, for hosts without KVM. Uses the sysbox runtime when available, else a privileged container.
@@ -64,7 +66,7 @@ One nftables table, `inet ermite_runner`, replaced atomically (`nft -f -`) and d
64 66
65 ### Guest forge access (opt-in, staging only)67 ### Guest forge access (opt-in, staging only)
66 68
67-Off by default. `ERMITE_RUNNER_GUEST_FORGE=1` lets sandboxes reach the forge **the way the runner does**, for a staging host where ermite is only reachable through an overlay (NetBird) and the runner itself uses a local route, e.g. `/etc/hosts` `ermite.bnema.dev -> 127.0.0.1` and a reverse proxy (Gordon) on `*:8088` with `ERMITE_RUNNER_URL=http://ermite.bnema.dev:8088`. Jobs otherwise cannot `git clone ${{ github.server_url }}/...`: the public URL (`https://ermite.bnema.dev`) is TLS-terminated off-host, and the private ranges are denied.69+Off by default. `ERMITE_RUNNER_GUEST_FORGE=1` lets sandboxes reach the forge **the way the runner does**, for a staging host where ermite is only reachable through an overlay network and the runner itself uses a local route, e.g. `/etc/hosts` `forge.example -> 127.0.0.1` and a reverse proxy on `*:8088` with `ERMITE_RUNNER_URL=http://forge.example:8088`. Jobs otherwise cannot `git clone ${{ github.server_url }}/...`: the public URL (`https://forge.example`) is TLS-terminated off-host, and the private ranges are denied.
68 70
69 The host name and port come from `ERMITE_RUNNER_URL` (port defaulted from the scheme: 443 or 80). The runner **refuses to start** when the URL host is an IP literal (sandboxes are pointed at the host by DNS), when the URL has a path, when the name does not resolve on the host, or when the URL is plain `http://` without `ERMITE_RUNNER_INSECURE_HTTP=1` (same rule as for the runner itself: tokens then travel in clear). Then, for every sandbox in both modes:71 The host name and port come from `ERMITE_RUNNER_URL` (port defaulted from the scheme: 443 or 80). The runner **refuses to start** when the URL host is an IP literal (sandboxes are pointed at the host by DNS), when the URL has a path, when the name does not resolve on the host, or when the URL is plain `http://` without `ERMITE_RUNNER_INSECURE_HTTP=1` (same rule as for the runner itself: tokens then travel in clear). Then, for every sandbox in both modes:
70 72
@@ -73,7 +75,7 @@ The host name and port come from `ERMITE_RUNNER_URL` (port defaulted from the sc
73 - the `github.server_url`, `github.api_url` and `github.graphql_url` of the job's contexts, and so `GITHUB_SERVER_URL`, `GITHUB_API_URL` and `GITHUB_GRAPHQL_URL`, are rewritten to the origin of `ERMITE_RUNNER_URL` when their origin is the server's public one (`github.server_url`); paths are kept (`/-/github/api`). Other values, and the URLs inside `github.event`, stay as the server recorded them;75 - the `github.server_url`, `github.api_url` and `github.graphql_url` of the job's contexts, and so `GITHUB_SERVER_URL`, `GITHUB_API_URL` and `GITHUB_GRAPHQL_URL`, are rewritten to the origin of `ERMITE_RUNNER_URL` when their origin is the server's public one (`github.server_url`); paths are kept (`/-/github/api`). Other values, and the URLs inside `github.event`, stay as the server recorded them;
74 - `guest forge access: sandboxes may reach <origin> on the host` is logged at start and at the start of every job, like the privileged-container warning.76 - `guest forge access: sandboxes may reach <origin> on the host` is logged at start and at the start of every job, like the privileged-container warning.
75 77
76-**The runner does not proxy.** The traffic reaches the host's own listener on that port, so a service must listen on it on an address the gateway reaches (`*`, as Gordon does; a listener bound to `127.0.0.1` receives nothing). A shared reverse proxy on that port routes by `Host` header, so **a job can reach every app that proxy serves on that port**, not only the forge, by sending another `Host` header: use this on staging hosts only, with a proxy whose other apps you accept to expose to job code. That traffic comes from a private address (`10.200.x.x`), so anything behind the proxy that trusts private sources (admin pages, metrics, rate-limit exemptions) trusts job code too. Jobs also see the forge over plain HTTP in that setup.78+**The runner does not proxy.** The traffic reaches the host's own listener on that port, so a service must listen on it on an address the gateway reaches (`*`; a listener bound to `127.0.0.1` receives nothing). A shared reverse proxy on that port routes by `Host` header, so **a job can reach every app that proxy serves on that port**, not only the forge, by sending another `Host` header: use this on staging hosts only, with a proxy whose other apps you accept to expose to job code. That traffic comes from a private address (`10.200.x.x`), so anything behind the proxy that trusts private sources (admin pages, metrics, rate-limit exemptions) trusts job code too. Jobs also see the forge over plain HTTP in that setup.
77 79
78 ### Cache (GitHub Actions cache, API v1)80 ### Cache (GitHub Actions cache, API v1)
79 81
@@ -182,7 +184,7 @@ sudo install -m 0644 contrib/ermite-runner.service /etc/systemd/system/
182 sudo install -d -m 0700 /etc/ermite-runner184 sudo install -d -m 0700 /etc/ermite-runner
183 sudo install -m 0600 /dev/stdin /etc/ermite-runner/env <<'ENV'185 sudo install -m 0600 /dev/stdin /etc/ermite-runner/env <<'ENV'
184 ERMITE_RUNNER_URL=https://ermite.example.org186 ERMITE_RUNNER_URL=https://ermite.example.org
185-ERMITE_RUNNER_NAME=igor187+ERMITE_RUNNER_NAME=runner-1
186 ERMITE_RUNNER_LABELS=ubuntu-latest,ubuntu-24.04188 ERMITE_RUNNER_LABELS=ubuntu-latest,ubuntu-24.04
187 ERMITE_RUNNER_ISOLATION=auto189 ERMITE_RUNNER_ISOLATION=auto
188 ERMITE_RUNNER_CAPACITY=2190 ERMITE_RUNNER_CAPACITY=2
M contrib/ermite-runner.service +1 -1
@@ -13,7 +13,7 @@
1313 # in the README.
1414 [Unit]
1515 Description=ermite CI runner
16-Documentation=https://git.bnema.dev/bnema/ermite-runner
16+Documentation=https://github.com/bnema/ermite-runner
1717 Wants=network-online.target
1818 After=network-online.target docker.service
1919
@@ -13,7 +13,7 @@
13 # in the README.13 # in the README.
14 [Unit]14 [Unit]
15 Description=ermite CI runner15 Description=ermite CI runner
16-Documentation=https://git.bnema.dev/bnema/ermite-runner16+Documentation=https://github.com/bnema/ermite-runner
17 Wants=network-online.target17 Wants=network-online.target
18 After=network-online.target docker.service18 After=network-online.target docker.service
19 19
M go.mod +1 -1
@@ -4,7 +4,7 @@ go 1.27.1
44
55 require (
66 bnema.dev/ermite-actions v0.2.0
7- bnema.dev/ermite-api v0.4.0
7+ bnema.dev/ermite-api v0.5.0
88 connectrpc.com/connect v1.21.0
99 github.com/bnema/zerowrap v1.4.1
1010 github.com/containerd/errdefs v1.0.0
@@ -4,7 +4,7 @@ go 1.27.1
4 4
5 require (5 require (
6 bnema.dev/ermite-actions v0.2.06 bnema.dev/ermite-actions v0.2.0
7- bnema.dev/ermite-api v0.4.07+ bnema.dev/ermite-api v0.5.0
8 connectrpc.com/connect v1.21.08 connectrpc.com/connect v1.21.0
9 github.com/bnema/zerowrap v1.4.19 github.com/bnema/zerowrap v1.4.1
10 github.com/containerd/errdefs v1.0.010 github.com/containerd/errdefs v1.0.0
M go.sum +3 -3
@@ -1,7 +1,7 @@
1-bnema.dev/ermite-actions v0.2.0 h1:XJyGNCDfgiEv/svN7FJqSz2nX/nT2SZgYtxBAhz4e/Y=
1+bnema.dev/ermite-actions v0.2.0 h1:238UBhSZcm8RxqqjZvX3RLGKQNyKtxoXKnKIkYt4P/M=
22 bnema.dev/ermite-actions v0.2.0/go.mod h1:qoIB/Iz4xKdLUG4R6wuBDk6cemdugR+UEo5bpSJJYh4=
3-bnema.dev/ermite-api v0.4.0 h1:KEj5f0cr0qacuo9DMu4zgdKWyhjcFVb3is+gNO9hbUg=
4-bnema.dev/ermite-api v0.4.0/go.mod h1:L5smjt+IAigyAo3Ny2EnFB9IwvIGOPT1GoByZNgbDa8=
3+bnema.dev/ermite-api v0.5.0 h1:LAhstFCx4NZuJZFifuavezwue8IOENPdyS7kda4lUQU=
4+bnema.dev/ermite-api v0.5.0/go.mod h1:L5smjt+IAigyAo3Ny2EnFB9IwvIGOPT1GoByZNgbDa8=
55 buf.build/gen/go/bufbuild/bufplugin/protocolbuffers/go v1.36.12-20260722160903-4d94f3df3a7b.2 h1:z5+rVknD0AvorY/QV9cb3ohUXw4E7HvxU4+2JUH6EHU=
66 buf.build/gen/go/bufbuild/bufplugin/protocolbuffers/go v1.36.12-20260722160903-4d94f3df3a7b.2/go.mod h1:Owcuj2phVyvThVYCD74iSV8ki0dAXw/uxkdcdZScdCc=
77 buf.build/gen/go/bufbuild/protodescriptor/protocolbuffers/go v1.36.12-20250109164928-1da0de137947.2 h1:tE4A2RVukQOSd4K+6ndK+8s65FbjiBt2k5CiddXxCCo=
@@ -1,7 +1,7 @@
1-bnema.dev/ermite-actions v0.2.0 h1:XJyGNCDfgiEv/svN7FJqSz2nX/nT2SZgYtxBAhz4e/Y=1+bnema.dev/ermite-actions v0.2.0 h1:238UBhSZcm8RxqqjZvX3RLGKQNyKtxoXKnKIkYt4P/M=
2 bnema.dev/ermite-actions v0.2.0/go.mod h1:qoIB/Iz4xKdLUG4R6wuBDk6cemdugR+UEo5bpSJJYh4=2 bnema.dev/ermite-actions v0.2.0/go.mod h1:qoIB/Iz4xKdLUG4R6wuBDk6cemdugR+UEo5bpSJJYh4=
3-bnema.dev/ermite-api v0.4.0 h1:KEj5f0cr0qacuo9DMu4zgdKWyhjcFVb3is+gNO9hbUg=3+bnema.dev/ermite-api v0.5.0 h1:LAhstFCx4NZuJZFifuavezwue8IOENPdyS7kda4lUQU=
4-bnema.dev/ermite-api v0.4.0/go.mod h1:L5smjt+IAigyAo3Ny2EnFB9IwvIGOPT1GoByZNgbDa8=4+bnema.dev/ermite-api v0.5.0/go.mod h1:L5smjt+IAigyAo3Ny2EnFB9IwvIGOPT1GoByZNgbDa8=
5 buf.build/gen/go/bufbuild/bufplugin/protocolbuffers/go v1.36.12-20260722160903-4d94f3df3a7b.2 h1:z5+rVknD0AvorY/QV9cb3ohUXw4E7HvxU4+2JUH6EHU=5 buf.build/gen/go/bufbuild/bufplugin/protocolbuffers/go v1.36.12-20260722160903-4d94f3df3a7b.2 h1:z5+rVknD0AvorY/QV9cb3ohUXw4E7HvxU4+2JUH6EHU=
6 buf.build/gen/go/bufbuild/bufplugin/protocolbuffers/go v1.36.12-20260722160903-4d94f3df3a7b.2/go.mod h1:Owcuj2phVyvThVYCD74iSV8ki0dAXw/uxkdcdZScdCc=6 buf.build/gen/go/bufbuild/bufplugin/protocolbuffers/go v1.36.12-20260722160903-4d94f3df3a7b.2/go.mod h1:Owcuj2phVyvThVYCD74iSV8ki0dAXw/uxkdcdZScdCc=
7 buf.build/gen/go/bufbuild/protodescriptor/protocolbuffers/go v1.36.12-20250109164928-1da0de137947.2 h1:tE4A2RVukQOSd4K+6ndK+8s65FbjiBt2k5CiddXxCCo=7 buf.build/gen/go/bufbuild/protodescriptor/protocolbuffers/go v1.36.12-20250109164928-1da0de137947.2 h1:tE4A2RVukQOSd4K+6ndK+8s65FbjiBt2k5CiddXxCCo=

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 4

Tags 11

↑↓ moveenter openesc close