Cómo ejecutar Headscale con UI en Docker Container
En este artículo, demostramos cómo ejecutar Headscale y Headscale UI utilizando Docker Containers. Nuestro artículo reciente fue específico para la instalación de Headscale en el sistema Ubuntu Linux usando el paquete .deb
. El enlace a la publicación se comparte en el siguiente enlace.
- Instalar y configurar Headscale en Ubuntu
Si no prefiere la instalación de Headscale basada en paquetes, este artículo está diseñado para usted. Headscale es una solución alternativa muy potente y de código abierto al servidor de coordinación Tailscale. Está diseñado para ser autohospedado en su propia infraestructura. Headscale se desarrolla de forma independiente y no tiene ninguna relación con la empresa Tailscale, excepto la versión reimplementada del servidor de coordinación de Tailscale.
Siga los pasos compartidos en esta publicación de blog para configurar un servidor Headscale dedicado que se ejecute en un contenedor Docker. El mismo procedimiento se puede reutilizar para la configuración de Podman/Podman Compose con pocas modificaciones. También hemos incluido la instalación de Headscale UI en la ventana acoplable.
1) Instalar el motor Docker
Comience su configuración asegurándose de que Docker Engine esté instalado y funcionando. Consulte la siguiente guía sobre la instalación de Docker en sistemas Linux.
- Cómo instalar Docker CE en sistemas Linux
Una vez instalado puedes comprobar la versión.
$ docker --version
Docker version 24.0.7, build afdd53b
También verifique si el complemento de redacción está instalado.
$ docker compose version
Docker Compose version v2.21.0
2) Definir el archivo Docker Compose
Creemos un directorio que almacene las configuraciones y los datos de Headscale.
mkdir -p ~/headscale && cd ~/headscale
Cree una base de datos SQlite vacía en el directorio headscale:
mkdir ./config
touch ./config/db.sqlite
Cree un nuevo archivo llamado docker-compose.yml
vim docker-compose.yml
Pegue y modifique los contenidos siguientes. Si no necesita que Headscale se ejecute en el contenedor Docker, elimine sus secciones.
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
En nuestro archivo de redacción estamos:
- Montaje
config/
en/etc/headscale
- Montaje de
data/
en/var/lib/headscale/
- Reenviar el puerto 8080 fuera del contenedor headscale para que la instancia
headscale
esté disponible - Reenviar el puerto 9080 desde el contenedor headscale-ui para que la instancia
headscale-ui
esté disponible
Si utiliza https en la interfaz de usuario, puede asignar puertos separados como se muestra a continuación.
- 9443:443
3) Iniciar contenedores Headscale
Descargue el archivo de plantilla de configuración.
mkdir {config,data}
wget https://raw.githubusercontent.com/juanfont/headscale/main/config-example.yaml -O config/config.yaml
Modifique el archivo de configuración según sus preferencias antes de iniciar el contenedor Docker. A continuación se muestran algunas configuraciones que probablemente desee:
# 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 los contenedores usando el comando docker compose
. La opción -d
significa desconectar para que se ejecuten en 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 el estado de los contenedores creados.
$ 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
Puede seguir los registros del contenedor para ver qué sucede dentro ejecutando.
$ 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"}
El comando ss
se puede utilizar para verificar que los puertos del host estén vinculados.
$ 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) Acceder al shell del contenedor
Puede acceder al shell del contenedor headscale
ejecutando:
docker exec -ti headscale bash
Para ejecutar headscale-ui:
docker exec -ti headscale-ui sh
Podemos probar la funcionalidad creando un usuario en la instancia de Headscale.
root@4f2fbe02c029:/# headscale users create computingforgeeks
Se ejecutará un comando de una línea sin ingresar al shell del contenedor.
docker exec headscale \
headscale users create myuser
5) Unir dispositivos cliente a la red Headscale
Necesita un usuario creado en su servidor Headscale. Crearemos uno llamado computingforgeeks.
$ docker exec headscale headscale users create computingforgeeks
User created
Instalación de clientes de Tailscale en sus dispositivos
- Cliente de Windows
- iOS
- Androide
- linux
- Mac OS
Instalación de Tailscale en Linux/BSD
Para sistemas basados en Linux y BSD, ejecute los comandos:
curl -fsSL https://tailscale.com/install.sh | sudo sh
Se puede verificar la versión de Tailscale con los siguientes comandos.
$ tailscale --version
1.50.1
tailscale commit: f45c02bfcf5ee5790c3af278c9e974c9b9b0e771
other commit: 36a20760a45bd1936686879b34c35146cc0c4ec1
go version: go1.21.1
Instalación en MacOS
Puedes instalar usando Homebrew:
brew install tailscale
O ejecutando el script.
curl -fsSL https://tailscale.com/install.sh | sudo sh
Registrar una máquina (inicio de sesión normal)
En una máquina cliente, ejecute el comando de inicio de sesión tailscale
:
tailscale up --login-server YOUR_HEADSCALE_URL
Vea el ejemplo a continuación.
# tailscale up --login-server http://192.168.20.11:8080
To authenticate, visit:
http://192.168.20.11:8080/register/nodekey:410155d1792d0f81a5f39415a1a418f882208751570c2e5195f7a6842ca44e6a
Al abrir los enlaces se obtienen comandos que se ejecutarán en el servidor Headscale para registrar el dispositivo.
Listado de todos los usuarios creados en el 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
Recuerde reemplazar USERNAME con su nombre de usuario válido cuando ejecute los comandos.
$ docker exec headscale \
headscale nodes register --user computingforgeeks --key nodekey:410155d1792d0f81a5f39415a1a418f882208751570c2e5195f7a6842ca44e6a
Machine rocky8 registered
La sintaxis general al registrar una máquina usando headscale
es:
docker exec headscale \
headscale --user <username> nodes register --key <YOU_+MACHINE_KEY>
Listado de todas las máquinas agregadas a la red de malla de 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 la máquina usando una clave previamente autenticada
También puede registrar una nueva máquina utilizando una clave previamente autenticada.
Primero genere una clave usando la línea de comando:
docker exec headscale \
headscale --user <username> preauthkeys create --reusable --expiration 24h
La ejecución del comando devuelve una clave previamente autenticada que se utiliza para conectar un nodo a headscale
al ejecutar el comando tailscale
:
tailscale up --login-server <YOUR_HEADSCALE_URL> --authkey <YOUR_AUTH_KEY>
Veamos el ejemplo a continuación.
# 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
El comando de registro de la máquina con clave previamente autenticada no genera ningún resultado. Pero puede confirmar si se agregan nuevos nodos desde la CLI del 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 útiles de Headscale
Elimina un nodo en tu red.
docker exec headscale \
headscale node delete -i <ID>
Mover nodo a otro usuario
docker exec headscale \
headscale node move -i <ID> -u <New-User>
Cambiar el nombre de una máquina en su red
docker exec headscale \
headscale node rename -i <ID> <NEW_NAME>
Caducar (cerrar sesión) una máquina en su red
docker exec headscale \
headscale node expire -i <ID>
Cree una clave API:
docker exec headscale \
headscale apikeys create --expiration 90d
Lista de claves API:
docker exec headscale \
headscale apikeys list
Caducar una clave API:
docker exec headscale \
headscale apikeys expire --prefix "<PREFIX>"
7) Acceda a la interfaz de usuario de Headscale
Genere una clave API en el servidor Headscale.
docker exec headscale \
headscale apikeys create --expiration 120d
Esto da un resultado similar a este.
8bnNOGwOkw.bjQXvEB4Vk9Ia1R9HupEB0yB9PFthth_Or8QcHncKmw
Abra la interfaz de usuario de Headscale en http://ServerIP_or_hostname:9080/web/settings.html
Ingrese la URL del servidor Headscale y el token generado en los cuadros. Ejemplos:
- URL de escala principal: //api.computingforgeeks.com
- Clave API de Headscale: 8bnNOGwOkw.bjQXvEB4Vk9Ia1R9HupEB0yB9PFthth_Or8QcHncKmw
Próximo artículo para revisar:
- Unir pfSense a Tailscale/Headscale VPN Mesh
- Cómo habilitar e iniciar el servidor SSH en OPNsense
- Cómo instalar y configurar el cliente Tailscale en OPNsense
Conclusión
Headscale es una solución perfecta para pequeñas y medianas empresas que buscan crear una red de malla Tailscale y conectar dispositivos a ella. Es una solución alternativa poderosa, segura y confiable a la configuración del servidor VPN. Le brinda control total sobre la red en malla y el servidor de coordinación. Las VPN en malla utilizan un modelo de igual a igual (P2P) para crear un entorno compartido seguro para sus usuarios.