@@ -59,7 +59,6 @@ shithub_runner_default_image=ghcr.io/shithub/runner-nix:1.0 |
| 59 | shithub_runner_seccomp_profile=/etc/shithubd-runner/seccomp.json | 59 | shithub_runner_seccomp_profile=/etc/shithubd-runner/seccomp.json |
| 60 | shithub_runner_container_user=65534:65534 | 60 | shithub_runner_container_user=65534:65534 |
| 61 | shithub_runner_pids_limit=512 | 61 | shithub_runner_pids_limit=512 |
| 62 | -shithub_runner_dns_servers=172.30.0.1 | | |
| 63 | ``` | 62 | ``` |
| 64 | | 63 | |
| 65 | The role writes non-secret config to | 64 | The role writes non-secret config to |
@@ -70,9 +69,10 @@ the systemd unit grants runner writes only to that subtree. |
| 70 | | 69 | |
| 71 | `shithub_runner_network_allowlist` defaults to GitHub source/archive | 70 | `shithub_runner_network_allowlist` defaults to GitHub source/archive |
| 72 | hosts plus Docker Hub registry hosts. Override it when a runner must | 71 | hosts plus Docker Hub registry hosts. Override it when a runner must |
| 73 | -fetch from an internal package registry. `shithub_runner_dns_servers` | 72 | +fetch from an internal package registry. The role creates the |
| 74 | -is empty by default; set it only after a DNS allowlist resolver exists | 73 | +`shithub-actions` Docker bridge at `172.30.0.1/24`, runs dnsmasq on |
| 75 | -on the runner network. | 74 | +that bridge, and sets `engine.dns_servers` to the bridge resolver by |
| | 75 | +default. |
| 76 | | 76 | |
| 77 | ## Deploy | 77 | ## Deploy |
| 78 | | 78 | |
@@ -89,8 +89,12 @@ The role: |
| 89 | - creates the `shithub-runner` system user and joins it to `docker` | 89 | - creates the `shithub-runner` system user and joins it to `docker` |
| 90 | - uploads `/usr/local/bin/shithubd-runner` | 90 | - uploads `/usr/local/bin/shithubd-runner` |
| 91 | - renders `/etc/shithubd-runner/config.toml` and `runner.env` | 91 | - renders `/etc/shithubd-runner/config.toml` and `runner.env` |
| 92 | -- renders `/etc/shithubd-runner/dnsmasq.conf` from the network | 92 | +- creates the dedicated Actions Docker network and bridge |
| 93 | - allowlist for operators who run a local DNS allowlist resolver | 93 | +- renders `/etc/dnsmasq.d/shithubd-runner.conf` from the network |
| | 94 | + allowlist and starts dnsmasq bound to the Actions bridge |
| | 95 | +- installs `shithub-runner-firewall.service`, which rejects direct-IP |
| | 96 | + egress from step containers unless dnsmasq populated the destination |
| | 97 | + in the allowlist ipset |
| 94 | - installs the pinned seccomp profile at | 98 | - installs the pinned seccomp profile at |
| 95 | `/etc/shithubd-runner/seccomp.json` | 99 | `/etc/shithubd-runner/seccomp.json` |
| 96 | - installs `deploy/systemd/shithubd-runner.service` | 100 | - installs `deploy/systemd/shithubd-runner.service` |
@@ -147,6 +151,9 @@ jobs: |
| 147 | Expected state: | 151 | Expected state: |
| 148 | | 152 | |
| 149 | - the UID check prints `65534` | 153 | - the UID check prints `65534` |
| | 154 | +- a workflow-level request for `permissions: {shithub-runner-root: write}` |
| | 155 | + still runs as `65534`; root opt-in is disabled in the shipped runner |
| | 156 | + config until a trusted-workflow policy exists |
| 150 | - writing under `/etc` fails because the root filesystem is read-only | 157 | - writing under `/etc` fails because the root filesystem is read-only |
| 151 | - `mount` fails because the container does not have `CAP_SYS_ADMIN` | 158 | - `mount` fails because the container does not have `CAP_SYS_ADMIN` |
| 152 | - step logs and systemd journal include the configured image, network, | 159 | - step logs and systemd journal include the configured image, network, |
@@ -162,16 +169,16 @@ The runner config carries two separate network controls: |
| 162 | Docker `--dns`. | 169 | Docker `--dns`. |
| 163 | | 170 | |
| 164 | For a single-host deployment, create a dedicated Docker bridge for | 171 | For a single-host deployment, create a dedicated Docker bridge for |
| 165 | -Actions jobs, run dnsmasq bound to that bridge, render | 172 | +Actions jobs, run dnsmasq bound to that bridge, and set |
| 166 | -`/etc/shithubd-runner/dnsmasq.conf`, and set | | |
| 167 | `shithub_runner_dns_servers` to the bridge address of that resolver. | 173 | `shithub_runner_dns_servers` to the bridge address of that resolver. |
| 168 | -The rendered dnsmasq config has no default upstream resolver; names not | 174 | +The Ansible role now does this by default. The rendered dnsmasq config |
| 169 | -matching the allowlist fail DNS resolution. | 175 | +has no default upstream resolver; names not matching the allowlist fail |
| 170 | - | 176 | +DNS resolution. |
| 171 | -DNS filtering is not a complete egress boundary by itself. Block | 177 | + |
| 172 | -direct-IP egress from the Actions bridge with host firewall rules, and | 178 | +The firewall service closes the direct-IP bypass: containers on the |
| 173 | -allow only DNS to the resolver plus established outbound connections | 179 | +Actions subnet may send DNS only to the bridge resolver, and other |
| 174 | -opened by that resolver. Keep the runner on a separate host from web | 180 | +egress is allowed only when the destination IP is present in the |
| | 181 | +dnsmasq-populated ipset. Keep the runner on a separate host from web |
| 175 | and database services. | 182 | and database services. |
| 176 | | 183 | |
| 177 | ## Rollback | 184 | ## Rollback |