Builds no longer share the runner's source address, and on the runner's host they reach only the forge's public ports.
runner nextsendsssh:git@<site host>, orgit@<host>:<port>when[ssh] portis not 22. The runner uses it for the build'sGITBAY_SSH(falls back to its own-remoteagainst an older server).ssh://$GITBAY_SSH/...stays valid in both forms.- A runner that polls over loopback starts podman builds with
--network pasta:--no-map-gw, so builds have no path to the host's loopback and no longer arrive from the runner's address. deploy/gitbay-runner-egress.nft(tableinet gitbay_runner, unitgitbay-runner-egress.service, required by the runner): ci-runner's traffic to the host's own addresses may reach 127.0.0.1:22, loopback DNS and public 22/80/443; 2222 and everything else on the host are rejected. Outbound internet is unchanged.make deploy-runnerchecks the rule withnft -c, reloads it, then probes as ci-runner. If the runner's own 127.0.0.1:22 is blocked it removes the table and stops before restarting the runner.- An sshd test pins the limiter: with registration open, unknown keys never count, so a build cannot lock the runner out on gitbay.org.
- Threat-Model, CI, Users, Admin and Architecture pages; CHANGELOG.
Do not deploy the runner half until runbook R3 passes from inside a scratch build (plan docs/plans/2026-09-27-ci-trust-and-build-reporting.md, R3): under pasta with --no-map-gw the host's public address may be the container's own, so ssh -T $GITBAY_SSH (which hutch and orgo publish over) and DNS must be checked inside a build, along with 2222 and 127.0.0.1 being refused. Deploy gitbayd first.
Stacked on !482. #260 closes when the R3 measurement is recorded on the CI page.
Ref #260