Como executar o Headscale com UI no Docker Container
Neste artigo, demonstramos como você pode executar Headscale e Headscale UI usando Docker Containers. Nosso artigo recente foi específico para a instalação do Headscale no sistema Ubuntu Linux usando o pacote .deb
. O link para a postagem é compartilhado no link abaixo.
- Instale e configure o Headscale no Ubuntu
Se você não prefere a instalação do Headscale baseada em pacote, este artigo foi desenvolvido para você. Headscale é uma solução alternativa muito poderosa e de código aberto para o servidor de coordenação Tailscale. Ele foi desenvolvido para ser auto-hospedado em sua própria infraestrutura. Headscale é desenvolvido de forma independente e não tem nenhum relacionamento com a empresa Tailscale, exceto ser uma versão reimplementada do servidor de coordenação Tailscale.
Siga as etapas compartilhadas nesta postagem do blog para configurar um servidor Headscale dedicado em execução no contêiner Docker. O mesmo procedimento pode ser reutilizado para a configuração do Podman/Podman Compose com poucas modificações. Também incluímos a instalação da UI Headscale no docker.
1) Instale o Docker Engine
Comece sua configuração garantindo que o Docker Engine esteja instalado e funcionando. Consulte o guia a seguir sobre instalação do Docker em sistemas Linux.
- Como instalar o Docker CE em sistemas Linux
Depois de instalado, você pode verificar a versão.
$ docker --version
Docker version 24.0.7, build afdd53b
Verifique também se o plugin de composição está instalado.
$ docker compose version
Docker Compose version v2.21.0
2) Definir arquivo Docker Compose
Vamos criar um diretório que armazene configurações e dados do Headscale.
mkdir -p ~/headscale && cd ~/headscale
Crie uma base de dados SQLite vazia no diretório headscale:
mkdir ./config
touch ./config/db.sqlite
Crie um novo arquivo chamado docker-compose.yml
vim docker-compose.yml
Cole e modifique o conteúdo abaixo. Se você não precisa do Headscale em execução no contêiner Docker, remova suas seções.
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
Em nosso arquivo de composição estamos:
- Montagem
config/
em/etc/headscale
- Montando
data/
em/var/lib/headscale/
- Encaminhamento da porta 8080 do contêiner headscale para que a instância
headscale
fique disponível - Encaminhando a porta 9080 do contêiner headscale-ui para que a instância
headscale-ui
fique disponível
Se estiver usando https na IU, você pode mapear portas separadas conforme abaixo.
- 9443:443
3) Inicie contêineres Headscale
Baixe o arquivo de modelo de configuração.
mkdir {config,data}
wget https://raw.githubusercontent.com/juanfont/headscale/main/config-example.yaml -O config/config.yaml
Modifique o arquivo de configuração de acordo com suas preferências antes de iniciar o contêiner Docker. Aqui estão algumas configurações que você provavelmente deseja:
# Change to your hostname or host IP
# server_url: //vpn.computingforgeeks.com:8080
server_url: http://192.168.20.11:8080
# Listen to 0.0.0.0 so it's accessible outside the container
metrics_listen_addr: 0.0.0.0:9090
Inicie os contêineres usando o comando docker compose
. A opção -d
significa desanexar para que sejam executados em segundo plano.
$ 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
Verifique o status dos contêineres criados.
$ 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
Você pode seguir os logs do contêiner para ver o que está acontecendo lá dentro executando.
$ 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"}
O comando ss
pode ser usado para verificar se as portas do host estão vinculadas.
$ ss -tunlp|egrep '8080|9080'
tcp LISTEN 0 4096 0.0.0.0:9080 0.0.0.0:* users:(("docker-proxy",pid=364448,fd=4))
tcp LISTEN 0 4096 0.0.0.0:8080 0.0.0.0:* users:(("docker-proxy",pid=364428,fd=4))
tcp LISTEN 0 4096 [::]:9080 [::]:* users:(("docker-proxy",pid=364455,fd=4))
tcp LISTEN 0 4096 [::]:8080 [::]:* users:(("docker-proxy",pid=364434,fd=4))
4) Acesse o shell do contêiner
Você pode acessar o shell do contêiner headscale
executando:
docker exec -ti headscale bash
Para execução do headscale-ui:
docker exec -ti headscale-ui sh
Podemos testar a funcionalidade criando um usuário na instância Headscale.
root@4f2fbe02c029:/# headscale users create computingforgeeks
Será uma execução de comando de uma linha sem entrar no shell do contêiner.
docker exec headscale \
headscale users create myuser
5) Junte-se a dispositivos clientes à rede Headscale
Você precisa de um usuário criado em seu servidor Headscale. Criaremos um chamado computingforgeeks.
$ docker exec headscale headscale users create computingforgeeks
User created
Instalando clientes Tailscale em seus dispositivos
- Cliente Windows
- iOS
- Android
- Linux
- Mac OS
Instalando Tailscale no Linux/BSD
Para sistemas baseados em Linux e BSD, execute os comandos:
curl -fsSL https://tailscale.com/install.sh | sudo sh
A verificação da versão do Tailscale pode ser feita com os comandos abaixo.
$ tailscale --version
1.50.1
tailscale commit: f45c02bfcf5ee5790c3af278c9e974c9b9b0e771
other commit: 36a20760a45bd1936686879b34c35146cc0c4ec1
go version: go1.21.1
Instalando no macOS
Você pode instalar usando o Homebrew:
brew install tailscale
Ou executando o script.
curl -fsSL https://tailscale.com/install.sh | sudo sh
Registrar uma máquina (login normal)
Em uma máquina cliente, execute o comando de login tailscale
:
tailscale up --login-server YOUR_HEADSCALE_URL
Veja o exemplo abaixo.
# tailscale up --login-server http://192.168.20.11:8080
To authenticate, visit:
http://192.168.20.11:8080/register/nodekey:410155d1792d0f81a5f39415a1a418f882208751570c2e5195f7a6842ca44e6a
A abertura dos links fornece comandos a serem executados no servidor Headscale para registrar o dispositivo.
Listando todos os usuários criados no servidor Headscale:
$ docker exec headscale headscale user list
ID | Name | Created
1 | computingforgeeks | 2023-10-05 22:50:40
2 | myuser | 2023-10-05 22:52:18
3 | user2 | 2023-10-05 22:59:03
Lembre-se de substituir USERNAME pelo seu nome de usuário válido ao executar os comandos.
$ docker exec headscale \
headscale nodes register --user computingforgeeks --key nodekey:410155d1792d0f81a5f39415a1a418f882208751570c2e5195f7a6842ca44e6a
Machine rocky8 registered
A sintaxe geral no registro de uma máquina usando headscale
é:
docker exec headscale \
headscale --user <username> nodes register --key <YOU_+MACHINE_KEY>
Listando todas as máquinas adicionadas à rede mesh Headscale.
# docker exec headscale headscale node list
ID | Hostname | Name | MachineKey | NodeKey | User | IP addresses | Ephemeral | Last seen | Expiration | Online | Expired
1 | jammy | jammy | [cN/Um] | [r1KTf] | computingforgeeks | 100.64.0.1, fd7a:115c:a1e0::1 | false | 2023-10-05 23:39:04 | 0001-01-01 00:00:00 | online | no
Registre a máquina usando uma chave pré-autenticada
Você também pode registrar uma nova máquina usando uma chave pré-autenticada.
Primeiro gere uma chave usando a linha de comando:
docker exec headscale \
headscale --user <username> preauthkeys create --reusable --expiration 24h
A execução do comando retorna uma chave pré-autenticada usada para conectar um nó ao headscale
ao executar o comando tailscale
:
tailscale up --login-server <YOUR_HEADSCALE_URL> --authkey <YOUR_AUTH_KEY>
Vejamos o exemplo abaixo.
# On Headscale server
# docker exec headscale headscale --user jkmutai preauthkeys create --reusable --expiration 24h
4763c4f4293b260eff230065378e5668c13db44f4569ed7b
# On Machine to be registered
# tailscale up --login-server http://vpn.hirebestengineers.com --authkey 4763c4f4293b260eff230065378e5668c13db44f4569ed7b
O comando de registro da máquina com chave pré-autenticada não fornece saída. Mas você pode confirmar se novos nós foram adicionados a partir da CLI do servidor Headscale.
# docker exec headscale headscale node list
ID | Hostname | Name | MachineKey | NodeKey | User | IP addresses | Ephemeral | Last seen | Expiration | Online | Expired
1 | rocky8 | rocky8 | [s+TG9] | [QQFV0] | jkmutai | 100.64.0.1, fd7a:115c:a1e0::1 | false | 2023-10-05 17:05:58 | 0001-01-01 00:00:00 | online | no
2 | mail | mail | [V8WI2] | [OvPLb] | jkmutai | 100.64.0.2, fd7a:115c:a1e0::2 | false | 2023-10-05 17:06:32 | 0001-01-01 00:00:00 | online | no
6) Comandos úteis do Headscale
Exclua um nó da sua rede.
docker exec headscale \
headscale node delete -i <ID>
Mover nó para outro usuário
docker exec headscale \
headscale node move -i <ID> -u <New-User>
Renomeie uma máquina na sua rede
docker exec headscale \
headscale node rename -i <ID> <NEW_NAME>
Expirar (fechar) uma máquina na sua rede
docker exec headscale \
headscale node expire -i <ID>
Crie uma chave de API:
docker exec headscale \
headscale apikeys create --expiration 90d
Listar chaves de API:
docker exec headscale \
headscale apikeys list
Expire uma chave de API:
docker exec headscale \
headscale apikeys expire --prefix "<PREFIX>"
7) Acesse a IU do Headscale
Gere a chave API no servidor Headscale.
docker exec headscale \
headscale apikeys create --expiration 120d
Isso fornece uma saída semelhante a esta.
8bnNOGwOkw.bjQXvEB4Vk9Ia1R9HupEB0yB9PFthth_Or8QcHncKmw
Abra a IU do Headscale em http://ServerIP_or_hostname:9080/web/settings.html
Insira o URL do servidor Headscale e o token gerado nas caixas. Exemplos:
- URL de escala principal: //api.computingforgeeks.com
- Chave de API Headscale: 8bnNOGwOkw.bjQXvEB4Vk9Ia1R9HupEB0yB9PFthth_Or8QcHncKmw
Próximo artigo para conferir:
- Unindo o pfSense ao Tailscale/Headscale VPN Mesh
- Como ativar e iniciar o servidor SSH no OPNsense
- Como instalar e configurar o cliente Tailscale no OPNsense
Conclusão
Headscale é uma solução perfeita para empresas de pequeno e médio porte que desejam criar uma rede mesh Tailscale e conectar dispositivos a ela. É uma solução alternativa poderosa, segura e confiável para configuração de servidor VPN. Dá a você controle total sobre a rede mesh e o servidor de coordenação. As VPNs Mesh usam um modelo peer-to-peer (P2P) para criar um ambiente compartilhado seguro para seus usuários.