Det här sätter du upp
Tailscale kopplar ihop dina enheter i ett privat nätverk, ett tailnet, var de än befinner sig. Enheterna ansluter direkt till varandra, krypterat med WireGuard, och var och en får en fast adress och ett namn. En styrserver håller listan över enheter och delar ut deras nycklar. Normalt kör Tailscale Inc. den, och skickar vidare trafik åt enheter som inte når varandra direkt.
Headscale är en styrserver med öppen källkod som du kör själv. Tailscales appar fungerar med den utan ändringar: du pekar dem bara mot din server. Listan över dina enheter stannar på din server, och det gör reläet också, så ingen del av ditt tailnet går genom Tailscales servrar.
Här körs den som en container, under en egen användare som heter headscale, bakom Caddy från Podman-guiden. Bara reläets adresskontroll, STUN, är öppen direkt mot internet.
Varje steg nedan har körts på en server hos Melonslab med Debian 13:
- Tre Tailscale 1.102-klienter på Linux gick med: två med en nyckel, och en genom inloggningslänken, som telefoner och datorer gör.
- En klient hemma nådde en på servern direkt, och via serverns eget relä när UDP mellan dem blockerades.
- STUN rapporterade hemmaklientens riktiga publika adress, och enhetsnamnen slogs upp med MagicDNS.
- Headscale loggade varje klients riktiga adress, och allt startade igen av sig självt efter en omstart av servern.
Headscale använde omkring 17 MB minne. Stegen för telefoner, Windows och macOS följer Headscales egen dokumentation.
Innan du börjar
Du behöver:
- en server uppsatt som i Podman-guiden, med Caddy igång;
- en A-post och en AAAA-post för
headscale.example.comsom pekar på din server; - Tailscale-appen på varje enhet, version 1.80 eller nyare, från tailscale.com/download.
Exemplen använder headscale.example.com, 203.0.113.10 som din servers IPv4-adress och 2001:db8:1f::a som dess IPv6-adress. ip -brief address show eth0 visar dina. Byt ut dem genomgående.
Headscale är ett tailnet där dina enheter når varandra. Vill du i stället surfa på internet via din server, se WireGuard-guiden.
1. Öppna STUN-porten
Enheterna frågar reläet på UDP-port 3478 vilken publik adress de syns med utåt, vilket hjälper dem att ansluta direkt till varandra. Om du använder ufw som i säkerhetsguiden kör du det här som root:
ufw allow 3478/udp
coturn från samtalsguiden använder också port 3478. Kör du den, använd 3479 här och i steg 3 och 4 i stället.
2. Skapa användaren
useradd -m -s /bin/bash headscale
loginctl enable-linger headscale
machinectl shell headscale@
Allt fram till steg 5 körs som headscale.
3. Skriv konfigurationen
mkdir -p ~/headscale ~/.config/containers/systemd
Skapa ~/headscale/config.yaml:
server_url: https://headscale.example.com
listen_addr: 0.0.0.0:8080
metrics_listen_addr: 127.0.0.1:9090
grpc_listen_addr: 127.0.0.1:50443
# Caddy's connections reach the container from the server's own IPv4 address.
trusted_proxies:
- 203.0.113.10/32
noise:
private_key_path: /var/lib/headscale/noise_private.key
prefixes:
v4: 100.64.0.0/10
v6: fd7a:115c:a1e0::/48
derp:
server:
enabled: true
region_id: 999
region_code: headscale
region_name: Headscale
stun_listen_addr: ":3478"
private_key_path: /var/lib/headscale/derp_server_private.key
ipv4: 203.0.113.10
ipv6: 2001:db8:1f::a
# Only this server relays traffic, not Tailscale's public relays.
urls: []
database:
type: sqlite
sqlite:
path: /var/lib/headscale/db.sqlite
dns:
magic_dns: true
base_domain: tail.example.com
nameservers:
global:
- 9.9.9.9
- 149.112.112.112
- 2620:fe::fe
- 2620:fe::9
Vad delarna gör:
trusted_proxieslåter Headscale logga varje enhets riktiga adress, som Caddy skickar vidare.prefixesär adressintervallen som Tailscale normalt använder i ett tailnet.derpslår på Headscales relä. Det förmedlar trafik mellan enheter som inte kan ansluta direkt, och trafiken är fortfarande krypterad hela vägen.urls: []utesluter Tailscales publika reläer, så att din server är det enda reläet. Vill du behålla deras som reserv anger duhttps://controlplane.tailscale.com/derpmap/defaultunderurlsi stället.dnsger varje enhet ett namn, somlaptop.tail.example.com.base_domainfår inte varaexample.comsjälvt, eftersom serverns eget namn ligger under det, så en underdomän somtail.example.comanvänds. Uppslagningar av andra namn går till Quad9.
4. Definiera containern
Skapa ~/.config/containers/systemd/headscale.container:
[Unit]
Description=Headscale, a Tailscale control server
[Container]
ContainerName=headscale
Image=docker.io/headscale/headscale:0.29
Exec=serve
ReadOnly=true
Tmpfs=/var/run/headscale
Volume=%h/headscale/config.yaml:/etc/headscale/config.yaml:ro
Volume=headscale-data:/var/lib/headscale
# Control and relay, reached through Caddy only
PublishPort=127.0.0.1:8091:8080
# STUN, open to the internet
PublishPort=3478:3478/udp
AutoUpdate=registry
[Service]
Restart=always
[Install]
WantedBy=default.target
Starta den:
systemctl --user daemon-reload
systemctl --user start headscale
podman logs headscale
Loggen visar stun server started at [::]:3478 och listening and serving HTTP on: 0.0.0.0:8080. En varning om att den lyssnar without TLS är normal: Caddy sköter HTTPS.
5. Sätt Caddy framför
Gå tillbaka till root med exit, byt till Caddys användare med machinectl shell caddy@ och lägg till de här två blocken sist i ~/Caddyfile:
http://headscale.example.com {
# Tailscale checks for captive portals here
handle /generate_204 {
respond 204
}
handle {
redir https://{host}{uri}
}
}
headscale.example.com {
reverse_proxy 127.0.0.1:8091 {
header_up True-Client-IP {remote_host}
header_up X-Real-IP {remote_host}
}
}
Det första blocket svarar på kontrollen Tailscale gör för att se om ett wifi-nätverk håller tillbaka trafik tills du loggar in, och skickar allt annat till HTTPS. De två header_up-raderna ersätter den adress en enhet själv uppger med den adress Caddy ser, så att ingen kan förfalska sin adress i Headscales logg.
Starta om Caddy med systemctl --user restart caddy, och kontrollera från valfri dator:
curl https://headscale.example.com/health
Svaret är {"status":"pass"}.
6. Skapa en användare
Gå tillbaka till root med exit, sedan till machinectl shell headscale@. Varje enhet hör till en användare. Skapa en, och lista användarna för att se dess id:
podman exec headscale headscale users create anna
podman exec headscale headscale users list
7. Anslut dina enheter
Varje app öppnar en sida på din server med ett kommando att köra. Kör det som användaren headscale, med USERNAME utbytt mot användaren från steg 6, här anna:
podman exec headscale headscale auth register --auth-id hskey-authreq-... --user anna
Kommandot svarar Node ... registered, och enheten går med. Så börjar du från varje app:
- Linux:
sudo tailscale up --login-server https://headscale.example.com, och öppna länken den skriver ut. - Windows: i PowerShell,
tailscale login --login-server https://headscale.example.com. - macOS:
tailscale login --login-server https://headscale.example.com, eller håll ned Option, klicka på Tailscale-ikonen och välj Add Account under Debug, Custom Login Server. - Android: öppna inställningsmenyn uppe till höger och sedan Accounts. Välj Use an alternate server i menyn med tre punkter, och ange
https://headscale.example.com. - iPhone och iPad: tryck på kontoikonen uppe till höger och Log in…. Välj Use custom coordination server i alternativmenyn, och ange
https://headscale.example.com.
https://headscale.example.com/apple och /windows visar samma steg för de systemen.
För en server, eller en enhet utan webbläsare, skapar du en nyckel i stället. --user tar id:t från users list:
podman exec headscale headscale preauthkeys create --user 1
Nyckeln börjar med hskey- och fungerar en gång inom en timme. På enheten:
sudo tailscale up --login-server https://headscale.example.com --authkey hskey-...
8. Kontrollera det
På valfri ansluten enhet:
tailscale status
tailscale ping laptop
tailscale netcheck
tailscale status listar varje enhet med dess adress. tailscale ping svarar pong from laptop (100.64.0.1) via 203.0.113.10:41641 eller liknande för en direkt anslutning, eller via DERP(headscale) när trafiken går via ditt relä. tailscale netcheck visar Nearest DERP: Headscale, och din publika IPv4-adress under IPv4, som STUN såg den.
Enheterna når varandra på namn, laptop.tail.example.com, så länge appen får ställa in DNS, vilket den får som standard. Alla enheter i ditt tailnet kan nå varandra, vilket passar en person eller en familj. För att begränsa vem som når vad skriver du en policy, som beskrivs i Headscales dokumentation.
9. Håll den uppdaterad
Som headscale slår du på Podmans dagliga uppdateringar:
systemctl --user enable --now podman-auto-update.timer
Med taggen 0.29 får du alla buggfixar inom Headscale 0.29. Headscale måste uppgraderas en minor-version i taget, från 0.29 till 0.30 och så vidare, utan att du hoppar över någon. Läs versionsanteckningarna före varje uppgradering, säkerhetskopiera som i steg 10 och ändra sedan taggen.
10. Säkerhetskopiera
Som headscale:
mkdir -p ~/backup
systemctl --user stop headscale
podman volume export headscale-data --output ~/backup/headscale-data.tar
cp ~/headscale/config.yaml ~/backup/
systemctl --user start headscale
Det sparar databasen, med alla användare och enheter, och serverns privata nycklar. Kopiera sedan ~/backup till en annan maskin och förvara den säkert.
Felsökning
Headscale stannar vid start med server_url cannot be part of base_domain. base_domain i steg 3 innehåller serverns eget namn. Använd en underdomän, som tail.example.com.
tailscale netcheck visar UDP: false, eller ingen Nearest DERP. STUN-porten går inte att nå. Kontrollera ufw-regeln från steg 1, och att porten är densamma i steg 1, 3 och 4.
En enhet förblir offline efter inloggningssidan. Kommandot auth register har inte körts, eller kördes med en användare som inte finns. podman exec headscale headscale nodes list visar varje registrerad enhet.