Files
portainer-core/docs/connect-devices-guide.md
T

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):

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)

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

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:

  1. Check port 8085 is forwarded:

    # Test from outside network
    curl http://<your-public-ip>:8085
    # Should return HTML or redirect
    
  2. Check Headscale is running:

    # On tower-of-joy
    docker ps | grep headscale
    docker logs headscale
    
  3. 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:

  1. Access Organizr: http://10.99.0.1:9999
  2. Complete setup wizard
  3. Add tabs for all services using mesh IPs
  4. Enjoy unified dashboard from anywhere!