🔗 Tailscale — Run the Tailscale client in Docker on a Raspberry Pi
This document shows a simple, clear Docker Compose setup to run the Tailscale client in a container on a Raspberry Pi, with explanations of the important environment variables, required capabilities, how to authenticate, advertise services (tags / exit node), and basic troubleshooting.
Keep secrets (TS_AUTHKEY) out of source control and restrict file permissions for any files containing auth keys.
✅ Prerequisites
- Raspberry Pi with Docker & Docker Compose installed
- Network access and an account at https://login.tailscale.com
- Basic knowledge of Docker and accessing the Pi via SSH or terminal
Quick Docker Compose example
Create a project directory, e.g. ~/docker/tailscale, and a docker-compose.yml. Adjust the mount path and auth key before starting.
services:
tailscale:
image: tailscale/tailscale:latest
container_name: tailscale
restart: unless-stopped
network_mode: "host" # recommended for full networking functionality
cap_add:
- NET_ADMIN
- SYS_MODULE
- NET_RAW
environment:
- TS_AUTHKEY=${TS_AUTHKEY} # set in .env (safer) or in your environment
- TS_EXTRA_ARGS=--advertise-tags=tag:container --advertise-exit-node
- TS_STATE_DIR=/var/lib/tailscale
- TS_USERSPACE=false # use kernel TUN when possible; set true for userspace mode
volumes:
- ./state:/var/lib/tailscale
- /dev/net/tun:/dev/net/tun # ensure TUN device access if not using host network
Notes:
- Using
network_mode: "host"is recommended for best compatibility (avoids NAT and simplifies routing). If you do not use host networking, you must ensure the container can create / access /dev/net/tun. - Put the TS_AUTHKEY in a
.envfile (not checked into git) or in the environment. Example.env:Secure this file:TS_AUTHKEY=tskey-xxxxxxxxxxxxxxxxxxxxchmod 600 .env.
Important environment variables explained
- TS_AUTHKEY — one-time or reusable auth key created at https://login.tailscale.com/admin/settings/keys. Use
tskey-*keys with appropriate expiry and reuse policy. Keep secret. - TS_STATE_DIR — persistent state (keys, device state). Persist this directory to keep the node identity across restarts.
- TS_EXTRA_ARGS — extra CLI arguments passed to
tailscaled/tailscale up. Common flags:- --advertise-exit-node — let this device act as an exit node for routed internet traffic
- --advertise-tags=tag:container — advertise an ACL tag (requires an ACL tag policy in the admin console)
- TS_USERSPACE — false (default) to use kernel TUN device; set
trueto run in userspace mode (no TUN) when kernel support is unavailable or container cannot access /dev/net/tun.
How to obtain an auth key
- Sign in to the Tailscale admin console: https://login.tailscale.com/admin
- Go to Settings → Keys (or Access Keys) and create a "Preauthorized key" or reusable auth key.
- Copy the key and place it in
.envor as an environment variable. For one-off installs, you can use an ephemeral key.
Security: create keys with the minimal lifetime and scopes you need. Revoke keys from the admin console if compromised.
Start, check and stop
Start:
cd ~/docker/tailscale
docker compose up -d
Check container logs:
docker logs -f tailscale
Check Tailscale status (inside the container):
docker exec -it tailscale tailscale status
docker exec -it tailscale tailscale ip # show assigned tailnet IPs
Stop and remove:
docker compose down
If using host networking and you changed the device name, restart may be required.
Advertise exit node or services
- Exit node: add
--advertise-exit-node(example in TS_EXTRA_ARGS). Approve the exit node in the admin console when the device appears. - Tags: to mark a device for ACLs, advertise tags with
--advertise-tags=tag:container. Then create an ACL in the admin console that pre-authorizes that tag for specific users or groups.
Security and permissions
- The container needs access to networking capabilities and TUN device:
- Prefer
network_mode: "host"+ cap_add for simplicity on Pi. - Or mount
/dev/net/tunand ensureTS_USERSPACE=falseis appropriate.
- Prefer
- Protect TS_AUTHKEY: store in
.envwithchmod 600or use secrets manager. - If exposing exit-node or services, enforce ACLs in the Tailscale admin console.
Updating
To update the image:
docker compose pull tailscale
docker compose up -d
Because state is persisted in ./state, the node retains identity after upgrades.
Troubleshooting
- Container fails to create TUN:
- Ensure
/dev/net/tunexists on the host:ls -l /dev/net/tun. Create withsudo mkdir -p /dev/net && sudo mknod /dev/net/tun c 10 200if missing (requires appropriate kernel). - If using
network_mode: "host", TUN is usually accessible.
- Ensure
tailscale statusshows no login:- Confirm TS_AUTHKEY is valid and not expired.
- Check container logs for errors:
docker logs tailscale.
- Exit node not available:
- Confirm
--advertise-exit-nodewas passed and approve the device in admin console.
- Confirm
- Tags not recognized:
- Ensure
--advertise-tagsincludes the correct tag formattag:yourtagand that the tag is allowed in ACLs.
- Ensure
Useful log commands:
docker logs -f tailscale
docker exec -it tailscale tailscale status
docker exec -it tailscale tailscale up --help
Alternatives & notes
- Systemd install of Tailscale on the host is simpler for many use cases — running in Docker is useful when you want to isolate, co-locate with other containerized services, or run multiple instances.
- On devices where direct kernel TUN access is not allowed, set
TS_USERSPACE=trueto use the userspace backend (slower, but works without /dev/net/tun). - If you plan to use Tailscale as an exit node for many clients, consider bandwidth and routing implications for your Raspberry Pi / network.
Example quick checklist
- Create directory and
docker-compose.yml. - Add
TS_AUTHKEYto.env(chmod 600). - Start:
docker compose up -d. - Approve device in Tailscale admin console.
- Test:
docker exec -it tailscale tailscale status.
Tailscale in Docker gives a convenient way to add a tailnet node on your Raspberry Pi. Use host networking where possible, secure your auth keys, and configure advertised services (tags/exit-node) from the admin console as needed.