A session running in an environment with Tailscale reaches the same private services your team reaches: an internal API, a staging database, anything behind a subnet router.
Each computer joins your tailnet as a tag-owned, ephemeral node. Your access control policy decides what it reaches. Tailscale removes the node about an hour after it goes offline.
A session suspends when it’s been idle, which takes its computer offline. A session suspended for long enough loses its node and rejoins your tailnet with a new address when it resumes.
Requirements
- Owner, Admin, IT admin, or Network admin access to your tailnet.
- An environment for the repository your sessions run in.
Prepare your tailnet
Create a tag
Add tag:indent to tagOwners in your access control
policy.
"tagOwners": {
"tag:indent": ["autogroup:admin"],
},Grant the tag access
A computer reaches nothing until a grant names its tag.
"grants": [
{
"src": ["tag:indent"],
"dst": ["tag:staging"],
"ip": ["tcp:443", "tcp:5432"],
},
],Create an OAuth credential
On the Trust credentials page,
generate an OAuth credential with Keys → Auth Keys → Write and the tag tag:indent.
Copy the client secret. Tailscale shows it once.
An OAuth client secret doesn’t expire. An auth key expires after at most 90 days.
Configure the environment
Open the environment from Settings → Environments and select the Configure step.
Ask Indent to install Tailscale
Indent writes the Dockerfile, so ask it to install Tailscale from tailscale.com/install.sh. The
Dockerfile gains a line like this one:
RUN curl -fsSL https://tailscale.com/install.sh | shThe Tailscale daemon starts when the computer boots.
Add the client secret to Runtime variables
Select Add variable, enter TS_AUTHKEY as the key, and paste the client secret as the value.
Indent sees the key, never the value.
Use Runtime variables rather than Environment variables. The latter applies to the build, and the secret is needed while the computer is running.
Add a process that joins the tailnet
Under Processes, select Add process, name it tailscale, and set its Command to:
while true; do sudo tailscale status >/dev/null 2>&1 || sudo tailscale up --auth-key="${TS_AUTHKEY}?ephemeral=true&preauthorized=true" --advertise-tags=tag:indent --hostname="indent-${COMPUTER_ID}" --accept-routes --shields-up; sleep 30; doneephemeral=true registers a node that Tailscale removes on its own. preauthorized=true skips
device approval. --shields-up blocks inbound connections, so the computer reaches your tailnet and
your tailnet does not reach the computer. --accept-routes picks up the routes your subnet routers
advertise. Names resolve through MagicDNS when your tailnet has it enabled.
COMPUTER_ID is set on every computer, so each node gets its own name. The loop rejoins the tailnet
after a suspension long enough to have removed the node.
Confirm it works
Select Build + Verify, then Publish. Start a session in the environment and ask Indent to
run tailscale status, or to reach one of the services you granted. The node appears on your
Machines page as indent-<computer id>.
Revoke access
Revoke the credential on the
Trust credentials page to stop new
computers from joining. Computers already on your tailnet keep their access. Delete their nodes on
the Machines page, or ask Indent to run
tailscale logout, which removes a node immediately.
Troubleshooting
Ask Indent to read ~/.indent/background-processes/tailscale.log.
API token invalid— the secret inTS_AUTHKEYis wrong or revoked.requested tags are invalid or not permitted— the credential doesn’t owntag:indent.- The node joins and reaches nothing — no grant names
tag:indent. - A tailnet with Tailnet Lock enabled rejects node keys that a signing node hasn’t signed. This setup doesn’t sign them.
Next steps
- Setting up environments — build the environment this configuration goes in.