Headscale сервер вполне можно использовать в stand-alone варианте без провайдера пользователей (identity provider), по типу Authentik. Однако пользователей придется создавать вручную через cli или панель, если таковая у вас установлена. В данном случае мы рассмотрим настройку headscale с использованием OIDC авторизации через Authentik.

Настройка Authentik

Создаем новое приложение с провайдером. Из опций провайдера выбираем OAuth/OpenID Connect

В настройках провайдера выбираем предпочитаемый вами authorization consent, и добавляем Redirect URI. Для headscale этим uri будет https://domain.com/oidc/callback, где domain.com - ваш домен.

Сохраняем приложение и провайдер, копируя в конфиг сгенерированные client id и client secret.

Деплой Headscale

В первую очередь необходимо создать в любом удобном месте на диске директорию для compose проекта. В ней создаем файл docker-compose.yml и записываем в него описанный здесь проект.

Далее создаем директорию headscale-config и файл config.yaml в нем. Туда записываем sample config, который можно взять здесь. В нем есть несколько полей, которые необходимо изменить.

## домен, по которому будет доступен headscale.
#  можно указать ip адрес и порт,
#  если не планируете использовать домен
server_url: https://headscale.domain
 
dns:
  base_domain: some.domain ## домен для нод внутри tailnet
 
## здесь необходимо заменить authentik.outpost на домен вашего authentik
#  и заполнить поля client_id и client_secret значениями из authentik
oidc:
  only_start_if_oidc_is_available: true
  issuer: "https://authentik.outpost/application/o/headscale/"
  client_id: ""
  client_secret: ""

После этого можно запустить проект командой docker compose up -d. При успешном запуске контейнера можно проверить работоспособность headscale, перейдя по ссылке https://headscale.domain/windows.

WARNING

Важно - для доступа к headscale по https вам необходимо либо выпустить сертификаты домена и передать их headscale в конфиге, либо использовать reverse proxy

Если при установке все сделано правильно, то по выше указанной ссылке вы должны увидеть следующую страницу:

Reverse proxy

В данном случае мы рассматриваем установку headscale с использованием reverse-proxy, поэтому в docker-compose headscale выходит на порт 8080. Основными вариантами reverse-proxy являются caddy и nginx. При использовании nginx потребуется наличие сертификатов для домена, получение которых мы здесь рассматривать не будем.

Caddy

Для caddy потребуется добавить совсем маленький блок конфигурации в /etc/caddy/Caddyfile:

headscale.domain {
        reverse_proxy * localhost:8080
}

где headscale.domain - домен, по которому будет доступен ваш headscale сервер.

Внимание

Домен в конфигурации caddy и поле server_url в конфиге headscale должны совпадать!

Nginx

В случае с nginx конфиг выглядит уже менее просто и локонично:

map $http_upgrade $connection_upgrade {
    default      upgrade;
    ''           close;
}
 
server {
    listen 80;
    listen [::]:80;
 
    listen 443      ssl http2;
    listen [::]:443 ssl http2;
 
    server_name headscale.domain;
 
    ssl_certificate <PATH_TO_CERT>;
    ssl_certificate_key <PATH_CERT_KEY>;
    ssl_protocols TLSv1.2 TLSv1.3;
 
    location / {
        proxy_pass http://localhost:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Host $server_name;
        proxy_redirect http:// https://;
        proxy_buffering off;
        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;
        add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
    }
}

где headscale.domain - домен, по которому будет доступен ваш headscale сервер.

Настройка панели headplane

Открываем (или создаем, если еще не существует) файл config.yaml в корне compose проекта. Туда записываем дефолтный конфиг, который можно взять здесь. В нем редактируем следующие поля:

server:
  ## здесь должна быть строка случайных символов.
  #  сгенерировать такую можно командой
  #  openssl rand --base64 32
  cookie_secret: "рандомная строка"
 
  ## заполняем этот блок теми же данными, что и аналогичный блок
  #  в конфигурации headscale
oidc:
  issuer: "https://authentik.outpost/application/o/headplane/"
  client_id: ""
  client_secret: ""
 
  disable_api_key_login: true
  token_endpoint_auth_method: "client_secret_post"
 
  # headscale apikeys create --expiration 999d
  headscale_api_key: ""
 
  ## меняем домен на тот, по которому доступен ваш headscale сервер
  redirect_uri: "https://headscale.domain/admin/oidc/callback"

и добавляем https://headscale.domain/admin/oidc/callback в redirect uris в настройках провайдера authentik. После этого добавляем настройку проксирования панели в вашем reverse proxy:

# caddy
headscale.domain {
        reverse_proxy * localhost:8080
+       reverse_proxy /admin* http://localhost:3037
}
 
# nginx
server {
    listen 80;
    listen [::]:80;
 
    listen 443      ssl http2;
    listen [::]:443 ssl http2;
 
    server_name headscale.domain;
 
    ssl_certificate <PATH_TO_CERT>;
    ssl_certificate_key <PATH_CERT_KEY>;
    ssl_protocols TLSv1.2 TLSv1.3;
 
    location / {
        proxy_pass http://localhost:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Host $server_name;
        proxy_redirect http:// https://;
        proxy_buffering off;
        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;
        add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
    }
+   location /admin {
+       proxy_pass http://localhost:3037;
+       proxy_http_version 1.1;
+       proxy_set_header Upgrade $http_upgrade;
+       proxy_set_header Connection $connection_upgrade;
+       proxy_set_header Host $server_name;
+       proxy_redirect http:// https://;
+       proxy_buffering off;
+       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;
+       add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
+   }
}

Теперь по ссылке https://headscale.domain/admin будет открываться панель headplane.

Дополнительные заметки