[network.tailscale] to floo.app.toml and every runtime of the app joins your tailnet: web and API services, workers, cron jobs, and the migration command. Your Dockerfile and start command do not change.
partial
auth_key_secretnames the floo secret that holds a Tailscale auth key.forwardlistshost:porttargets on your tailnet. Each one listens onlocalhost:<port>inside your app, with the same port.
Set it up
-
In the Tailscale admin console, open Settings → Keys and generate an auth key with Reusable and Ephemeral on. Give it a tag, such as
tag:floo. -
Store the key as a secret in each environment that declares the block. Copy the key, then run:
On Linux, replace
pbpastewithxclip -o -selection clipboard. Repeat with--env prodbefore you release. -
Add the
[network.tailscale]block, commit, and push.
floo-my-app-dev-web-ccc67a), and leaves the tailnet when the instance stops.
Connect from your code
A forward is a local TCP port. Point any client at127.0.0.1 and the forwarded port, and keep the database password in a secret:
FLOO_TAILNET_PROXY (http://localhost:1056). It supports CONNECT and absolute-form HTTP requests, not SOCKS5. floo does not set HTTP_PROXY or HTTPS_PROXY, so only requests you send through the proxy use the tailnet:
Limit what the app can reach
The app gets whatever access your tailnet ACLs give the key’s tag. Granttag:floo only the hosts and ports the app needs:
Ports and resources
A forward cannot use these ports or a port one of your services listens on. The deploy fails validation with the conflicting entry named.
The sidecar adds 0.5 vCPU and 256 MiB to every instance, on top of your service’s size.
Preview environments run pull-request code, so they do not join the tailnet and do not receive the auth key.
When the tailnet is down
Your app starts only after its instance joins the tailnet. If the join fails, the deploy or migration fails with The app could not join its tailnet and Tailscale’s reason, such asinvalid key. Your code did not fail. Replace the key, then run:
--rebuild builds your default branch, which declares the tailnet. A plain floo redeploy restarts the last live build. If that build predates your [network.tailscale] block, the deploy goes live without trying the new key.
When a host is unreachable after startup, the sidecar logs floo-tailnet: TAILNET_DIAL_FAILED <host:port>. Through the proxy, the request answers 502 with the header X-Floo-Tailnet: unreachable, so your code can tell a tailnet failure from an error in the upstream service.