Commit 9467ed29d6
9467ed29d693e590e8e037c8858eeb793f21f029
parent: 9809a86bfc
Verified · cmc
cmc <hello@cleberg.net> · 2026-09-28 07:31 UTC
runner egress: remove the rule when it blocks the runner's poll
Ref #260
Layout: unified · split
deploy/gitbay-runner-egress.nft
+4 −3
| @@ -20,9 +20,10 @@ |
| 20 | 20 | # 127.0.0.1:22 the forge over loopback, for the runner. Builds do |
| 21 | 21 | # not reach loopback at all: the runner starts them |
| 22 | 22 | # with pasta's gateway mapping off (--no-map-gw). |
| 23 | | # loopback :53 the host's resolver, which pasta forwards a |
| 24 | | # build's DNS to when the host's nameserver is a |
| 25 | | # loopback address. |
| 23 | # loopback :53 the host's resolver, for when the host's nameserver |
| 24 | # is a loopback address. That pasta forwards a |
| 25 | # build's DNS there is to be confirmed from inside a |
| 26 | # build by runbook R3, not assumed. |
| 26 | 27 | # public 22/80/443 the forge, as anyone on the internet reaches it. |
| 27 | 28 | # Everything else is rejected: the admin sshd on 2222 on every address, |
| 28 | 29 | # and any service bound to loopback. -isolation none builds run as the |
deploy/gitbay-runner-egress.service
+4 −1
| @@ -10,6 +10,9 @@ |
| 10 | 10 | # Reload re-reads the file and replaces the table in one transaction; it |
| 11 | 11 | # does not restart the runner, which a restart of this unit would |
| 12 | 12 | # (Requires= propagates restarts). `make deploy-runner` reloads. |
| 13 | # |
| 14 | # Stop uses destroy, which succeeds when the table is already gone (a |
| 15 | # flush ruleset removes it); delete would fail and leave the unit failed. |
| 13 | 16 | [Unit] |
| 14 | 17 | Description=Host egress rule for CI builds |
| 15 | 18 | After=nftables.service ufw.service |
| @@ -20,7 +23,7 @@ Type=oneshot |
| 20 | 23 | RemainAfterExit=yes |
| 21 | 24 | ExecStart=/usr/sbin/nft -f /etc/gitbay-runner/egress.nft |
| 22 | 25 | ExecReload=/usr/sbin/nft -f /etc/gitbay-runner/egress.nft |
| 23 | | ExecStop=/usr/sbin/nft delete table inet gitbay_runner |
| 26 | ExecStop=/usr/sbin/nft destroy table inet gitbay_runner |
| 24 | 27 | |
| 25 | 28 | [Install] |
| 26 | 29 | WantedBy=multi-user.target |
deploy/runner-egress-check.sh
+14 −7
| @@ -14,17 +14,24 @@ RUNNER_USER="${RUNNER_USER:-ci-runner}" |
| 14 | 14 | public=$(hostname -I | awk '{print $1}') |
| 15 | 15 | |
| 16 | 16 | probe() { |
| 17 | | su -s /bin/bash "$RUNNER_USER" -c "timeout 5 bash -c 'exec 3<>/dev/tcp/$1/$2'" 2>/dev/null |
| 17 | su -s /bin/bash "$RUNNER_USER" -c "timeout 5 bash -c 'exec 3<>/dev/tcp/$1/$2'" </dev/null 2>/dev/null |
| 18 | 18 | } |
| 19 | 19 | |
| 20 | 20 | nft list table inet gitbay_runner >/dev/null |
| 21 | 21 | |
| 22 | | for dest in 127.0.0.1:22 "$public:22"; do |
| 23 | | if ! probe "${dest%:*}" "${dest##*:}"; then |
| 24 | | echo "$RUNNER_USER cannot reach $dest: the egress rule would stop the runner" >&2 |
| 25 | | exit 1 |
| 26 | | fi |
| 27 | | done |
| 22 | # The runner polls 127.0.0.1:22. If the rule blocks that, the running |
| 23 | # runner is already cut off, so remove the table: CI keeps polling as it |
| 24 | # did before the deploy, and the exit still stops make before the restart. |
| 25 | if ! probe 127.0.0.1 22; then |
| 26 | nft destroy table inet gitbay_runner |
| 27 | echo "$RUNNER_USER cannot reach 127.0.0.1:22 with the egress rule loaded;" >&2 |
| 28 | echo "removed table inet gitbay_runner so the runner keeps polling. Fix the rule and deploy again." >&2 |
| 29 | exit 1 |
| 30 | fi |
| 31 | if ! probe "$public" 22; then |
| 32 | echo "$RUNNER_USER cannot reach $public:22: builds would not reach the forge" >&2 |
| 33 | exit 1 |
| 34 | fi |
| 28 | 35 | for dest in 127.0.0.1:2222 "$public:2222"; do |
| 29 | 36 | if probe "${dest%:*}" "${dest##*:}"; then |
| 30 | 37 | echo "$RUNNER_USER reaches $dest: the egress rule is not in force" >&2 |