dev-base: add tailscale CLI + default AWS region us-east-1 (unblocks tower access from agent containers) #286

Closed
opened 2026-06-25 11:23:00 +00:00 by coilysiren · 2 comments
Owner

A warded explore session on agent-proxy cannot reach the tower (kai-tower-3026 ollama on the tailnet), which gates the M1 reliability-proxy benchmark (the first build-ready milestone). Two pieces are missing from the dev-base image (docker/dev-base/Dockerfile):

  1. No tailscale CLI - tailscale: command not found. The image ships node/go/aws/codex/goose/docker but no tailnet client, so an agent container cannot query tailnet status or route to the tower over the tailnet.
  2. No default AWS region - aws and ward ops aws ssm ... fail with NoRegion, so the tower FQDN at SSM /coilysiren/kai-tower-3026/tailnet-fqdn cannot be resolved even when creds are present.

Asks

  • Add a pinned tailscale CLI install to docker/dev-base/Dockerfile, arch-mapped exactly like the existing tools (amd64 -> amd64, arm64 -> arm64), from the static tarball https://pkgs.tailscale.com/stable/tailscale_${TAILSCALE_VERSION}_${ARCH}.tgz, extracting the tailscale client binary to /usr/local/bin and chmod 0755. Add a TAILSCALE_VERSION ARG up with the other pinned-toolchain ARGs so dep-bump.yml can auto-bump it. End the RUN with tailscale version as the smoke check.
  • Set AWS_DEFAULT_REGION=us-east-1 and AWS_REGION=us-east-1 in the Dockerfile ENV block.
  • Push to main so the publish-image job in .forgejo/workflows/release.yml rebuilds and republishes dev-base:latest.

Scope note

This only makes the CLI and the region default exist in the image. It deliberately does not provision tailnet auth or AWS credentials into the container - those are separate axes. Region default alone does not grant SSM access without creds, and the tailscale binary alone does not bring up the tailnet. The goal here is that a credentialed/authed container stops failing on a missing binary and a missing region.

Verify

  • tailscale version resolves in a fresh container off the rebuilt image.
  • aws configure get region (or the AWS_DEFAULT_REGION env) shows us-east-1.
  • aws ssm get-parameter ... (with creds) no longer errors with NoRegion.

Surfaced from a read-only warded explore session on agent-proxy; both gaps block the M1 tower benchmark.

A `warded explore` session on `agent-proxy` cannot reach the tower (`kai-tower-3026` ollama on the tailnet), which gates the M1 reliability-proxy benchmark (the first build-ready milestone). Two pieces are missing from the dev-base image (`docker/dev-base/Dockerfile`): 1. **No `tailscale` CLI** - `tailscale: command not found`. The image ships node/go/aws/codex/goose/docker but no tailnet client, so an agent container cannot query tailnet status or route to the tower over the tailnet. 2. **No default AWS region** - `aws` and `ward ops aws ssm ...` fail with `NoRegion`, so the tower FQDN at SSM `/coilysiren/kai-tower-3026/tailnet-fqdn` cannot be resolved even when creds are present. ## Asks - Add a pinned `tailscale` CLI install to `docker/dev-base/Dockerfile`, arch-mapped exactly like the existing tools (amd64 -> amd64, arm64 -> arm64), from the static tarball `https://pkgs.tailscale.com/stable/tailscale_${TAILSCALE_VERSION}_${ARCH}.tgz`, extracting the `tailscale` client binary to `/usr/local/bin` and `chmod 0755`. Add a `TAILSCALE_VERSION` ARG up with the other pinned-toolchain ARGs so `dep-bump.yml` can auto-bump it. End the RUN with `tailscale version` as the smoke check. - Set `AWS_DEFAULT_REGION=us-east-1` and `AWS_REGION=us-east-1` in the Dockerfile ENV block. - Push to `main` so the `publish-image` job in `.forgejo/workflows/release.yml` rebuilds and republishes `dev-base:latest`. ## Scope note This only makes the CLI and the region default **exist** in the image. It deliberately does **not** provision tailnet auth or AWS credentials into the container - those are separate axes. Region default alone does not grant SSM access without creds, and the `tailscale` binary alone does not bring up the tailnet. The goal here is that a credentialed/authed container stops failing on a missing binary and a missing region. ## Verify - `tailscale version` resolves in a fresh container off the rebuilt image. - `aws configure get region` (or the `AWS_DEFAULT_REGION` env) shows `us-east-1`. - `aws ssm get-parameter ...` (with creds) no longer errors with `NoRegion`. Surfaced from a read-only `warded explore` session on `agent-proxy`; both gaps block the M1 tower benchmark.
Author
Owner

🔒 Reserved by ward agent --driver claude — container ward-agentic-os-issue-286-claude-a000211b on host docker-desktop is carrying this issue (reserved 2026-06-25T11:23:04Z). Concurrent ward agent runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); --force overrides.

— Claude (she/her), via ward agent

<!-- ward-agent-reservation --> 🔒 Reserved by `ward agent --driver claude` — container `ward-agentic-os-issue-286-claude-a000211b` on host `docker-desktop` is carrying this issue (reserved 2026-06-25T11:23:04Z). Concurrent `ward agent` runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); `--force` overrides. <!-- ward-agent-signature --> — Claude (she/her), via `ward agent`
Author
Owner

Retrospective, in my own voice:

This one felt clean. The Dockerfile already had a tidy pattern for every pinned tool (arch-map once into /tmp/arch.env, then a per-tool RUN), so tailscale slotted in by copying docker's shape almost verbatim - I just confirmed the static tarball lays out as tailscale_<ver>_<arch>/tailscale and used --strip-components=1 to lift only the client binary. Tailscale's arch spelling happens to match TARGETARCH (amd64/arm64), so the mapping was a no-op, but I added a TS_ARCH entry anyway to stay consistent with the existing tools rather than special-casing.

The one thing that fought back was the documentation-layout 4000-char cap on docs/dev-base-image.md - my two bullets tipped it over, and I ended up trimming pre-existing prose to land it at exactly 4000. Slightly uncomfortable editing unrelated lines to make room, but the result reads tighter, not worse.

Confidence is high on the region default (pure ENV) and the dep-bump resolver (verified it resolves 1.98.4 against the stable feed, matching the pin). The tailscale install I verified by extracting and running the real binary locally, but I did NOT do a full multi-arch docker build - the arm64 leg only really exercises in CI's buildx run. If anything bites, that's where it'd be.

Follow-ups worth noting, none blocking: this only makes the binary and region exist per the scope note, so the actual M1 tower benchmark still needs tailnet auth + AWS creds wired by ward before it's truly unblocked. Watch the next publish-image run to confirm :latest actually republishes.

Retrospective, in my own voice: This one felt clean. The Dockerfile already had a tidy pattern for every pinned tool (arch-map once into /tmp/arch.env, then a per-tool RUN), so tailscale slotted in by copying docker's shape almost verbatim - I just confirmed the static tarball lays out as `tailscale_<ver>_<arch>/tailscale` and used `--strip-components=1` to lift only the client binary. Tailscale's arch spelling happens to match TARGETARCH (amd64/arm64), so the mapping was a no-op, but I added a TS_ARCH entry anyway to stay consistent with the existing tools rather than special-casing. The one thing that fought back was the documentation-layout 4000-char cap on docs/dev-base-image.md - my two bullets tipped it over, and I ended up trimming pre-existing prose to land it at exactly 4000. Slightly uncomfortable editing unrelated lines to make room, but the result reads tighter, not worse. Confidence is high on the region default (pure ENV) and the dep-bump resolver (verified it resolves 1.98.4 against the stable feed, matching the pin). The tailscale install I verified by extracting and running the real binary locally, but I did NOT do a full multi-arch docker build - the arm64 leg only really exercises in CI's buildx run. If anything bites, that's where it'd be. Follow-ups worth noting, none blocking: this only makes the binary and region *exist* per the scope note, so the actual M1 tower benchmark still needs tailnet auth + AWS creds wired by ward before it's truly unblocked. Watch the next `publish-image` run to confirm `:latest` actually republishes.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
coilyco-flight-deck/agentic-os#286
No description provided.