diff --git a/README.md b/README.md index 68e21ac..68b22fa 100644 --- a/README.md +++ b/README.md @@ -379,6 +379,22 @@ so reviewers read the pre-fixup code and no interdiff exists — with no warning push itself succeeded. Always: push, resubmit, then reply with the printed interdiff URL. See `machine-docs/PR-WORKFLOW.md`, "A push does NOT advance the round". +## The testing gateway — public domains for tailnet boxes + +A box on the tailnet with no public IP can still have a real HTTPS domain: the shared testing +gateway holds a wildcard record for `*.gtest.commoninternet.net` and forwards by SNI. + +```bash +python3 engine/tools/gateway-domain.py add myapp # -> myapp.gtest.commoninternet.net -> this box +python3 engine/tools/gateway-domain.py list +python3 engine/tools/gateway-domain.py remove myapp +``` + +The admin password is `gateway.admin_password` in the secret store below; the tool reads it +itself. **The gateway does not terminate TLS** — it proxies the encrypted stream, so your box +serves the certificate for that name. Full detail, including how to get a cert and why hostname +backends are refused, is in the `gateway-domain` skill (`skills/gateway-domain/SKILL.md`). + ## Secrets — one encrypted store, never in git **Every credential on an orchestrator host lives in one sops+age encrypted file. Do not put a diff --git a/skills/gateway-domain/SKILL.md b/skills/gateway-domain/SKILL.md new file mode 100644 index 0000000..e58eb52 --- /dev/null +++ b/skills/gateway-domain/SKILL.md @@ -0,0 +1,129 @@ +--- +name: gateway-domain +description: Give a tailnet box a real public HTTPS domain (.gtest.commoninternet.net) by mapping it on the shared testing gateway. Use when an agent needs a publicly reachable URL for a box with no public IP — an OAuth callback, a webhook receiver, a demo link, an ACME challenge. Covers the add/remove tool, where the admin password lives, and the traps (your box serves the TLS cert, not the gateway; hostname backends are unremovable). +--- + +# Giving your box a public domain + +Your machine is on the tailnet with no public IP. You need a real HTTPS URL for it. The +**testing gateway** already owns a wildcard DNS record, so every name under +`*.gtest.commoninternet.net` resolves to it. Map your name to your tailnet IP and it forwards +matching traffic to you. + +```bash +python3 engine/tools/gateway-domain.py add myapp +# myapp.gtest.commoninternet.net -> 100.84.190.30 +``` + +That is the whole happy path. The backend defaults to **this box's own tailscale IP**, so run +it on the machine that will serve the domain. + +```bash +python3 engine/tools/gateway-domain.py list +python3 engine/tools/gateway-domain.py add myapp # this box, port 443 +python3 engine/tools/gateway-domain.py add myapp 100.64.1.5 # another box +python3 engine/tools/gateway-domain.py add myapp 100.64.1.5:8443 # backend not on 443 +python3 engine/tools/gateway-domain.py remove myapp +``` + +A bare label is expanded to `