Headscale v0.26 – Consideraciones tras la actualización
Introducción
Notas sobre el cambio a Headscale v0.26.0 y los ajustes necesarios tras el salto a Policy v2. Este artículo recoge los dos puntos críticos que rompían la configuración previa: base_domain y los identificadores de usuario.
Requisitos previos
- Tener ya configurado Headscale con una versión anterior funcionando.
- Usar Caddy como proxy inverso con TLS (por eso no se usan las opciones de TLS internas de Headscale).
- Haber actualizado a la versión 0.26.0 o superior.
Cambios importantes en Headscale 0.26.0
Usuarios con @ obligatorio en Policy v2
Con la nueva implementación de políticas (Policy v2), todos los identificadores de usuario deben contener un @. Si no lo tienen, Headscale lanza un error como este:
"Invalid Owner 'xxx'. An alias must be one of the following types..."
También puedes ver este error ejecutando:
docker logs headscale # o el nombre del contenedor que uses
Ejemplo del policy.json antes (v1):
{
"tagOwners": {
"tag:admin": ["usuario1"],
"tag:srvadmin": ["usuario1"]
},
"acls": [
{
"action": "accept",
"src": ["tag:admin"],
"dst": ["*:*"]
},
{
"action": "accept",
"src": ["tag:srvadmin"],
"dst": [
"100.64.0.35:15134",
"100.64.0.35:13515",
"100.64.0.35:57000",
"100.64.0.35:5134"
]
}
]
}
Y después (v2):
{
"tagOwners": {
"tag:admin": ["usuario1@midominio.local"],
"tag:srvadmin": ["usuario1@midominio.local"]
},
"acls": [
{
"action": "accept",
"src": ["tag:admin"],
"dst": ["*:*"]
},
{
"action": "accept",
"src": ["tag:srvadmin"],
"dst": [
"100.64.0.35:15134",
"100.64.0.35:13515",
"100.64.0.35:57000",
"100.64.0.35:5134"
]
}
]
}
Para ver los usuarios válidos ya creados:
headscale users list
Migración de Policy v1 a v2 (pasos seguidos)
Esto fue lo que se hizo para realizar la migración correctamente:
-
Iniciar Headscale 0.26.0 con la variable de entorno
HEADSCALE_POLICY_V1=1oHEADSCALE_POLICY_V1: '1'activada.-
Se puede confirmar que ha funcionado si aparece este mensaje al arrancar:
Using policy manager version: 1
-
-
Volcar la política actual a un archivo:
headscale policy get > policy.json -
Editar
policy.jsony migrarlo manualmente al formato v2.-
Se puede comprobar si hay errores con:
headscale policy check --file policy.json
-
-
Cargar la política migrada:
-
Si estás usando Headscale en contenedor Docker, el archivo debe estar en una ruta accesible desde dentro del contenedor. Por ejemplo:
- './Headscale:/etc/headscale' -
En ese caso, el comando sería:
hs policy set --file /etc/headscale/policy.jsonDonde
hses un alias que apunta a:docker exec Headscale headscale
-
-
Reiniciar Headscale sin la variable
HEADSCALE_POLICY_V1.-
Si todo va bien, el mensaje será:
Using policy manager version: 2
-
base_domain no puede coincidir con server_url
Otro breaking change relevante es que base_domain no puede ser igual (ni estar contenido) en el server_url. Si coinciden, MagicDNS deja de funcionar o se comporta de forma errática.
Ejemplo incorrecto:
server_url: https://headscale.midominio.local
base_domain: midominio.local
Ejemplo correcto:
server_url: https://headscale.midominio.local
base_domain: redprivada.lan
En este caso se usó un dominio inventado, corto y sin registrar: redprivada.lan.
Errores comunes o decisiones importantes
- Si olvidaste poner
@a los usuarios, el error no es muy claro. Hay que revisar elpolicy.jsony asegurarse de que todos los identificadores lo llevan. - Aunque el
config-example.yamltrae bloques de Let's Encrypt, se ignoraron porque ya se gestiona TLS con Caddy. - Puedes registrar un dominio personalizado si lo ves útil, pero por ahora solo se usa como base de resolución DNS local.
- La migración de v1 a v2 puede hacerse sin sobresaltos si se siguen los pasos indicados, especialmente si estás usando Docker.
Resumen breve
- Todos los usuarios deben tener
@en su identificador. base_domainno puede coincidir conserver_url.- MagicDNS depende de que estos dos valores estén bien puestos.
- La política ahora se valida al cargar, no en tiempo de ejecución.
- La migración a Policy v2 se puede hacer conservando primero la configuración previa.
- Si usas Docker, asegúrate de que el archivo esté en una ruta montada dentro del contenedor.
Notas personales
Anotar bien estos dos cambios porque son minas antipersona: si se olvidan, te explota la configuración en la cara sin piedad.