find the push button tailnet airgap mode #419

Closed
opened 2026-06-26 16:00:54 +00:00 by coilysiren · 0 comments
Owner

Kai's note: find the push button tailnet airgap mode. I am 100% certain tailscale provides this. (see also #418)

Goal (stated precisely so the goose does not chase the wrong feature)

A one-flip mode where a chosen dev device can reach only tailnet peers and not the public internet, to force/prove airgapped dev. The goose must name the exact Tailscale mechanism, rule out the look-alikes below, and implement the toggle in this repo's Tailscale-as-code.

Candidate mechanisms (research against current tailscale.com docs and confirm)

  • MOST LIKELY - ACL egress restriction via autogroup:internet. Public-internet egress through Tailscale is governed by ACL grants to exit nodes / autogroup:internet. Define a tag:airgap, and write an ACL grant that lets tag:airgap reach only tailnet destinations (other tags / tailnet CIDRs) and explicitly not autogroup:internet. Flipping airgap = tag the device tag:airgap and apply. This is the "push button."
  • RED HERRING - tailscale up --shields-up. Blocks incoming connections only. Airgap is about outgoing egress, so this is NOT it - call it out so the next person does not waste time.
  • RED HERRING - Tailnet Lock. Cryptographic node-admission control, not egress airgap.
  • HEAVIER ALT - force-all-egress through an exit node that itself has no internet. Works but is not a clean one-flip and adds an exit-node dependency.

Implementation (this repo already manages Tailscale as code)

  • ACL policy lives in terraform/tailscale/main.tf as the tailscale_acl.policy resource (jsonencode'd - one source of truth). Device tags live in terraform/tailscale/devices.yaml (existing tags: tag:kais-macbook-pro, tag:kai-tower-3026, ...).
  • Add a tag:airgap and the tailnet-only grant to the ACL, apply with ward terraform-tailscale action=apply (verb in .ward/ward.yaml; dump current policy with ward dump-tailscale-acl).
  • Document the toggle in docs/tailnet-airgap.md: how to put a device into airgap (add tag:airgap, apply) and take it out, plus a connectivity test (tailnet peer reachable, curl https://example.com fails).

Honest caveat the doc MUST state

The Tailscale control plane is itself public SaaS - coordination/key exchange still traverses the internet. So an ACL airgap restricts data egress, not the control channel. Full control-plane airgap needs Headscale (a separate, larger effort). Do not overclaim "fully airgapped."

Acceptance

  • docs/tailnet-airgap.md names the exact Tailscale feature, rules out the red herrings, and states the control-plane caveat.
  • A tag:airgap + tailnet-only ACL grant implemented in terraform/tailscale/, applied and verified (ward dump-tailscale-acl shows it; an airgap-tagged device reaches tailnet peers but not the public internet).

Files

terraform/tailscale/main.tf, terraform/tailscale/devices.yaml, new docs/tailnet-airgap.md. Related: #418 (audit), #417 (secrets airgap).

> **Kai's note:** find the push button tailnet airgap mode. I am 100% certain tailscale provides this. (see also #418) ## Goal (stated precisely so the goose does not chase the wrong feature) A one-flip mode where a chosen dev device can reach **only tailnet peers** and **not the public internet**, to force/prove airgapped dev. The goose must name the exact Tailscale mechanism, **rule out the look-alikes below**, and implement the toggle in this repo's Tailscale-as-code. ## Candidate mechanisms (research against current tailscale.com docs and confirm) - **MOST LIKELY - ACL egress restriction via `autogroup:internet`.** Public-internet egress through Tailscale is governed by ACL grants to exit nodes / `autogroup:internet`. Define a `tag:airgap`, and write an ACL grant that lets `tag:airgap` reach **only** tailnet destinations (other tags / tailnet CIDRs) and explicitly **not** `autogroup:internet`. Flipping airgap = tag the device `tag:airgap` and apply. This is the "push button." - **RED HERRING - `tailscale up --shields-up`.** Blocks **incoming** connections only. Airgap is about **outgoing** egress, so this is NOT it - call it out so the next person does not waste time. - **RED HERRING - Tailnet Lock.** Cryptographic node-admission control, not egress airgap. - **HEAVIER ALT - force-all-egress through an exit node** that itself has no internet. Works but is not a clean one-flip and adds an exit-node dependency. ## Implementation (this repo already manages Tailscale as code) - ACL policy lives in `terraform/tailscale/main.tf` as the `tailscale_acl.policy` resource (jsonencode'd - one source of truth). Device tags live in `terraform/tailscale/devices.yaml` (existing tags: `tag:kais-macbook-pro`, `tag:kai-tower-3026`, ...). - Add a `tag:airgap` and the tailnet-only grant to the ACL, apply with `ward terraform-tailscale action=apply` (verb in `.ward/ward.yaml`; dump current policy with `ward dump-tailscale-acl`). - Document the toggle in `docs/tailnet-airgap.md`: how to put a device into airgap (add `tag:airgap`, apply) and take it out, plus a connectivity test (tailnet peer reachable, `curl https://example.com` fails). ## Honest caveat the doc MUST state The Tailscale **control plane is itself public SaaS** - coordination/key exchange still traverses the internet. So an ACL airgap restricts **data egress**, not the control channel. Full control-plane airgap needs **Headscale** (a separate, larger effort). Do not overclaim "fully airgapped." ## Acceptance - `docs/tailnet-airgap.md` names the exact Tailscale feature, rules out the red herrings, and states the control-plane caveat. - A `tag:airgap` + tailnet-only ACL grant implemented in `terraform/tailscale/`, applied and verified (`ward dump-tailscale-acl` shows it; an airgap-tagged device reaches tailnet peers but not the public internet). ## Files `terraform/tailscale/main.tf`, `terraform/tailscale/devices.yaml`, new `docs/tailnet-airgap.md`. Related: #418 (audit), #417 (secrets airgap).
Sign in to join this conversation.
No description provided.