1. Как работает Tailscale и зачем Headscale
Tailscale создаёт mesh-сеть на основе WireGuard: каждое устройство получает постоянный IP из диапазона 100.64.0.0/10 и видит остальные устройства сети напрямую. Не нужно открывать порты, настраивать маршруты или управлять WireGuard-ключами вручную.
Как это работает
Tailscale работает отлично, но контрол-сервер — в облаке Tailscale. Это означает зависимость от стороннего сервиса и ограничения бесплатного тарифа (3 пользователя, 100 устройств). Headscale — open source реализация того же контрол-сервера, которую вы запускаете на своём VPS. Клиенты остаются официальными — только указывают на ваш сервер вместо Tailscale.
| Параметр | Tailscale Cloud | Headscale self-hosted |
|---|---|---|
| Стоимость | Бесплатно до 3 юзеров / $6/мес за пользователя | Только стоимость VPS (~300 ₽/мес) |
| Узлов | 100 (бесплатно) | Без лимита |
| Пользователей | 3 (бесплатно) | Без лимита |
| Данные | Метаданные у Tailscale | Только на вашем сервере |
| Клиенты | Официальные Tailscale | Официальные Tailscale |
| Magic DNS | ✓ | ✓ |
| ACL | ✓ | ✓ |
| Надёжность | Managed SLA | Зависит от вашего VPS |
Версия Headscale в этом гайде — v0.28.0
Это актуальная стабильная версия (февраль 2025). В ней переработана система аутентификации и pre-auth ключи теперь хранятся в bcrypt-хеше — показываются только один раз при создании.
2. Требования к серверу
Headscale потребляет очень мало ресурсов — контрол-плейн занимается только координацией ключей, не пропуская через себя пользовательский трафик.
| Параметр | Минимум | Рекомендуется |
|---|---|---|
| CPU | 1 vCPU | 1 vCPU (достаточно для 100+ узлов) |
| RAM | 256 МБ | 512 МБ (с запасом для Nginx) |
| Диск | 5 ГБ | 10 ГБ |
| ОС | Ubuntu 22.04, Debian 12 | Ubuntu 22.04 LTS |
| Публичный IP | Обязателен | Статический IP |
| Домен | Обязателен | Поддомен: vpn.ваш-домен.ru |
Можно поставить на уже работающий VPS
Headscale отлично уживается с Nginx, Docker и другими сервисами. Контрол-сервер потребляет 20–50 МБ RAM в покое. Специальный VPS для Headscale не нужен — достаточно добавить его к существующему серверу.
3. Установка Headscale
Рекомендуемый способ — deb-пакет. Он автоматически создаёт системного пользователя, устанавливает конфиг по умолчанию и регистрирует systemd-сервис.
wget https://github.com/juanfont/headscale/releases/download/v0.28.0/headscale_0.28.0_linux_amd64.debsudo apt install ./headscale_0.28.0_linux_amd64.debПосле установки сервис ещё не запущен — сначала нужно отредактировать конфиг. Проверьте, что всё установилось корректно:
headscale version
# headscale v0.28.0Файлы после установки
- /etc/headscale/config.yaml — конфигурация
- /var/lib/headscale/ — база данных и ключи
- /var/run/headscale/ — unix-сокет
4. Настройка конфига
Откройте конфиг и измените ключевые параметры под ваш домен:
sudo nano /etc/headscale/config.yamlНайдите и измените следующие параметры (конфиг большой — используйте Ctrl+W для поиска):
# URL, по которому клиенты будут подключаться к вашему серверу
server_url: https://vpn.ваш-домен.ru
# Адрес для прослушивания (Nginx будет проксировать на этот порт)
listen_addr: 127.0.0.1:8080
# Метрики (опционально — для Prometheus)
metrics_listen_addr: 127.0.0.1:9090
# IP-диапазоны для узлов mesh-сети
ip_prefixes:
- 100.64.0.0/10
- fd7a:115c:a1e0::/48
# База данных (SQLite — подходит для домашнего и небольшого проф. использования)
database:
type: sqlite
sqlite:
path: /var/lib/headscale/db.sqlite
# DERP — публичные relay-серверы Tailscale (использовать бесплатно)
derp:
urls:
- https://controlplane.tailscale.com/derpmap/default
auto_update_enabled: true
update_frequency: 24h
# Magic DNS
dns:
magic_dns: true
base_domain: vpn.ваш-домен.ruВажно: base_domain ≠ server_url домен
server_url — домен контрол-сервера (vpn.ваш-домен.ru).base_domain — суффикс для Magic DNS имён устройств (server1.vpn.ваш-домен.ru). Они могут совпадать — это нормально.
5. Nginx + SSL
Headscale использует HTTP/2 и WebSocket — конфиг Nginx немного отличается от стандартного reverse proxy.
Шаг 1: добавить DNS-запись
vpn.ваш-домен.ru → A → IP_СЕРВЕРАШаг 2: конфиг Nginx
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name vpn.ваш-домен.ru;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name vpn.ваш-домен.ru;
# SSL — certbot заполнит эти строки автоматически
ssl_certificate /etc/letsencrypt/live/vpn.ваш-домен.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/vpn.ваш-домен.ru/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
# WebSocket и HTTP/2 upgrade
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_set_header X-Forwarded-Proto $scheme;
# Важно: отключить буферизацию для стриминга событий
proxy_buffering off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}Шаг 3: SSL-сертификат и запуск
# Активировать конфиг (пока без SSL — для certbot)
sudo ln -s /etc/nginx/sites-available/headscale /etc/nginx/sites-enabled/
# Временно переключить на HTTP для получения сертификата
# (замените listen 443 на listen 80, уберите ssl http2)
sudo nginx -t && sudo systemctl reload nginx
# Получить SSL-сертификат
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d vpn.ваш-домен.ru
# Запустить Headscale
sudo systemctl enable --now headscale
# Проверить статус
sudo systemctl status headscaleПосле успешного запуска проверьте, что сервер отвечает:
curl https://vpn.ваш-домен.ru/health
# {"status":"pass"}6. Подключение первого узла (Linux)
Сначала создадим пользователя (namespace) в Headscale и сгенерируем ключ аутентификации. Затем установим Tailscale-клиент на первый сервер.
На сервере с Headscale: создать пользователя
sudo headscale users create mynetsudo headscale preauthkeys create --user mynet --reusable --expiration 24hСохраните ключ — он выглядит как hskey-auth-xxxxxxxxxxxx-xxxxxxxx. После создания он больше не будет показан. Флаг --reusable позволяет использовать один ключ для нескольких узлов.
На подключаемом сервере: установить Tailscale
curl -fsSL https://tailscale.com/install.sh | shsudo tailscale up --login-server https://vpn.ваш-домен.ru --authkey hskey-auth-xxxxxxxxxxxx-xxxxxxxxПроверить регистрацию узла
sudo headscale nodes list
# ID | Hostname | Name | MachineKey | NodeKey | User | IP addresses | Status
# 1 | server1 | server1 | [abc...] | [def...]| mynet | 100.64.0.1, fd7a::1 | onlineУзел подключён! Он получил адрес из диапазона 100.64.x.x. Проверить связь между узлами можно командой tailscale ping 100.64.0.X.
7. Подключение Windows, macOS, Android, iOS
На устройствах без командной строки есть два способа входа — через ключ (как выше) или через браузер с последующим подтверждением на Headscale.
- 1Скачайте официальный Tailscale-клиент с tailscale.com/download.
- 2Зажмите Alt (Windows) или Option (macOS) и нажмите на иконку Tailscale в трее — появится пункт «Use custom server» / «Debug» → «Use custom control server».
- 3Введите: https://vpn.ваш-домен.ru и нажмите «Log in».
- 4Откроется браузер — скопируйте показанную команду и выполните её на сервере Headscale.
- 1Установите Tailscale из Play Store / App Store.
- 2Нажмите три точки → «Use custom control server» (Android) или Settings → Account → Log in with custom control server (iOS).
- 3Введите: https://vpn.ваш-домен.ru
- 4Завершите авторизацию, выполнив команду на Headscale.
Подтвердить узел через Headscale CLI
При входе через браузер (без pre-auth ключа) Tailscale показывает команду вида:
sudo headscale nodes register --user mynet --key nodekey:xxxxxxxxxx8. Magic DNS: обращение по имени хоста
С включённым Magic DNS все узлы сети доступны по коротким именам — не нужно помнить IP-адреса. Headscale автоматически настраивает DNS-суффикс на всех подключённых устройствах.
Как именуются узлы
server1100.64.0.1server1.vpn.ваш-домен.ruserver2100.64.0.2server2.vpn.ваш-домен.rulaptop100.64.0.3laptop.vpn.ваш-домен.ru# Пинг соседнего сервера по короткому имени
ping server2
# SSH на другой VPS без пароля (если настроены ключи)
ssh user@server2
# Curl к приложению на другом сервере
curl http://server2:8080/api/healthTailscale полностью заменяет /etc/hosts
Больше не нужно прописывать IP-адреса серверов в /etc/hosts. При добавлении нового узла в сеть он сразу становится доступен по имени на всех остальных узлах — Magic DNS обновляется автоматически.
9. Несколько VPS в приватной сети
Основной сценарий для Headscale — объединить несколько серверов в приватную сеть без открытых портов. Вот типичная топология:
# Пример инфраструктуры
┌─────────────────────────────────────────────────┐
│ Headscale VPS │
│ vpn.ваш-домен.ru (публичный) │
│ Tailscale IP: 100.64.0.1 │
└───────────────┬─────────────────────────────────┘
│ контрол-плейн (ключи, реестр)
┌────────┴────────┐
▼ ▼
┌────────────┐ ┌────────────┐
│ App VPS │◄──►│ DB VPS │
│ 100.64.0.2 │ │ 100.64.0.3 │
│ Нет откр. │ │ Нет откр. │
│ портов DB │ │ портов │
└────────────┘ └────────────┘
# Прямое WireGuard-соединение между App и DB VPS
# Трафик не идёт через Headscale VPS
Подключаем каждый VPS к Headscale с одним pre-auth ключом:
# Установить Tailscale
curl -fsSL https://tailscale.com/install.sh | sh
# Подключиться к вашей Headscale
sudo tailscale up --login-server https://vpn.ваш-домен.ru --authkey hskey-auth-xxxxxxxxxxxx-xxxxxxxxТеперь серверы видят друг друга по адресам 100.64.x.x. PostgreSQL на DB VPS больше не нужно выставлять наружу — подключайтесь изнутри сети:
# На App VPS — подключение к базе данных на DB VPS
psql -h db-vps -U myuser -d mydb
# db-vps разрешается через Magic DNS в 100.64.0.3🔒 Нет открытых портов
PostgreSQL, Redis, внутренние API — закрыты снаружи. Доступны только внутри сети Headscale.
⚡ Минимальная задержка
Трафик идёт напрямую между серверами по WireGuard, не через Headscale VPS.
🔑 Автоматическая ротация ключей
WireGuard-ключи ротируются автоматически — не нужно следить вручную.
Полезные команды управления
# Список всех узлов
sudo headscale nodes list
# Список пользователей
sudo headscale users list
# Создать ещё один reusable ключ (для новых серверов)
sudo headscale preauthkeys create --user mynet --reusable --expiration 7d
# Список ключей
sudo headscale preauthkeys list --user mynet
# Удалить узел из сети
sudo headscale nodes delete --id 3
# Статус на клиентском сервере
tailscale status