Headscale: власний сервер керування Tailscale
Запустіть власний сервер керування Tailscale на VPS: встановіть headscale з офіційного .deb, задайте server_url, перезапустіть сервіс і підключіть перший вузол.
Що таке headscale
Headscale — це self-hosted реалізація сервера керування Tailscale, тому машина, яка координує вашу приватну мережу, є VPS, яким ви володієте. Це спільнотний проєкт, який не керується компанією Tailscale Inc. Кожна машина все одно запускає офіційний клієнт tailscale, налаштований на ваш сервер за допомогою одного прапорця — --login-server.
Сервер керування — це компонент, який знає, хто належить до мережі. Він надає кожному вузлу адресу з 100.64.0.0/10, розповсюджує публічні ключі та повідомляє вузлам, де знайти один одного. Тунелі залишаються WireGuard, побудованими безпосередньо між вузлами. Трафік між двома вашими машинами не проходить через сервер headscale, якщо прямий шлях неможливо встановити і вузли не переходять на ретрансляцію (relay). Самостійне виконання ролі координатора змінює лише те, хто її виконує, а не її функціональні можливості, тому варто ознайомитися з тим, до чого сервер керування має і не має доступу в цій моделі, перш ніж розглядати цей перехід як самостійне рішення для підвищення безпеки.
Headscale обслуговує одну tailnet (одну мережу Tailscale) на один інстанс. Проєкт описує таку схему як придатну для особистого використання або невеликої організації. Якщо у вас три або чотири машини, звичайний WireGuard VPN на власному VPS потребує менше програмного забезпечення для обслуговування і створює менше можливостей для збоїв. Headscale стає виправданим, коли ви більше не хочете вручну створювати блок [Peer] для кожного нового ноутбука. Вартість часто є причиною, через яку користувачі починають шукати рішення, тому перед розгортанням сервера варто прочитати що саме покриває безкоштовний тариф для hosted-версії, оскільки кілька особистих машин зазвичай у нього вміщуються. Якщо ви вже перевищили цей ліміт, порівняйте витрати з вартістю платних тарифів на одного користувача й один ресурс із тегом, оскільки кількість пристроїв користувачів необмежена, а для ресурсів із тегами діють окремі ліміти та тарифи. Якщо вам потрібна self-hosted control plane, але ви віддаєте перевагу власному клієнту та вебінтерфейсу для керування пірами, а не прямій заміні Tailscale, варто розглянути NetBird на одному VPS як альтернативу. Обидва рішення передають ваш трафік через WireGuard, тому вибір залежить від способу написання правил доступу та поведінки relay-серверів. Перед інсталяцією будь-якого з них варто порівняти NetBird і Tailscale за цими критеріями. Для ширшого порівняння двох моделей див. чим відрізняються WireGuard і Tailscale.
Що потрібно перед встановленням
- VPS з ОС Ubuntu 24.04, публічною IPv4-адресою та доступом sudo. Якщо сервер новий, спочатку виконайте інструкції з перших десяти хвилин налаштування нового VPS.
- DNS-запис типу A, що вказує на цю адресу. У цьому посібнику використовується
headscale.example.com. - Другий домен або субдомен для MagicDNS. У цьому посібнику використовується
tailnet.example.net. Він не повинен збігатися з доменом, вказаним уserver_url. - Один клієнтський пристрій для підключення під керуванням Linux, macOS, Windows, Android або iOS. Headscale 0.29.6 потребує клієнт Tailscale версії 1.80.0 або новішої.
Встановлення headscale з офіційного пакета .deb
Проєкт публікує пакети .deb на сторінці GitHub releases. Станом на October 27, 2026 найновіший стабільний реліз — 0.29.6, випущений October 24, 2026. Спочатку перевірте свою архітектуру, оскільки її назва міститься в імені файлу.
sudo apt update
sudo apt install -y wget
dpkg --print-architectureЦя команда виводить amd64 на звичайному x86 VPS і arm64 на плані типу Ampere або Graviton. Запишіть результат у наведену нижче змінну.
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 versionПрефікс ./ перед іменем файлу обов’язковий. Без нього apt шукає у ваших репозиторіях пакет із назвою headscale.deb і завершується з помилкою.
Пакет створює системного користувача headscale, записує типовий файл /etc/headscale/config.yaml, встановлює unit systemd і запускає сервіс. Тому headscale уже працює, коли apt повертає результат, а sudo systemctl is-active headscale виводить active. Однак після свіжого встановлення пакет не вмикає unit, тому після перезавантаження сервіс не запуститься знову, доки ви не ввімкнете його. Це виконує наведений нижче крок перезапуску. Сервіс також працює з конфігурацією, що постачається разом із пакетом, і вона вказує server_url на http://127.0.0.1:8080 — адресу, до якої жоден ваш клієнт не може підключитися. Поки що назовні нічого не відкрито, оскільки listen_addr із пакета також прив’язаний до loopback, але не підключайте жоден клієнт, доки не налаштуєте server_url і не перезапустите сервіс. Це виконують наступні два кроки.
Налаштування server_url перед підключенням клієнтів
Відредагуйте /etc/headscale/config.yaml за допомогою sudo nano /etc/headscale/config.yaml або застосуйте ті самі три зміни через sed. Збережіть копію оригіналу, оскільки файл великий, містить багато коментарів і є найкращим довідником для решти налаштувань.
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 — це публічна адреса, яку використовує headscale під час створення URL-адрес для реєстрації. Клієнти використовують control address, налаштовану через --login-server, тому використовуйте однакову публічну назву з https:// в обох місцях, ніколи не використовуйте 127.0.0.1. Документація headscale зазначає, що можливе використання звичайного HTTP або HTTPS на порту, відмінному від 443, проте для продуктивного середовища наполегливо рекомендується HTTPS на порту 443, і саме цей варіант передбачається в цьому посібнику.
listen_addr — це адреса, на якій очікує з’єднання процес. Залиште її на loopback. Reverse proxy на тому самому сервері виконує TLS (transport layer security) termination і пересилає запити далі, тому зовнішнім клієнтам не потрібно мати прямий доступ до порту 8080.
base_domain — це суфікс MagicDNS, домен, у межах якого ваші вузли отримують імена. Це має бути повністю визначене доменне ім’я (FQDN) без крапки в кінці, і воно має відрізнятися від домену в server_url, інакше простори імен конфліктуватимуть.
Розділ бази даних не чіпайте. За замовчуванням використовується SQLite за шляхом /var/lib/headscale/db.sqlite у директорії, яку створив і обслуговує пакет; SQLite цілком достатньо для tailnet такого розміру.
Перезапустіть headscale і переконайтеся, що він працює
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 виводить active, is-enabled виводить enabled, а curl виводить 200. Саме перезапуск завантажує внесені зміни. Headscale зчитує конфігурацію один раз під час запуску, тому процес, запущений пакетом, продовжує використовувати встановлений пакетами server_url, доки ви його не перезапустите. sudo systemctl enable --now headscale не виконує це завдання: сервіс уже працює, тому команда --now start нічого не змінює, і старе значення залишається активним. Запуск під час завантаження системи забезпечує enable, але це не налаштовується автоматично: після нового встановлення пакет запускає сервіс без увімкнення автозапуску, тому один раз виконайте sudo systemctl enable headscale, як описано вище.
Якщо is-active виводить будь-що, крім active, або curl не виводить 200, перегляньте журнал за допомогою sudo journalctl -u headscale -n 50 --no-pager. На цьому етапі причиною майже завжди є файл конфігурації, оскільки headscale аналізує весь файл до відкриття сокета. Тому неправильний відступ або неприпустиме обов’язкове налаштування зупиняє процес ще до того, як він починає прослуховувати порт. Виправте файл, а потім виконайте sudo systemctl restart headscale. Кожна наступна зміна конфігурації потребує такого самого перезапуску. Після цього клієнти перепідключаються автоматично. Якщо ви ще не працювали з unit-файлами systemd, у розділі Запуск власних сервісів і таймерів за допомогою systemd описано команди, використані тут.
Перевірте файли стану, поки ви працюєте в shell:
stat -c '%U %n' /var/lib/headscale/db.sqlite /var/lib/headscale/noise_private.keyОбидва рядки починаються з headscale — непривілейованого користувача, якого створив пакет. noise_private.key — це ідентифікатор сервера для його клієнтів. Не видаляйте його. Якщо видалити цей файл, headscale згенерує новий і клієнтам доведеться отримати новий криптографічний ключ сервера перед повторним підключенням; наявні реєстрації залишаться в базі даних.
Налаштування TLS перед headscale
Клієнти повинні звертатися до server_url через HTTPS. Caddy — це найшвидший шлях, оскільки він самостійно запитує та поновлює сертифікат.
sudo apt install -y caddyЗамініть /etc/caddy/Caddyfile на блок із документації 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 виводить adapted config to JSON, якщо файл синтаксично правильний. Попередження про відсутність форматування є суто косметичним. З вашого ноутбука команда curl -sS -o /dev/null -w '%{http_code}\\n' https://headscale.example.com/health також має виводити 200. Ця єдина перевірка підтверджує, що DNS, фаєрвол, сертифікат і проксі працюють злагоджено.
Ось нюанс налаштування проксі, через який багато хто втрачає вечір. Керуюче з’єднання Tailscale — це HTTP upgrade, воно ініціюється через POST, а не GET, а значення заголовка Upgrade має бути tailscale-control-protocol. Caddy передає це без додаткових налаштувань. nginx цього не робить, тому фронтенд на базі nginx повинен явно передавати заголовки Upgrade та Connection. Документація headscale пропонує вирішення через карту оновлень (upgrade map):
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;
}
}Якщо пропустити ці рядки, звичайні запити все одно будуть успішними — саме тому /health повертає 200 і все виглядає справним, хоча керуюче з’єднання ніколи не встановлюється: нові вузли не можуть зареєструватися, а існуючі не можуть перепідключитися та повідомити про свій статус. Якщо ви обираєте шлях із nginx, Certbot на Ubuntu 24.04 з nginx допоможе налаштувати сертифікат.
Які порти відкрити в UFW
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verboseПорт 443 забезпечує кожне керуюче з’єднання клієнта з headscale. Якщо ви згодом увімкнете вбудоване реле DERP, йому також знадобиться 3478/udp, про що йдеться нижче. Порт 80 потрібен для HTTP-челенджу ACME (automatic certificate management environment) та перенаправлення на HTTPS. Caddy може отримати сертифікат і з закритим портом 80, оскільки він може використовувати TLS-ALPN челендж на порту 443, але з відкритим портом 80 доступні обидва методи, а звичайні запити http:// перенаправляються.
Порт 8080 має залишатися закритим. listen_addr — це 127.0.0.1:8080, тому проксі звертається до headscale через інтерфейс loopback, і правила фаєрволу тут не задіяні. Відкриття порту 8080 в UFW нічого не дасть, оскільки ззовні на ньому нічого не слухає, і це не приносить жодної користі. Пам’ятайте, що більшість провайдерів використовують другий фаєрвол у своїй панелі керування, окремо від UFW, тому порт може бути відкритий на сервері, але закритий на рівні мережі. Основи роботи з фаєрволом UFW на VPS детальніше описує синтаксис правил.
Створення користувача та preauth key
sudo headscale users create alice
sudo headscale users listКоманда headscale є клієнтом. Вона взаємодіє із запущеним daemon через unix socket за адресою /var/run/headscale/headscale.sock. Цей socket має режим 0770, а його власником є група headscale. З цього випливають два наслідки. Команда завершується помилкою, якщо сервіс зупинений. Це ще одна причина дотримуватися порядку дій у цьому посібнику. Також для виконання команди потрібен sudo, якщо ви не додасте власний обліковий запис до групи headscale.
Команда users list виводить ID поруч із кожним іменем. Вам потрібен цей номер, оскільки команда для роботи з key приймає числовий user ID, а не ім’я.
sudo headscale preauthkeys create --user 1 --expiration 24hKey виводиться лише один раз. Скопіюйте його зараз. Preauth key можна використати лише один раз, і за замовчуванням він дійсний протягом однієї години. Тому під час тестування варто налаштувати --expiration 24h. Додайте --reusable, щоб key міг зареєструвати кілька машин. Ставтеся до нього як до пароля, оскільки будь-хто, хто має цей key, може приєднатися до вашої мережі.
Підключення першого клієнта за допомогою --login-server
На машині, яку ви хочете додати:
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 виводить адресу, призначену headscale, наприклад 100.64.0.1. Повернувшись на сервер, sudo headscale nodes list покаже вузол з його ID, користувачем та статусом підключення.
Використовуйте публічну HTTPS-адресу з server_url для --login-server. Клієнт автоматично видаляє кінцеві слеші з URL керування; точне порівняння рядків не вимагає їх обов'язкового виключення.
Машина, яка раніше була підключена до сервісу Tailscale, зберігає цей логін. Спочатку виконайте на ній sudo tailscale logout, а потім запустіть tailscale up з --login-server.
Якщо ви не вкажете --auth-key, клієнт виведе URL-адресу. Відкрийте її, і на сторінці з'явиться ідентифікатор спроби реєстрації, який потрібно підтвердити на сервері:
sudo headscale auth register --user alice --auth-id PASTE-THE-ID-FROM-THE-PAGEЦя форма зручніша для вашого власного ноутбука. Preauth keys краще підходять для будь-яких скриптів, оскільки не потребують присутності користувача. Коли VPS стає вузлом, він також може передавати інтернет-трафік інших ваших машин, що відповідає налаштуванню exit node, з тією різницею, що ви підтверджуєте анонсований маршрут на сервері за допомогою команди headscale, а не в консолі адміністратора хмарного сервісу. Якщо вам потрібен доступ до приватної мережі за цим VPS, а не вихід в інтернет, той самий крок підтвердження дозволяє анонсувати цю підмережу для решти вашої tailnet. Публікація одного застосунку з вузла, замість маршрутизації цілих мереж через нього, є іншим завданням, і serve та funnel — це два способи зробити це, хоча обидва вони покладаються на механізми сертифікатів та вхідного трафіку Tailscale, тому розглядайте їх як функції хмарної tailnet, а не як інструменти, що надаються безпосередньо headscale.
DERP та механізм ретрансляції трафіку у разі відсутності прямого з’єднання
DERP (designated encrypted relay for packets) — це резервний шлях передачі даних. Коли два вузли не можуть встановити пряме з’єднання WireGuard (зазвичай через те, що обидва знаходяться за суворим NAT — network address translation), вони надсилають пакети через ретранслятор. Ретранслятор не має ключів, тому він не може прочитати ваш трафік. Він лише бачить, які вузли обмінюються даними та обсяг переданої інформації.
Важливо розуміти, як працює конфігурація за замовчуванням. Headscale постачається з налаштуваннями, що вказують на https://controlplane.tailscale.com/derpmap/default з auto_update_enabled: true та update_frequency: 3h, тому ваш control plane залишається під вашим контролем, а ретранслятори — під контролем Tailscale. Для більшості користувачів це прийнятний компроміс. Якщо ні — розгортайте власний ретранслятор.
Щоб запустити власний ретранслятор, встановіть enabled: true у розділі derp.server у файлі config.yaml, замініть стандартні ipv4: 198.51.100.1 та ipv6: 2001:db8::1 на публічні адреси вашого ретранслятора або видаліть обидва параметри для використання DNS. Після цього перезапустіть headscale та відкрийте порт STUN (session traversal utilities for NAT) за допомогою sudo ufw allow 3478/udp. Ці налаштування адрес мають пріоритет над DNS, тому залишення будь-якого з плейсхолдерів призведе до того, що клієнти намагатимуться підключитися до недоступної адреси. У файлі конфігурації чітко вказано вимогу: server_url має використовувати https, оскільки DERP вимагає TLS. Очищення списку derp.urls видаляє ретранслятори Tailscale з карти; перед цим переконайтеся, що у вас налаштований і працює вбудований або власний ретранслятор. Headscale не запуститься з порожньою картою ретрансляторів, а карта, що містить лише недоступний ретранслятор, унеможливить зв’язок для вузлів, які не можуть з’єднатися напряму.
На клієнтській стороні команда tailscale netcheck виводить затримку до кожного відомого регіону ретрансляції, а tailscale status показує direct з адресою або relay з кодом регіону для активних з’єднань між вузлами. Якщо вузол «застряг» на relay, необхідно перевірити прямий шлях, включаючи правила NAT та firewall. Якщо вузол використовує direct, але з’єднання все одно повільне — це інша проблема, і зазвичай причина криється в MTU, а не в самому тунелі.
Чому вузол відображається як офлайн?
Проксі відхиляє оновлення. Ознакою цього є те, що /health повертає 200, тоді як нові реєстрації не вдаються або існуючі вузли не можуть відновити з’єднання. Керуюче з’єднання — це POST-запит, що містить Upgrade: tailscale-control-protocol, і проксі, який не пересилає його, блокує як реєстрацію, так і канал, що повідомляє про стан вузла. Порівняйте свою конфігурацію nginx із наведеними вище рядками для оновлення або перейдіть на Caddy, щоб виключити вплив проксі.
Змінилася публічна адреса керування. Вузли продовжують звертатися за адресою, налаштованою за допомогою --login-server; зміна server_url не оновлює це налаштування на клієнті. Якщо стара адреса більше не веде до вашого сервера, виконайте sudo tailscale up --login-server https://headscale.example.com --force-reauth на кожному вузлі.
Клієнт не запущений. На вузлі виконайте sudo systemctl is-active tailscaled та sudo journalctl -u tailscaled -n 50 --no-pager. Клієнт, який не може розпізнати або досягти вашого домену, записує свої спроби повторного підключення в журнал.
Термін дії ключа закінчився. Це питання розглянуто в наступному розділі.
Щоб моніторити стан сервера під час тестування, виконайте sudo journalctl -u headscale -f на VPS і перезапустіть tailscaled на клієнті. Перевірте також журнал клієнта: запит, що надходить до headscale, не обов’язково створює рядок у журналі за стандартного рівня деталізації, тому відсутність записів у журналі сервера сама по собі не доводить проблему з DNS, фаєрволом або проксі.
Термін дії ключів та вузол, що припиняє роботу через кілька тижнів
Існує два окремі терміни дії, і їх плутанина призводить до марнування часу.
Preauth-ключі за задумом мають короткий термін дії. Стандартно це одна година та одне використання. Якщо tailscale up відхиляє ключ, згенеруйте новий на сервері, замість того щоб редагувати будь-що на клієнті.
Ключі вузлів — це довготривала частина. Розділ node у config.yaml задає expiry: 0, а 0 означає відсутність стандартного терміну дії; проте явний термін дії для клієнта або термін дії OIDC все одно можуть застосовуватися. Теговані вузли звільнені від автоматичного закінчення терміну дії, хоча адміністратор може примусово завершити його. Встановіть expiry: 180d, якщо ви хочете мати стандартний термін у 180 днів для реєстрацій без тегів, але термін, запитаний клієнтом, має пріоритет, а OIDC може перевизначити стандартне значення. Зміна цього налаштування не впливає на вже існуючі реєстрації. Вузол із терміном дії потребує повторної автентифікації до настання цього терміну за допомогою sudo tailscale up --login-server https://headscale.example.com --force-reauth, і headless-сервер, який ніхто не переавтентифікує, випаде з мережі, коли його реєстрація закінчиться.
Виконуйте це вручну, коли хтось втрачає ноутбук. sudo headscale nodes list надає вам ID, потім sudo headscale nodes expire -i 3 виконує вихід цього вузла, а sudo headscale nodes delete -i 3 повністю видаляє його з мережі.
Резервне копіювання та оновлення
/var/lib/headscale та /etc/headscale разом складають весь сервер. Зупиніть сервіс перед копіюванням, оскільки SQLite може виконувати запис у цей момент, і база даних, скопійована під навантаженням, може виявитися неузгодженою.
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-*.tgzПеренесіть обидва файли за межі сервера. Вони містять приватні ключі та всі реєстрації, тому потребують такого ж захисту, як і сам сервер. резервне копіювання restic з VPS описує налаштування цього процесу за розкладом із шифруванням.
Оновлення повторюють процес встановлення: завантажте нові .deb, sudo apt install ./headscale.deb, після чого перезапустіть і повторно виконайте перевірки is-active та /health. Починаючи з версії 0.29, шлях оновлення є суворим. Пропуск мінорної версії заблоковано, як і відкат до старішої мінорної версії. Оновлюйтеся по одній мінорній версії за раз, робіть резервну копію перед кожним кроком і спочатку читайте примітки до випуску відповідної версії, оскільки той самий реліз змінив поведінку політики ACL і перемістив кілька ключів конфігурації. Версія 0.29.6 також містить оновлення безпеки для перевірки сертифікатів і залежностей, тому наявні інсталяції 0.29 повинні встановити цей патч.
FAQ
Чи вже запущено headscale одразу після встановлення .deb?
Так. Пакет запускає сервіс одразу після встановлення з параметром /etc/headscale/config.yaml, який приймає з’єднання лише через loopback і встановлює server_url у значення http://127.0.0.1:8080. Після нового встановлення сервіс не вмикається для автозапуску, тому під час завантаження системи він не запускатиметься, доки ви не виконаєте sudo systemctl enable headscale. Адреса, встановлена за замовчуванням, непридатна для клієнтів, тому відредагуйте server_url, listen_addr і base_domain, потім виконайте sudo systemctl restart headscale і перевірте результат за допомогою sudo systemctl is-active headscale. Значення має бути restart: headscale читає файл лише під час запуску, а enable --now для вже запущеного сервісу вмикає автозапуск, але не перезапускає сервіс, тому старі значення залишаються активними. Якщо після перезапуску виникла помилка, sudo journalctl -u headscale -n 50 --no-pager покаже її причину. На цьому етапі це майже завжди помилка YAML, оскільки headscale аналізує весь файл до прив’язування до порту.
Чи потрібно встановлювати звичайний клієнт Tailscale на моїх машинах?
Так. Headscale замінює лише сервер керування. На кожному вузлі працює офіційний клієнт Tailscale, якому ви вказуєте свій сервер за допомогою sudo tailscale up --login-server https://headscale.example.com. Цей прапорець є у стандартному клієнті, тому нічого не потрібно виправляти або збирати повторно.
Чи проходить мій трафік через сервер headscale?
Зазвичай ні. Headscale координує мережу та розподіляє ключі й адреси, а передавання даних відбувається безпосередньо між вузлами через WireGuard. Трафік обходить прямий маршрут лише тоді, коли два вузли не можуть напряму встановити з’єднання й переходять на ретранслятор DERP. У конфігурації, встановленій за замовчуванням, це публічні ретранслятори Tailscale. Виконайте tailscale status на вузлі, щоб перевірити, чи є певний вузол-учасник direct або використовує relay.
Чому мій вузол залишається офлайн після реєстрації?
Якщо вузол відображається в headscale nodes list, але ніколи не переходить у стан онлайн, потрібно перевірити його керувальне з’єднання, зокрема reverse proxy. Це з’єднання є оновленням HTTP, яке надсилається методом POST із заголовком Upgrade: tailscale-control-protocol. nginx відкидає його, якщо явно не передати заголовки Upgrade і Connection за допомогою proxy_set_header. Наведена вище конфігурація робить це через блок map $http_upgrade $connection_upgrade. Відкидання цих заголовків також перешкоджає реєстрації нових вузлів. Caddy передає це з’єднання без додаткової конфігурації, тому він дає змогу швидко перевірити, чи є причиною проблема в reverse proxy.
Чи потрібні для headscale доменне ім’я та TLS?
Для цієї конфігурації так: використовуйте доменне ім’я та HTTPS. Сертифікати також можуть охоплювати окремі IP-адреси, але у файлі конфігурації зазначено, що DERP потребує TLS. Доменне ім’я разом із Caddy налаштовується приблизно за п’ять хвилин і надає кінцеву точку HTTPS з автоматичним поновленням. Звичайний HTTP можливий, але документація headscale наполегливо рекомендує HTTPS на порту 443 для production і зазначає, що в певних ситуаціях клієнт Tailscale очікує HTTPS на порту 443.