8.4 KiB
Connecting Devices to Headscale VPN
Step-by-step guide for connecting various devices to your Headscale mesh network Created: 2025-11-11
Overview
Once connected to Headscale, devices can access all services via mesh IPs (10.99.0.x):
- Organizr: http://10.99.0.1:9999
- Portainer: http://10.99.0.1:8001
- Netdata: http://10.99.0.1:19999
- All other services using mesh IPs
Prerequisites
You need a pre-auth key from Headscale:
# Generate a new pre-auth key (run on tower-of-joy)
docker exec headscale headscale preauthkeys create --user homelab --expiration 24h
# Output example:
# b4c17f9e9f01ea2e54b24e0369e2949bd28bfaf46944c634
Save this key - you'll use it to connect each device.
macOS (MacBook/iMac)
Method 1: Tailscale App (Recommended)
Step 1: Install Tailscale
# Option A: Using Homebrew
brew install tailscale
# Option B: Download from website
# Visit: https://tailscale.com/download/mac
# Download and install the .pkg file
Step 2: Start Tailscale
# Start the Tailscale service
sudo tailscaled install-system-daemon
sudo /Applications/Tailscale.app/Contents/MacOS/Tailscale up
Step 3: Connect to Headscale
Open the Tailscale app from menu bar → Preferences → Login Server
OR use command line:
sudo tailscale up --login-server=http://<your-public-ip>:8085 \
--authkey=<your-preauth-key> \
--hostname=macbook
# Example:
# sudo tailscale up --login-server=http://your-public-ip:8085 \
# --authkey=b4c17f9e9f01ea2e54b24e0369e2949bd28bfaf46944c634 \
# --hostname=macbook
Step 4: Verify Connection
# Check status
tailscale status
# Should show:
# 10.99.0.1 tower-of-joy homelab linux -
# 10.99.0.2 macbook homelab darwin -
# Get your mesh IP
tailscale ip -4
# Example output: 10.99.0.2
Step 5: Test Access
# Ping tower-of-joy
ping 10.99.0.1
# Access Organizr
open http://10.99.0.1:9999
# Or use curl
curl http://10.99.0.1:9999
Method 2: Using Public IP (If port 8085 forwarded)
If you've forwarded port 8085 on your router:
sudo tailscale up --login-server=http://<your-public-ip>:8085 \
--authkey=<your-preauth-key> \
--hostname=macbook
Linux (Laptop/Desktop)
# Install Tailscale
curl -fsSL https://tailscale.com/install.sh | sh
# Connect to Headscale
sudo tailscale up --login-server=http://<your-public-ip-or-local-ip>:8085 \
--authkey=<your-preauth-key> \
--hostname=linux-laptop
# Verify
tailscale status
ping 10.99.0.1
# Access Organizr
xdg-open http://10.99.0.1:9999
Windows
Step 1: Download Tailscale
- Visit: https://tailscale.com/download/windows
- Download and run the installer
Step 2: Configure Custom Login Server
- After installation, Tailscale runs in system tray
- Right-click Tailscale icon → Settings → Admin Console URL
- Change to:
http://<your-public-ip>:8085
Step 3: Login with Pre-Auth Key
- Right-click Tailscale icon → "Log in to Tailscale"
- Use the pre-auth key when prompted
Step 4: Verify
# In PowerShell or CMD
tailscale status
ping 10.99.0.1
# Access Organizr in browser
start http://10.99.0.1:9999
iOS (iPhone/iPad)
Step 1: Install Tailscale App
- Open App Store
- Search "Tailscale"
- Install official Tailscale app
Step 2: Configure Custom Control Server
- Open Tailscale app
- Tap Settings (gear icon)
- Tap "Use Custom Control Server"
- Enter:
http://<your-public-ip>:8085
Step 3: Connect
- Tap "Log In"
- If prompted for key, use your pre-auth key
- Grant VPN permissions when prompted
Step 4: Test
- Open Safari
- Navigate to:
http://10.99.0.1:9999 - You should see Organizr interface
Android
Step 1: Install Tailscale App
- Open Google Play Store
- Search "Tailscale"
- Install official Tailscale app
Step 2: Configure Custom Control Server
- Open Tailscale app
- Tap menu (three dots)
- Settings → Use custom control server
- Enter:
http://<your-public-ip>:8085
Step 3: Connect
- Tap "Log In"
- Use pre-auth key if prompted
- Grant VPN permissions
Step 4: Test
- Open Chrome/Firefox
- Navigate to:
http://10.99.0.1:9999 - Organizr should load
Troubleshooting
Can't Connect to Headscale Server
Problem: "Failed to connect to login server"
Solutions:
-
Check port 8085 is forwarded:
# Test from outside network curl http://<your-public-ip>:8085 # Should return HTML or redirect -
Check Headscale is running:
# On tower-of-joy docker ps | grep headscale docker logs headscale -
Use local IP if on same network:
# Instead of public IP, use local IP sudo tailscale up --login-server=http://192.168.86.149:8085 ...
Connected but Can't Reach Services
Problem: Connected to VPN but can't access 10.99.0.1
Check:
# Verify VPN connection
tailscale status
# Should show tower-of-joy as online
# Test ping
ping 10.99.0.1
# Should respond
# Check firewall (on tower-of-joy)
# Ensure mesh interface accepts traffic
sudo iptables -L -n | grep tailscale
Solution:
# On tower-of-joy, allow traffic from mesh network
sudo iptables -A INPUT -i tailscale0 -j ACCEPT
Pre-Auth Key Expired
Problem: "Invalid auth key"
Solution:
# Generate new key (on tower-of-joy)
docker exec headscale headscale preauthkeys create --user homelab --expiration 24h
# Use the new key to connect
DNS Not Resolving
Problem: Can ping 10.99.0.1 but browser can't resolve
Solution:
- Use IP addresses directly:
http://10.99.0.1:9999 - Don't use hostnames unless you've configured DNS
- Mesh IPs always work
Verifying Your Connection
Quick Test Checklist
From your newly connected device:
# 1. Check VPN status
tailscale status
# Should show: connected, online
# 2. Get your mesh IP
tailscale ip -4
# Example: 10.99.0.2
# 3. Ping tower-of-joy
ping -c 4 10.99.0.1
# Should get responses
# 4. Test Organizr
curl -I http://10.99.0.1:9999
# Should return HTTP 200 OK
# 5. Test other services
curl -I http://10.99.0.1:8001 # Portainer
curl -I http://10.99.0.1:19999 # Netdata
curl -I http://10.99.0.1:3001 # Uptime Kuma
View All Connected Devices
# On tower-of-joy
docker exec headscale headscale nodes list
# Shows all devices:
# ID | Hostname | IP | Last Seen
# 1 | tower-of-joy | 10.99.0.1 | now
# 2 | macbook | 10.99.0.2 | now
# 3 | iphone | 10.99.0.3 | now
Managing Devices
Remove a Device
# On tower-of-joy
docker exec headscale headscale nodes list
# Note the ID of the device to remove
docker exec headscale headscale nodes delete <ID>
Rename a Device
docker exec headscale headscale nodes rename <OLD-NAME> <NEW-NAME>
Generate Multiple Pre-Auth Keys
# For different devices or time periods
docker exec headscale headscale preauthkeys create --user homelab --expiration 1h --reusable
docker exec headscale headscale preauthkeys create --user homelab --expiration 7d
docker exec headscale headscale preauthkeys create --user homelab --expiration 30d
List All Pre-Auth Keys
docker exec headscale headscale preauthkeys list
Security Best Practices
Key Expiration
- ✅ Use short expiration for one-time device setups (1h-24h)
- ✅ Use longer expiration for trusted devices (7d-30d)
- ⚠️ Never use permanent keys
Device Management
- ✅ Use descriptive hostnames (macbook, work-laptop, phone)
- ✅ Regularly review connected devices
- ✅ Remove old/unused devices
- ✅ Regenerate keys periodically
Network Security
- ✅ Headscale port (8085) should be firewalled to trusted IPs if possible
- ✅ Use strong authentication on services
- ✅ Consider adding MFA to Organizr for public access
- ✅ Monitor Headscale logs for suspicious activity
Quick Reference
MacBook Connection (Your Current Task)
# 1. Generate pre-auth key (on tower-of-joy)
docker exec headscale headscale preauthkeys create --user homelab --expiration 24h
# 2. On MacBook
brew install tailscale
sudo tailscale up --login-server=http://<your-public-ip>:8085 \
--authkey=<key-from-step-1> \
--hostname=macbook
# 3. Verify
tailscale status
open http://10.99.0.1:9999
Next Steps After Connecting:
- Access Organizr: http://10.99.0.1:9999
- Complete setup wizard
- Add tabs for all services using mesh IPs
- Enjoy unified dashboard from anywhere!