Запускаем Headscale с пользовательским интерфейсом в контейнере Docker
KrakenВ этой статье покажем, как запустить Headscale и Headscale UI с помощью контейнеров Docker.
Что такое Headscale
Решение с открытым исходным кодом, альтернатива серверу координации Tailscale. Его особенность: возможность самостоятельного размещения в собственной инфраструктуре.
Устанавливаем Headscale
1. Проверяем версию Docker Engine установлен и работает:
docker --version Docker version 24.0.5, build ced0996
2. Проверяем, установлен ли плагин compose:
<docker compose version Docker Compose version v2.20.2
3. Cоставляем файл Docker Compose
Нам нужно создать каталог, в котором будут храниться конфигурации и данные Headscale.
Как узнать, что находится в образах контейнеров:
mkdir -p ~/headscale && cd ~/he
Создаём пустую базу данных SQlite в каталоге headscale:
touch ./config/db.sqlite
Создаём новый файл с именем docker-compose.yml
vim docker-compose.yml
Вставляем и изменяем приведенное ниже содержимое
version: '3.9' services: headscale: container_name: headscale image: headscale/headscale:latest command: headscale serve restart: unless-stopped ports: - 8080:8080 - 9090:9090 volumes: - ./config:/etc/headscale/ - ./data:/var/lib/headscale/ headscale-ui: container_name: headscale-ui image: ghcr.io/gurucomputing/headscale-ui:latest pull_policy: always restart: unless-stopped ports: - 9080:80
В нашем файле compose мы:
- Монтируем config/ → /etc/headscale
- Монтируем data/ в каталоге → /var/lib/headscale/
- Переадресовываем порт 8080 из контейнера headscale, чтобы экземпляр headscale стал доступен
- Переадресовывем порт 9080 из контейнера headscale-ui, чтобы экземпляр headscale-ui стал доступен.
- При использовании https в пользовательском интерфейсе прописываем отдельные порты
- 9443:443
4. Запускаем контейнеры Headscale
— Загружаем файл шаблона конфигурации:
mkdir {config,data} wget https://raw.githubusercontent.com/juanfont/headscale/main/config-example.yaml -O config/config.yaml
— Перед запуском меняем конфигурационный файл в соответствии со своими предпочтениями. Вот на всякий некоторые настройки:
# Изменение имени хоста или IP-адреса хоста # server_url: //vpn.itsecforu.ru:8080 server_url: http://192.168.20.11:8080 # Слушать 0.0.0.0, чтобы он был доступен за пределами контейнера metrics_listen_addr: 0.0.0.0:9090
— Запускаем контейнеры с помощью команды docker compose.
docker compose up -d [+] Running 19/19 headscale-ui 13 layers [⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿] 0B/0B Pulled 3.2s 8921db27df28 Pull complete 0.5s 5e0dab5e7f18 Pull complete 0.5s e7466e9238c6 Pull complete 0.5s 9aca5eef2d98 Pull complete 0.7s 4f4fb700ef54 Pull complete 0.8s 5007d4d43f68 Pull complete 0.8s 2ebc6f305da4 Pull complete 1.0s 712d06ffc498 Pull complete 1.1s ac473b17e437 Pull complete 1.7s 36f5767e6555 Pull complete 1.7s 7c6ac0210a21 Pull complete 1.8s 7765e166cec5 Pull complete 1.8s 896f16a8f15c Pull complete 2.0s headscale 4 layers [⣿⣿⣿⣿] 0B/0B Pulled 4.4s 9e3ea8720c6d Pull complete 2.3s 71273269cd97 Pull complete 2.4s 007b622b7a95 Pull complete 2.5s 50a37fbfee41 Pull complete 2.5s [+] Running 3/3 Network headscale_default Created 0.1s Container headscale-ui Started 0.6s Container headscale Started
Опция -d → отсоединение, поэтому они будут работать в фоновом режиме.
— Проверяем состояние созданных контейнеров:
docker compose ps NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS headscale headscale/headscale:latest "headscale serve" headscale 45 seconds ago Up 43 seconds 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp, 0.0.0.0:9090->9090/tcp, :::9090->9090/tcp headscale-ui ghcr.io/gurucomputing/headscale-ui:latest "/bin/sh -c '/bin/sh…" headscale-ui 45 seconds ago Up 43 seconds 443/tcp, 0.0.0.0:9080->80/tcp, :::9080->80/tcp
— Когда мы запустили логи контейнера, можно проследить, что там творится внутри:
docker logs --follow headscale 2023-10-05T23:29:19Z INF go/src/headscale/hscontrol/protocol_common.go:574 > Successfully sent auth url AuthURL=http://192.168.20.11:8080/register/nodekey:af52937e8bc375a0d73a01cd453fd2f814144796b0270cedb0d126a39518c306 machine=jammy noise=true docker logs --follow headscale-ui no Caddyfile detected, copying across default config Starting Caddy {"level":"info","ts":1696545638.4848695,"msg":"using provided configuration","config_file":"/data/Caddyfile","config_adapter":"caddyfile"} {"level":"info","ts":1696545638.4858341,"logger":"admin","msg":"admin endpoint started","address":"localhost:2019","enforce_origin":false,"origins":["//localhost:2019","//[::1]:2019","//127.0.0.1:2019"]} {"level":"info","ts":1696545638.4859416,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0xc000544fc0"} {"level":"info","ts":1696545638.486509,"logger":"http","msg":"server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS","server_name":"srv0","https_port":443} {"level":"warn","ts":1696545638.4865189,"logger":"http","msg":"automatic HTTP->HTTPS redirects are disabled","server_name":"srv0"} {"level":"warn","ts":1696545638.4865253,"logger":"http","msg":"server is listening only on the HTTP port, so no automatic HTTPS will be applied to this server","server_name":"srv1","http_port":80} {"level":"info","ts":1696545638.4865966,"logger":"pki.ca.local","msg":"root certificate trust store installation disabled; unconfigured clients may show warnings","path":"storage:pki/authorities/local/root.crt"} {"level":"warn","ts":1696545638.4866195,"logger":"tls","msg":"YOUR SERVER MAY BE VULNERABLE TO ABUSE: on-demand TLS is enabled, but no protections are in place","docs":"https://caddyserver.com/docs/automatic-https#on-demand-tls"} {"level":"info","ts":1696545638.48668,"logger":"http.log","msg":"server running","name":"srv1","protocols":["h1","h2","h3"]} {"level":"info","ts":1696545638.486689,"logger":"tls","msg":"cleaning storage unit","description":"FileStorage:/home/appuser/.local/share/caddy"} {"level":"info","ts":1696545638.4867213,"logger":"http","msg":"enabling HTTP/3 listener","addr":":443"} {"level":"info","ts":1696545638.4867342,"logger":"tls","msg":"finished cleaning storage units"} {"level":"info","ts":1696545638.4867566,"msg":"failed to sufficiently increase receive buffer size (was: 208 kiB, wanted: 2048 kiB, got: 416 kiB). See https://github.com/lucas-clemente/quic-go/wiki/UDP-Receive-Buffer-Size for details."} {"level":"info","ts":1696545638.4868112,"logger":"http.log","msg":"server running","name":"srv0","protocols":["h1","h2","h3"]} {"level":"info","ts":1696545638.486932,"msg":"autosaved config (load with --resume flag)","file":"/home/appuser/.config/caddy/autosave.json"} {"level":"info","ts":1696545638.4869497,"msg":"serving initial configuration"}
— Команда ss используем для проверки привязки портов на хосте.
ss -tunlp|egrep '8080|9080'
5. Получаем доступ к оболочке контейнера
Тут нам нужна команда:
docker exec -ti headscale bash
А это для headscale-ui:
docker exec -ti headscale-ui sh
Мы можем протестировать функциональность, создав пользователя на инстансе Headscale:
root@4f2fbe02c029:/# headscale use
А вот вид однострочной команды без входа в оболочку:
$ docker exec headscale \ headscale users create myuser
6. Даём доступ к пользовательскому интерфейсу Headscale
— Генерируем API-ключ на сервере Headscale.
docker exec headscale \ headscale apikeys create --expiration 120d
Вот как примерно будет:
8bnNOGwOkw.bjQXvEB4Vk9Ia1R9HupEB0yB9PFthth_Or8QcHncKmw
Подписывайтесь на нас:
Telegram: https://t.me/kraken_sec
VK: https://vk.com/kraken.security
А ещё мы проводим обучение: https://kraken-academy.ru/