Jak zainstalować Headscale na własnym serwerze VPS
Wdrożenie własnego serwera sterującego dla sieci Tailscale. Instrukcja instalacji pakietu .deb, konfiguracji parametru server_url oraz poprawnego dodania pierwszego węzła.
Czym jest headscale
Headscale to samodzielnie hostowana implementacja serwera kontrolnego Tailscale, dzięki której maszyną koordynującą prywatną sieć jest posiadany przez użytkownika VPS. Jest to projekt społecznościowy, niezarządzany przez Tailscale Inc. Każda maszyna nadal uruchamia oficjalnego klienta tailscale, skierowanego na własny serwer za pomocą jednej flagi, --login-server.
Serwer kontrolny to komponent, który posiada wiedzę o tym, kto należy do sieci. Przydziela każdemu węzłowi adres z puli 100.64.0.0/10, dystrybuuje klucze publiczne i informuje węzły, gdzie mogą się nawzajem odnaleźć. Tunele pozostają oparte na WireGuard, tworzonym bezpośrednio między węzłami. Ruch między dwiema maszynami nie przechodzi przez serwer headscale, chyba że nie można nawiązać bezpośredniego połączenia i węzły przełączą się na przekaźnik (relay). Samodzielne pełnienie roli koordynatora zmienia jedynie podmiot sprawujący kontrolę, a nie zakres jego możliwości, dlatego warto zrozumieć do czego serwer kontrolny ma, a do czego nie ma dostępu w tym modelu, zanim potraktuje się tę zmianę jako samodzielne zwiększenie bezpieczeństwa.
Headscale obsługuje jedną tailnet (jedną sieć Tailscale) na instancję. Projekt określa to rozwiązanie jako odpowiednie do użytku osobistego lub w małej organizacji. Przy trzech lub czterech maszynach zwykła sieć VPN WireGuard na własnym VPS oznacza mniej oprogramowania do uruchomienia i mniej elementów, które mogą ulec awarii. Headscale zaczyna się opłacać, gdy nie chcesz już ręcznie tworzyć bloku [Peer] dla każdego nowego laptopa. Koszt często skłania do rozpoczęcia poszukiwań, dlatego przed uruchomieniem serwera warto przeczytać co faktycznie obejmuje bezpłatny plan hostowany, ponieważ kilka prywatnych maszyn zazwyczaj mieści się w jego zakresie. Jeśli ten limit został już przekroczony, porównaj koszty z cenami planów płatnych za użytkownika i oznaczony zasób, ponieważ urządzenia użytkowników są nielimitowane, natomiast oznaczone zasoby mają osobne limity i opłaty. Jeśli potrzebujesz self-hosted control plane, ale wolisz własnego klienta i interfejs webowy do zarządzania peerami niż zamiennik Tailscale działający bez dodatkowej konfiguracji, NetBird na pojedynczym VPS jest alternatywą wartą rozważenia. Oba rozwiązania przesyłają ruch przez WireGuard, więc wybór zależy od sposobu definiowania reguł dostępu i działania relayów. Przed instalacją któregoś z nich warto porównać NetBird z Tailscale pod tymi względami. Szersze porównanie obu modeli opisano w artykule o różnicach między WireGuard i Tailscale.
Wymagania wstępne przed instalacją
- Serwer VPS z systemem Ubuntu 24.04, publicznym adresem IPv4 oraz dostępem sudo. W przypadku nowego serwera należy najpierw wykonać kroki opisane w pierwsze dziesięć minut na nowym serwerze VPS.
- Rekord DNS typu A wskazujący na ten adres. W tym przewodniku użyto
headscale.example.com. - Druga domena lub subdomena dla MagicDNS. W tym przewodniku użyto
tailnet.example.net. Nie może to być ta sama domena, która została użyta wserver_url. - Jedno urządzenie klienckie do połączenia z siecią, działające pod kontrolą systemu Linux, macOS, Windows, Android lub iOS. Headscale 0.29.6 wymaga klienta Tailscale w wersji 1.80.0 lub nowszej.
Instalacja headscale z oficjalnego pakietu .deb
Projekt publikuje pakiety .deb na swojej stronie wydań w serwisie GitHub. Według stanu na 27 października 2026 r. najnowsze stabilne wydanie to 0.29.6, opublikowane 24 października 2026 r. Najpierw należy sprawdzić architekturę systemu, ponieważ jest ona zawarta w nazwie pliku.
sudo apt update
sudo apt install -y wget
dpkg --print-architecturePolecenie to wyświetla amd64 na standardowym serwerze VPS x86 oraz arm64 w przypadku planów typu Ampere lub Graviton. Wynik należy podstawić do poniższej zmiennej.
HEADSCALE_VERSION="0.29.6"
HEADSCALE_ARCH="amd64"
wget --output-document=headscale.deb \\
"https://github.com/juanfont/headscale/releases/download/v${HEADSCALE_VERSION}/headscale_${HEADSCALE_VERSION}_linux_${HEADSCALE_ARCH}.deb"
sudo apt install -y ./headscale.deb
headscale versionZnak ./ przed nazwą pliku jest wymagany. Bez niego apt szuka pakietu o nazwie headscale.deb w repozytoriach, co kończy się niepowodzeniem.
Pakiet tworzy użytkownika systemowego headscale, zapisuje domyślny plik /etc/headscale/config.yaml, instaluje jednostkę systemd, a następnie uruchamia usługę. W momencie zakończenia działania apt usługa headscale już pracuje, a sudo systemctl is-active headscale wyświetla active. W przypadku świeżej instalacji pakiet nie włącza jednak jednostki automatycznie, więc usługa nie uruchomi się po restarcie systemu, dopóki nie zostanie włączona, co wykonuje poniższy krok restartu. Usługa działa również na domyślnej konfiguracji, która wskazuje server_url na http://127.0.0.1:8080; nie jest to adres osiągalny dla żadnego klienta. Żadne zasoby nie są jeszcze wystawione, ponieważ domyślny listen_addr również nasłuchuje na interfejsie zwrotnym (loopback), jednak nie należy przyłączać żadnych klientów przed ustawieniem server_url i zrestartowaniem usługi, co realizują dwa kolejne kroki.
Skonfiguruj server_url przed dołączeniem pierwszego klienta
Edytuj /etc/headscale/config.yaml za pomocą sudo nano /etc/headscale/config.yaml lub wprowadź te same trzy zmiany przy użyciu sed. Zachowaj kopię oryginalnego pliku, ponieważ jest on długi, zawiera liczne komentarze i stanowi najlepsze źródło informacji o pozostałych ustawieniach.
sudo cp /etc/headscale/config.yaml /etc/headscale/config.yaml.orig
sudo sed -i 's|^server_url:.*|server_url: https://headscale.example.com|' /etc/headscale/config.yaml
sudo sed -i 's|^listen_addr:.*|listen_addr: 127.0.0.1:8080|' /etc/headscale/config.yaml
sudo sed -i 's|^ base_domain:.*| base_domain: tailnet.example.net|' /etc/headscale/config.yaml
sudo grep -E '^(server_url|listen_addr):|^ base_domain:' /etc/headscale/config.yamlserver_url to publiczny adres, którego headscale używa podczas generowania adresów URL rejestracji. Klienci korzystają z adresu kontrolnego skonfigurowanego za pomocą --login-server, dlatego należy użyć tej samej publicznej nazwy w https:// w obu miejscach, nigdy 127.0.0.1. Dokumentacja headscale dopuszcza użycie zwykłego HTTP lub HTTPS na porcie innym niż 443, jednak w środowiskach produkcyjnych zdecydowanie zaleca się stosowanie HTTPS na porcie 443, co jest założeniem niniejszego przewodnika.
listen_addr to adres, na którym proces nasłuchuje połączeń. Pozostaw go ustawionego na interfejs pętli zwrotnej (loopback). Reverse proxy działające na tym samym serwerze zajmuje się terminacją TLS (transport layer security) i przekazywaniem ruchu, więc żaden zewnętrzny podmiot nie musi mieć bezpośredniego dostępu do portu 8080.
base_domain to sufiks MagicDNS, czyli domena, w której węzły otrzymują swoje nazwy. Musi to być w pełni kwalifikowana nazwa domeny (FQDN) bez kropki na końcu. Musi ona różnić się od domeny użytej w server_url, w przeciwnym razie przestrzenie nazw będą ze sobą kolidować.
Sekcję bazy danych pozostaw bez zmian. Domyślnie używany jest SQLite w /var/lib/headscale/db.sqlite, w katalogu utworzonym i zarządzanym przez pakiet. SQLite jest wystarczający dla tailnetu tej wielkości.
Restart headscale i weryfikacja działania
sudo systemctl restart headscale
sudo systemctl enable headscale
sudo systemctl is-active headscale
sudo systemctl is-enabled headscale
curl -sS -o /dev/null -w '%{http_code}\\n' http://127.0.0.1:8080/healthis-active wyświetla active, is-enabled wyświetla enabled, a curl wyświetla 200. Restart jest krokiem, który wczytuje wprowadzone zmiany. headscale odczytuje konfigurację jednokrotnie, podczas uruchamiania, więc proces zainicjowany przez pakiet korzysta z dostarczonego server_url aż do momentu restartu. sudo systemctl enable --now headscale nie wykonuje tego zadania: usługa już działa, więc --now start nie zmienia niczego i stara wartość pozostaje aktywna. Uruchamianie przy starcie systemu jest zadaniem enable i nie jest wykonywane automatycznie: przy świeżej instalacji pakiet uruchamia usługę bez jej włączania, dlatego należy jednorazowo wykonać sudo systemctl enable headscale, zgodnie z powyższym opisem.
Jeśli is-active wyświetla cokolwiek innego niż active lub curl nie wyświetla 200, należy odczytać dziennik za pomocą sudo journalctl -u headscale -n 50 --no-pager. Awaria na tym etapie niemal zawsze wynika z pliku konfiguracyjnego, ponieważ headscale analizuje cały plik przed otwarciem gniazda, więc błędne wcięcie lub nieprawidłowe wymagane ustawienie zatrzymuje proces, zanim jakikolwiek port zacznie nasłuchiwać. Należy poprawić plik, a następnie wykonać sudo systemctl restart headscale. Każda późniejsza zmiana konfiguracji wymaga tego samego restartu. Klienci połączą się ponownie automatycznie. Jeśli jednostki systemd są nowym zagadnieniem, uruchamianie własnych usług i timerów za pomocą systemd zawiera opis użytych tutaj poleceń.
Podczas pracy w powłoce warto sprawdzić pliki stanu:
stat -c '%U %n' /var/lib/headscale/db.sqlite /var/lib/headscale/noise_private.keyObie linie zaczynają się od headscale, czyli użytkownika bez uprawnień administracyjnych utworzonego przez pakiet. noise_private.key to tożsamość serwera dla jego klientów. Należy ją zachować. W przypadku usunięcia tego pliku, headscale wygeneruje nowy, a klienci będą musieli pobrać nowy klucz serwera przed ponownym połączeniem; istniejące rejestracje pozostaną w bazie danych.
Umieszczenie TLS przed headscale
Klienci powinni łączyć się z server_url przez HTTPS. Caddy stanowi najkrótszą drogę, ponieważ samodzielnie żąda certyfikatu i go odnawia.
sudo apt install -y caddyZastąp /etc/caddy/Caddyfile blokiem z dokumentacji headscale:
headscale.example.com {
reverse_proxy 127.0.0.1:8080 {
header_up True-Client-IP {remote_host}
header_up X-Real-IP {remote_host}
}
}sudo caddy validate --adapter caddyfile --config /etc/caddy/Caddyfile
sudo systemctl restart caddy
sudo systemctl is-active caddyvalidate wypisuje adapted config to JSON, gdy plik zostanie poprawnie przeanalizowany. Ostrzeżenie o braku formatowania ma charakter kosmetyczny. Z poziomu laptopa polecenie curl -sS -o /dev/null -w '%{http_code}\\n' https://headscale.example.com/health również powinno zwrócić 200. Ta pojedyncza weryfikacja potwierdza, że DNS, firewall, certyfikat oraz proxy współpracują poprawnie.
Oto szczegół konfiguracji proxy, który często sprawia użytkownikom trudności. Połączenie kontrolne Tailscale to upgrade HTTP, inicjowany metodą POST zamiast GET, a wartość nagłówka Upgrade wynosi tailscale-control-protocol. Caddy przekazuje to bez dodatkowej konfiguracji. nginx tego nie robi, więc frontend nginx musi jawnie przekazywać nagłówki Upgrade oraz Connection. Dokumentacja headscale rozwiązuje to za pomocą mapy upgrade:
map $http_upgrade $connection_upgrade {
default keep-alive;
'' close;
}
server {
listen 443 ssl;
server_name headscale.example.com;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_buffering off;
proxy_pass http://127.0.0.1:8080;
}
}Pominięcie tych linii sprawia, że zwykłe żądania nadal kończą się powodzeniem, dlatego /health zwraca kod 200 i wszystko wygląda na sprawne, podczas gdy połączenie kontrolne nigdy nie zostaje nawiązane: nowe węzły nie mogą się zarejestrować, a istniejące nie mogą się ponownie połączyć i zgłosić statusu online. W przypadku wyboru nginx, Certbot na Ubuntu 24.04 z nginx opisuje kwestię certyfikatów.
Które porty otworzyć w UFW
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbosePort 443 obsługuje każde połączenie sterujące klienta z headscale. Jeśli w późniejszym czasie włączony zostanie wbudowany przekaźnik DERP, wymaga on również portu 3478/udp, opisanego poniżej. Port 80 służy do wyzwania HTTP w ramach ACME (automatic certificate management environment) oraz do przekierowania na HTTPS. Caddy może uzyskać certyfikat przy zamkniętym porcie 80, korzystając z wyzwania TLS-ALPN na porcie 443, jednak przy otwartym porcie 80 dostępne są obie metody, a zwykłe żądania http:// są przekierowywane.
Port 8080 pozostaje zamknięty. listen_addr to 127.0.0.1:8080, więc proxy łączy się z headscale przez interfejs loopback i reguła zapory sieciowej nie jest wymagana. Otwarcie portu 8080 w UFW nie udostępni żadnej usługi, ponieważ z zewnątrz nikt na nim nie nasłuchuje, nie przynosi to również żadnych korzyści. Należy pamiętać, że większość dostawców utrzymuje drugą zaporę sieciową w panelu sterowania, niezależną od UFW, więc port może być otwarty na serwerze, a jednocześnie zamknięty na poziomie infrastruktury sieciowej. Podstawy zapory UFW na VPS szczegółowo omawia składnię reguł.
Tworzenie użytkownika i klucza preauth
sudo headscale users create alice
sudo headscale users listPolecenie headscale jest klientem. Komunikuje się ono z działającym daemonem poprzez gniazdo unixowe w /var/run/headscale/headscale.sock, które posiada uprawnienia 0770 i należy do grupy headscale. Wynikają z tego dwie kwestie. Polecenie kończy się niepowodzeniem, gdy usługa jest zatrzymana, co stanowi kolejny powód, dla którego kolejność działań w tym przewodniku jest istotna. Wymaga ono również uprawnień sudo, chyba że dodasz własne konto do grupy headscale.
users list wyświetla identyfikator obok każdej nazwy. Ten numer jest niezbędny, ponieważ polecenie klucza wymaga numerycznego identyfikatora użytkownika, a nie nazwy.
sudo headscale preauthkeys create --user 1 --expiration 24hKlucz jest wyświetlany tylko raz. Skopiuj go teraz. Klucz preauth jest jednorazowy i ważny przez jedną godzinę, chyba że określisz inaczej, dlatego warto ustawić --expiration 24h podczas testów. Dodaj --reusable dla klucza, który rejestruje wiele maszyn i traktuj go jak hasło, ponieważ każdy, kto go posiada, może dołączyć do Twojej sieci.
Podłączanie pierwszego klienta za pomocą --login-server
Na maszynie, którą chcesz dołączyć:
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up --login-server https://headscale.example.com --auth-key 'hskey-auth-PASTE-YOUR-KEY-HERE'
tailscale status
tailscale ip -4tailscale ip -4 wyświetla adres przypisany przez headscale, w formacie zbliżonym do 100.64.0.1. Po powrocie na serwer, sudo headscale nodes list pokazuje węzeł wraz z jego identyfikatorem, użytkownikiem oraz stanem połączenia.
Użyj publicznego adresu HTTPS z server_url dla --login-server. Klient usuwa końcowe ukośniki z adresu URL kontrolera; nie ma wymogu ścisłego dopasowania ciągu znaków, który wymuszałby ich pominięcie.
Maszyna, która była wcześniej zalogowana do hostowanej usługi Tailscale, zachowuje to logowanie. Uruchom na niej najpierw sudo tailscale logout, a następnie wykonaj tailscale up z użyciem --login-server.
Jeśli pominiesz --auth-key, klient wyświetli adres URL. Otwórz go, a strona pokaże identyfikator tej próby rejestracji, który zatwierdzasz na serwerze:
sudo headscale auth register --user alice --auth-id PASTE-THE-ID-FROM-THE-PAGETen formularz jest wygodniejszy w przypadku własnego laptopa. Klucze preauth są lepsze dla wszelkich zadań skryptowych, ponieważ nie wymagają nadzoru człowieka. Gdy sam VPS stanie się węzłem, może również obsługiwać ruch internetowy Twoich pozostałych maszyn, co stanowi konfigurację węzła wyjściowego, z tą różnicą, że zatwierdzasz anonsowaną trasę na serwerze za pomocą polecenia headscale, zamiast robić to w hostowanej konsoli administracyjnej. Jeśli Twoim celem jest dostęp do sieci prywatnej znajdującej się za tym VPS-em, a nie wyjście do Internetu, ten sam krok zatwierdzenia obejmuje anonsowanie tej podsieci dla reszty Twojej sieci tailnet. Publikowanie pojedynczej aplikacji z węzła, zamiast trasowania przez niego całych sieci, to inne zadanie, a serve oraz funnel to dwa sposoby na jego realizację, choć oba opierają się na własnym mechanizmie certyfikatów i ruchu przychodzącego Tailscale, więc należy je traktować jako funkcje hostowanego tailnetu, a nie coś, co zapewnia headscale.
DERP oraz mechanizm przekazywania ruchu w przypadku niepowodzenia połączenia bezpośredniego
DERP (designated encrypted relay for packets) stanowi ścieżkę zapasową. Gdy dwa węzły nie mogą nawiązać bezpośredniego połączenia WireGuard, zazwyczaj z powodu pracy za restrykcyjnym NAT (network address translation), przesyłają pakiety za pośrednictwem przekaźnika. Przekaźnik nie posiada kluczy, więc nie może odczytać ruchu. Rejestruje jedynie, które węzły komunikują się ze sobą oraz ilość przesyłanych danych.
Należy jasno określić działanie konfiguracji domyślnej. Headscale jest dostarczany z ustawieniami wskazującymi na https://controlplane.tailscale.com/derpmap/default przy użyciu auto_update_enabled: true oraz update_frequency: 3h, co oznacza, że płaszczyzna sterowania należy do użytkownika, natomiast przekaźniki do Tailscale. Dla większości użytkowników jest to akceptowalny kompromis. Jeśli nie, należy uruchomić własny przekaźnik.
Aby uruchomić własny przekaźnik, należy ustawić enabled: true w sekcji derp.server pliku config.yaml, zastąpić domyślne ipv4: 198.51.100.1 oraz ipv6: 2001:db8::1 publicznymi adresami własnego przekaźnika lub usunąć oba ustawienia, aby skorzystać z DNS, a następnie zrestartować headscale i otworzyć port STUN (session traversal utilities for NAT) za pomocą sudo ufw allow 3478/udp. Ustawienia adresów nadpisują DNS, więc pozostawienie któregokolwiek z symboli zastępczych spowoduje kierowanie klientów na nieosiągalny adres. Plik konfiguracyjny jasno określa wymaganie: server_url musi używać https, ponieważ DERP wymaga TLS. Opróżnienie listy derp.urls usuwa przekaźniki Tailscale z mapy; przed wykonaniem tej czynności należy zapewnić działający wbudowany lub niestandardowy przekaźnik. Headscale nie uruchomi się z pustą mapą przekaźników, a mapa zawierająca tylko nieosiągalny przekaźnik uniemożliwi komunikację węzłom, które nie mogą połączyć się bezpośrednio.
Z poziomu klienta polecenie tailscale netcheck wyświetla opóźnienia do każdego znanego regionu przekaźników, a tailscale status pokazuje direct z adresem lub relay z kodem regionu dla aktywnych połączeń między węzłami. Węzeł zablokowany na relay wymaga sprawdzenia ścieżki bezpośredniej, w tym reguł NAT i zapory sieciowej. Węzeł o statusie direct, który nadal działa wolno, to odrębny problem, a typowa odpowiedź w takim przypadku dotyczy MTU, a nie samego tunelu.
Dlaczego węzeł jest widoczny jako offline?
Proxy odrzuca aktualizację. Sygnałem tego stanu jest sytuacja, w której /health zwraca 200, podczas gdy nowe rejestracje kończą się niepowodzeniem lub istniejące węzły nie mogą nawiązać połączenia. Połączenie sterujące to żądanie POST przesyłające Upgrade: tailscale-control-protocol; proxy, które go nie przekazuje, blokuje zarówno rejestrację, jak i kanał raportujący stan węzła. Należy porównać konfigurację nginx z powyższymi liniami dotyczącymi aktualizacji lub przejść na Caddy, aby wykluczyć problem z proxy.
Zmienił się publiczny adres sterujący. Węzły nieustannie próbują łączyć się z adresem skonfigurowanym za pomocą --login-server; zmiana server_url nie aktualizuje tego ustawienia po stronie klienta. Jeśli stary adres nie prowadzi już do serwera, należy uruchomić sudo tailscale up --login-server https://headscale.example.com --force-reauth na każdym węźle.
Klient nie jest uruchomiony. Na węźle należy sprawdzić sudo systemctl is-active tailscaled oraz sudo journalctl -u tailscaled -n 50 --no-pager. Klient, który nie może rozwiązać nazwy domeny lub połączyć się z nią, rejestruje tam swoje ponowne próby.
Klucz wygasł. Kwestia ta została omówiona w następnej sekcji.
Aby monitorować stronę serwera podczas testów, należy uruchomić sudo journalctl -u headscale -f na VPS i zrestartować tailscaled na kliencie. Warto również sprawdzić dziennik klienta: żądanie docierające do headscale nie zawsze generuje wpis przy domyślnym poziomie logowania, więc brak wpisów w logach serwera nie jest jednoznacznym dowodem na awarię DNS, firewalla lub proxy.
Wygasanie kluczy a węzeł, który przestaje działać po kilku tygodniach
Istnieją dwa oddzielne terminy wygasania, a ich mylenie powoduje stratę czasu.
Klucze preauth wygasają szybko zgodnie z założeniem. Wartość domyślna to jedna godzina i jedno użycie. Jeśli tailscale up odrzuca klucz, należy wygenerować nowy na serwerze, zamiast edytować cokolwiek po stronie klienta.
Klucze węzłów to długowieczna część konfiguracji. Sekcja node w config.yaml ustawia expiry: 0, a 0 oznacza brak domyślnego wygasania; nadal może mieć zastosowanie jawne wygaśnięcie klienta lub wygaśnięcie OIDC. Węzły z tagami są zwolnione z automatycznego wygasania, chociaż administrator może je wygasić ręcznie. Należy ustawić expiry: 180d, jeśli wymagane jest 180-dniowe domyślne wygasanie dla rejestracji bez tagów, jednak wygaśnięcie żądane przez klienta ma pierwszeństwo, a OIDC może nadpisać ustawienie domyślne. Zmiana tego ustawienia nie wpływa wstecznie na istniejące rejestracje. Węzeł z określonym czasem wygaśnięcia wymaga ponownego uwierzytelnienia przed upływem tego terminu przy użyciu sudo tailscale up --login-server https://headscale.example.com --force-reauth. Serwer typu headless, którego nikt nie uwierzytelni ponownie, zostanie usunięty z sieci po wygaśnięciu jego rejestracji.
W przypadku utraty laptopa należy wykonać te czynności ręcznie. sudo headscale nodes list pozwala uzyskać identyfikator, następnie sudo headscale nodes expire -i 3 wylogowuje dany węzeł, a sudo headscale nodes delete -i 3 całkowicie usuwa go z sieci.
Kopie zapasowe i aktualizacje
/var/lib/headscale oraz /etc/headscale łącznie stanowią cały serwer. Przed ich skopiowaniem należy zatrzymać usługę, ponieważ SQLite może wykonywać zapisy w locie, a baza danych skopiowana pod obciążeniem może być niespójna.
sudo systemctl stop headscale
sudo tar czf /root/headscale-state.tgz -C /var/lib headscale
sudo tar czf /root/headscale-config.tgz -C /etc headscale
sudo systemctl start headscale
sudo chmod 600 /root/headscale-*.tgzPrzenieś oba pliki poza serwer. Zawierają one klucze prywatne oraz wszystkie rejestracje, więc wymagają takiej samej ochrony jak sam serwer. kopie zapasowe restic z VPS opisuje, jak wykonywać to w sposób zaplanowany i zaszyfrowany.
Aktualizacje powtarzają proces instalacji: pobierz nowe .deb, sudo apt install ./headscale.deb, a następnie zrestartuj i ponownie uruchom testy is-active oraz /health. Od wersji 0.29 ścieżka aktualizacji jest rygorystyczna. Pomijanie wersji podrzędnej jest zablokowane, podobnie jak przywracanie starszej wersji podrzędnej. Przechodź o jedną wersję podrzędną na raz, wykonuj kopię zapasową przed każdym krokiem i najpierw przeczytaj informacje o wydaniu danej wersji, ponieważ to samo wydanie zmieniło zachowanie polityki ACL i przeniosło kilka kluczy konfiguracyjnych. Wersja 0.29.6 zawiera również aktualizacje bezpieczeństwa dotyczące walidacji certyfikatów i zależności, dlatego istniejące instalacje w wersji 0.29 powinny zainstalować to wydanie poprawkowe.
FAQ
Czy headscale działa od razu po instalacji pakietu .deb?
Tak. Pakiet uruchamia usługę natychmiast po instalacji, korzystając z dostarczonego pliku /etc/headscale/config.yaml, który nasłuchuje wyłącznie na interfejsie zwrotnym i ustawia server_url na http://127.0.0.1:8080. W przypadku świeżej instalacji usługa nie jest włączana automatycznie, więc nie uruchomi się przy starcie systemu, dopóki nie zostanie wykonane polecenie sudo systemctl enable headscale. Dostarczony adres jest bezużyteczny dla klientów, dlatego należy edytować server_url, listen_addr oraz base_domain, a następnie wykonać sudo systemctl restart headscale i potwierdzić za pomocą sudo systemctl is-active headscale. Musi to być restart: headscale odczytuje plik tylko podczas uruchamiania, a enable --now na działającej usłudze włącza ją jedynie do autostartu, nie restartując jej, przez co stare wartości pozostają aktywne. Jeśli po restarcie wystąpi błąd, sudo journalctl -u headscale -n 50 --no-pager wskaże przyczynę; na tym etapie niemal zawsze jest to błąd w pliku YAML, ponieważ headscale analizuje cały plik przed powiązaniem gniazda z portem.
Czy na moich maszynach nadal instaluję standardowego klienta Tailscale?
Tak. Headscale zastępuje jedynie serwer kontrolny. Każdy węzeł korzysta z oficjalnego klienta Tailscale, który wskazuje się na własny serwer za pomocą flagi sudo tailscale up --login-server https://headscale.example.com. Flaga ta istnieje w standardowym kliencie, więc nie ma potrzeby stosowania poprawek ani przebudowywania oprogramowania.
Czy mój ruch sieciowy przechodzi przez serwer headscale?
Zazwyczaj nie. Headscale koordynuje sieć oraz przydziela klucze i adresy, natomiast ścieżka danych to WireGuard działający bezpośrednio między węzłami. Ruch jest przekierowywany tylko wtedy, gdy dwa węzły nie mogą nawiązać bezpośredniego połączenia i muszą skorzystać z przekaźnika DERP; w domyślnej konfiguracji są to publiczne przekaźniki Tailscale. Uruchom tailscale status na węźle, aby sprawdzić, czy dany partner jest połączony direct, czy przez relay.
Dlaczego mój węzeł pozostaje w trybie offline po rejestracji?
Węzeł, który pojawia się w headscale nodes list, ale nie przechodzi w tryb online, wymaga sprawdzenia połączenia kontrolnego, w tym konfiguracji reverse proxy. Połączenie to jest żądaniem HTTP upgrade wysyłanym jako POST z nagłówkiem Upgrade: tailscale-control-protocol. Nginx odrzuca takie żądania, chyba że nagłówki Upgrade oraz Connection zostaną jawnie przekazane za pomocą proxy_set_header, co powyższa konfiguracja realizuje w bloku map $http_upgrade $connection_upgrade. Odrzucenie tych nagłówków uniemożliwia również rejestrację nowych węzłów. Caddy przekazuje je bez dodatkowej konfiguracji, co czyni go szybkim sposobem na sprawdzenie, czy przyczyną problemu jest proxy.
Czy do headscale potrzebuję nazwy domeny i TLS?
W tej konfiguracji tak: należy użyć nazwy domeny i HTTPS. Certyfikaty mogą obejmować również adresy IP, jednak plik konfiguracyjny wskazuje, że DERP wymaga TLS. Domena wraz z Caddy pozwala w około pięć minut uzyskać punkt końcowy HTTPS z automatycznym odnawianiem certyfikatów. Użycie zwykłego HTTP jest możliwe, ale dokumentacja headscale zdecydowanie zaleca HTTPS na porcie 443 w środowiskach produkcyjnych i zaznacza, że klient Tailscale w określonych sytuacjach zakłada użycie HTTPS na porcie 443.