Docker Compose
Il file docker-compose.yaml avvia due container: Headscale (il server di coordinamento vero e proprio) e Headplane (un’interfaccia web per gestirlo comodamente). Headplane comunica con Headscale tramite la rete interna e può riavviarlo grazie all’accesso al Docker socket.
services:
headscale:
image: headscale/headscale:latest
container_name: headscale
restart: unless-stopped
command: serve
port:
- 3478:3478
labels:
# Necessaria: Headplane usa questa label per trovare il container
# tramite il Docker socket e poterlo riavviare quando cambi DNS/config
me.tale.headplane.target: headscale
volumes:
- ./headscale-config/headscale.yaml:/etc/headscale/config.yaml:ro
- ./headscale-config/acl.hjson:/etc/headscale/acl.hjson:ro
- ./headscale-data:/var/lib/headscale
networks:
- internal
- caddy_network
headplane:
image: ghcr.io/tale/headplane:0.6.2-beta.5
container_name: headplane
restart: unless-stopped
volumes:
# Config propria di Headplane
- ./headplane-config/headplane.yaml:/etc/headplane/config.yaml:ro
# Storage persistente (database interno, cache)
- ./headplane-data:/var/lib/headplane
# Config di Headscale (read-only) — serve a Headplane per mostrare
# le impostazioni nella UI. Il path interno deve corrispondere
# a headscale.config_path nel headplane.yaml
- ./headscale-config/headscale.yaml:/etc/headscale/config.yaml:ro
# Docker socket per l'integrazione (restart Headscale da UI)
- /var/run/docker.sock:/var/run/docker.sock:ro
depends_on:
- headscale
networks:
- internal
- caddy_network
networks:
internal:
driver: bridge
internal: true
caddy_network:
external: trueConfigurazione di Headscale
Il file headscale-config/headscale.yaml contiene la configurazione principale del server. Qui si definiscono l’URL pubblico, il database, i prefissi di rete e il server DERP integrato per il relay del traffico quando la connessione diretta tra i nodi non è possibile.
server_url: https://hs.gennaro.cc
listen_addr: 0.0.0.0:8080
grpc_listen_addr: 0.0.0.0:50443
grpc_allow_insecure: false
metrics_listen_addr: 0.0.0.0:9090
database:
type: sqlite
sqlite:
path: /var/lib/headscale/db.sqlite
prefixes:
v4: 100.64.0.0/10
v6: fd7a:115c:a1e0::/48
allocation: sequential
derp:
server:
enabled: true
region_id: 999
region_code: "homelab"
region_name: "Homelab DERP"
stun_listen_addr: 0.0.0.0:3478
private_key_path: /var/lib/headscale/derp_server_private.key
urls:
- https://controlplane.tailscale.com/derpmap/default
auto_update_enabled: true
update_frequency: 24h
dns:
magic_dns: true
base_domain: tail.gennaro.cc
nameservers:
global:
- 1.1.1.1
- 8.8.8.8
log:
level: info
private_key_path: /var/lib/headscale/private.key
noise:
private_key_path: /var/lib/headscale/noise_private.key
policy:
mode: file
path: /etc/headscale/acl.hjsonACL di Headscale
Le Access Control List si trovano nel file headscale-config/acl.hjson. In questo esempio la policy è completamente aperta: tutti i nodi possono raggiungere qualsiasi altro nodo su qualsiasi porta. I tag owner permettono di assegnare ruoli ai dispositivi direttamente dalla UI di Headplane.
{
// Definisci un gruppo con il tuo utente
"groups": {
"group:admins": ["edoardo@"]
},
// Usa il gruppo come tag owner
"tagOwners": {
"tag:server": ["group:admins"],
"tag:test": ["group:admins"],
"tag:media": ["group:admins"],
"tag:admin": ["group:admins"]
},
"acls": [
{
"action": "accept",
"src": ["*"],
"dst": ["*:*"]
}
]
}Configurazione di Headplane
Il file headplane-config/headplane.yaml configura l’interfaccia web. Headplane si collega a Headscale sulla rete interna Docker e gestisce l’autenticazione tramite OIDC. L’integrazione con il Docker socket permette di riavviare Headscale direttamente dalla UI quando si modificano DNS o altre impostazioni.
headscale:
url: http://headscale:8080
config_path: /etc/headscale/config.yaml
config_strict: false
server:
host: 0.0.0.0
port: 3000
cookie_secure: true
cookie_secret: "aaaaaaaaaaaaaaaa"
data_path: /var/lib/headplane
integration:
docker:
enabled: true
socket: "unix:///var/run/docker.sock"
container_name: headscale
oidc:
disable_api_key_login: false
token_endpoint_auth_method: "client_secret_post"
issuer: "https://login.infomaniak.com"
client_id: "a3512bae-a959-....-a5c6-f48d6baa97c0"
client_secret: "ayb7np8sEP...6RwNuZ9TdV69BlPWzrVueYiMih"
redirect_uri: "https://hs.gennaro.cc/admin/oidc/callback"
headscale_api_key: "hskA...Iilnb"
allowed_emails:
- "email_account@domain.xx"