This guide covers connecting devices to your Headscale server using Tailscale clients on various platforms.
Prerequisites
Before connecting any device, you need:
A running Headscale server
A user created in Headscale
A pre-auth key for authentication
Generate a Pre-Auth Key
Create a user (if you haven't already)
docker exec headscale headscale users create myuser
Or use the helper script: ./scripts/headscale.sh users create myuser
Generate a pre-auth key
Docker Command
Helper Script
Headplane GUI
docker exec headscale headscale preauthkeys create --user myuser --reusable --expiration 24h
./scripts/headscale.sh keys create myuser --reusable --expiration 24h
Open http://localhost:3001/admin/
Go to Pre-Auth Keys section
Click Create New Key
Select user and configure expiration
Copy the generated key
Save this key securely - you’ll need it to connect each device. Use --reusable for connecting multiple devices with the same key.
Linux
Automated Setup (Recommended)
Navigate to configuration directory
cd tailscale-configs/linux-systemd
Run the setup script
The script will prompt you for:
Headscale server URL (e.g., http://localhost:8000)
Pre-auth key
Whether to accept routes from other nodes
Whether to advertise as an exit node
Routes to advertise (if any)
Verify connection
tailscale status
tailscale ip
Manual Setup
Install Tailscale
curl -fsSL https://tailscale.com/install.sh | sh
Connect to Headscale
sudo tailscale up --login-server http://localhost:8000 --authkey YOUR_KEY --accept-routes
macOS
Using GUI Application
Download and install Tailscale
Configure custom server
Open Tailscale from menu bar
Click Preferences
Go to Advanced tab
Under “Login Server”, enter: http://localhost:8000
Click Save
Connect with pre-auth key
Click Connect in the main menu
Browser opens - paste your pre-auth key
Click Authenticate
Using Terminal
sudo /Applications/Tailscale.app/Contents/MacOS/Tailscale up \
--login-server=http://localhost:8000 \
--authkey=YOUR_PREAUTH_KEY \
--accept-routes
Windows
Using GUI Application
Download and install Tailscale
Configure custom server
Open Tailscale app from Start menu
Click Settings (gear icon)
Go to Admin Console
Click Use a Custom Login Server
Enter: http://YOUR_SERVER_IP:8000
Click Connect
Authenticate
Browser window opens
Paste your pre-auth key
Click Authenticate
Using PowerShell (as Administrator)
tailscale up -- login - server http: // localhost: 8000 -- authkey YOUR_KEY -- accept - routes
Mobile Devices
iOS
Install Tailscale
Download Tailscale from the App Store.
Configure alternative server
Open the app
Tap Settings (gear icon)
Scroll to Use Alternative Coordination Server
Toggle ON
Enter your server URL: http://YOUR_SERVER_IP:8000
Tap Save
Use your computer’s IP address or public domain, not localhost (which won’t work from your phone).
Connect
Go back and tap Connect
Browser opens
Paste your pre-auth key
Tap Authenticate
Android
Install Tailscale
Download Tailscale from Google Play Store.
Configure server URL
Open the app
Tap ⋮ (three dots menu)
Select Settings
Tap Server URL
Enter: http://YOUR_SERVER_IP:8000
Tap OK
Connect
Go back and tap Connect
Browser opens
Paste pre-auth key
Tap Authenticate
Docker Containers
Sidecar Pattern
Connect a Docker container to your Tailscale network using the sidecar pattern:
services :
myapp :
image : myapp:latest
network_mode : "service:tailscale"
depends_on :
- tailscale
tailscale :
image : tailscale/tailscale:latest
hostname : myapp-container
environment :
- TS_AUTHKEY=YOUR_PREAUTH_KEY
- TS_STATE_DIR=/var/lib/tailscale
- TS_LOGIN_SERVER=http://host.docker.internal:8000
- TS_ACCEPT_ROUTES=true
volumes :
- tailscale-data:/var/lib/tailscale
- /dev/net/tun:/dev/net/tun
cap_add :
- NET_ADMIN
- SYS_MODULE
restart : unless-stopped
volumes :
tailscale-data :
Create .env file with your key
echo "TS_AUTHKEY=your-preauth-key-here" > .env
Verify connection
docker exec myapp-tailscale tailscale status
Verification
After connecting any device, verify the connection:
Check Status
View IP Addresses
Test Connectivity
View Routes
Verify in Headplane GUI
Open http://localhost:3001/admin/
Go to Nodes page
Your device should appear in the list with:
Hostname
IP addresses
Online status
Last seen timestamp
Connection Options
Common Parameters
Parameter Description Example --login-serverYour Headscale server URL http://localhost:8000--authkeyPre-auth key from Headscale YOUR_PREAUTH_KEY--accept-routesAccept subnet routes from other nodes (flag, no value) --advertise-routesShare local networks 192.168.1.0/24,10.0.0.0/24--advertise-exit-nodeBecome an exit node (flag, no value) --hostnameCustom hostname my-device--advertise-tagsApply ACL tags tag:personal,tag:servers--sshEnable Tailscale SSH (flag, no value)
Example Configurations
Personal Laptop
Server Node
Exit Node
sudo tailscale up \
--login-server=http://localhost:8000 \
--authkey=YOUR_KEY \
--accept-routes \
--hostname=my-laptop
Accept routes from other nodes to access shared networks. sudo tailscale up \
--login-server=http://localhost:8000 \
--authkey=YOUR_KEY \
--advertise-routes=192.168.1.0/24 \
--advertise-tags=tag:servers
Advertise local network and apply server tag for ACL rules. sudo tailscale up \
--login-server=http://localhost:8000 \
--authkey=YOUR_KEY \
--advertise-exit-node \
--advertise-tags=tag:servers
Route internet traffic through this node.
Troubleshooting
Unable to Connect
Verify Headscale is running
curl http://localhost:8000/health
# Should return: {"status":"pass"}
Check pre-auth key validity
docker exec headscale headscale preauthkeys list --user myuser
Ensure the key hasn’t expired.
Check Tailscale logs
journalctl -u tailscaled -f
tail -f /usr/local/var/log/tailscale-headscale.log
docker logs myapp-tailscale
Reset Connection
If you need to reset and reconnect:
# Disconnect
sudo tailscale down
# Clear state (optional)
sudo rm -rf /var/lib/tailscale/ *
# Reconnect with new key
sudo tailscale up --login-server=http://localhost:8000 --authkey=NEW_KEY
Mobile Connection Issues
When connecting from mobile devices, you must use your server’s actual IP address or domain name, not localhost.
Find your server’s IP:
# Linux/macOS
ip addr show | grep inet
# Or get external IP
curl ifconfig.me
Security Best Practices
Use short-lived keys : Set expiration to 24h for testing, 1h for production
Use single-use keys : Remove --reusable when possible
Apply ACL tags : Organize devices with --advertise-tags=tag:personal
Never commit auth keys : Add .env files to .gitignore
Use ephemeral nodes : Add --ephemeral for temporary devices
Rotate keys regularly : Generate new keys and reconnect devices periodically
Next Steps