La ejecución del playbook termina en verde, la unidad de WireGuard está activa, el handshake funciona y el nuevo peer sigue sin llegar a nada. Ver un playbook que informa de éxito mientras el servidor corre la configuración de ayer es especialmente frustrante, porque nada de la salida está mal. Ansible hizo exactamente lo que se le pidió: aseguró que la unidad estuviera iniciada, y ya lo estaba. Aplicar un archivo de configuración reescrito es otra tarea, y solo ocurre si algo le dice al servicio que lo vuelva a leer.

Mira qué informa realmente una segunda ejecución

Ejecuta el playbook dos veces con la configuración cambiada en su sitio y compara el resumen. La segunda ejecución debería mostrar la tarea de la unidad como ok, no como changed, porque un servicio que ya funciona se deja tranquilo por diseño. Eso es la idempotencia funcionando bien, y también la razón por la que el archivo nuevo nunca llega al kernel.

Añade una ejecución de comprobación con salida diff para ver qué tareas tocarían algo.

ansible-playbook -i inventory site.yml --check --diff
systemctl show wg-quick@wg0 -p ActiveEnterTimestamp -p NRestarts
stat -c '%y %n' /etc/wireguard/wg0.conf

Las tres marcas de tiempo cuentan la historia antes de leer una sola línea de registro. Si el archivo de configuración es más nuevo que el momento en que la unidad se activó, la interfaz en ejecución se construyó con un archivo anterior, y cada síntoma posterior se deriva de eso.

No es un defecto de Ansible. El mismo comportamiento aparece con cualquier herramienta de gestión de configuración que separa «asegúrate de que funciona» de «asegúrate de que funciona con esto». La distinción parece pedante hasta que te cuesta una tarde.

Iniciado es un estado, no una recarga

state: started afirma una condición sobre la unidad. No promete que el servicio vuelva a leer sus entradas, y no puede saber que un archivo que nunca abrió ha cambiado. En un despliegue wg-quick las entradas incluyen la configuración de la interfaz, las direcciones, las rutas, las entradas DNS y cualquier hook post-up.

Por eso un archivo actualizado puede contener un peer nuevo, otra dirección o una directiva de enrutamiento cambiada mientras la interfaz viva sigue sirviendo el conjunto antiguo. El handshake todavía tiene éxito porque las claves y los extremos cargados siguen siendo válidos. Eso es justo lo que hace difícil ver el fallo, y por qué la gente persigue el DNS durante una hora antes de comprobar una marca de tiempo.

Otras dos opciones del módulo se confunden a menudo con una solución. daemon_reload hace que systemd vuelva a leer los archivos de unidad, algo irrelevante para un archivo de configuración de WireGuard. state: reloaded pide a la unidad que ejecute su acción de recarga, y si eso hace lo que necesitas depende por completo de la unidad. Ninguna sustituye a saber qué entradas ha leído realmente el proceso en ejecución.

Instala el archivo y luego notifica un handler

El patrón que mantiene la idempotencia y aplica los cambios es el habitual: la tarea que escribe el archivo notifica un handler, y el handler solo se ejecuta cuando el archivo ha cambiado de verdad. Una segunda ejecución sin ediciones no hace nada, y eso es lo que quieres.

- name: write the interface configuration
  ansible.builtin.template:
    src: wg0.conf.j2
    dest: /etc/wireguard/wg0.conf
    owner: root
    mode: "0600"
  notify: apply wg0

- name: ensure the interface unit is enabled
  ansible.builtin.systemd_service:
    name: wg-quick@wg0
    enabled: true
    state: started

- name: apply wg0
  listen: apply wg0
  ansible.builtin.systemd_service:
    name: wg-quick@wg0
    state: restarted

Los handlers se ejecutan al final de la obra, después de las tareas que los notificaron, así que una tarea posterior de la misma obra aún puede ver la interfaz antigua. Si el orden importa, vacía los handlers explícitamente con meta: flush_handlers antes de la tarea que depende de la configuración nueva.

Usa restart en lugar de reload salvo que hayas verificado la acción de recarga de la unidad. La unidad wg-quick de origen sí admite una, y sincroniza la configuración de WireGuard, pero no vuelve a ejecutar la configuración de direcciones, rutas, DNS ni hooks. Por eso un reload tras añadir una directiva de ruta parece tener éxito y no cambia nada.

Compara el dispositivo en vivo con el archivo

La comprobación que cierra esta clase de fallos es una comparación entre lo que tiene el kernel y lo que dice el archivo. Dos comandos producen una salida comparable, y la diferencia es la desviación.

sudo wg showconf wg0
sudo wg-quick strip wg0
sudo diff <(sudo wg showconf wg0) <(sudo wg-quick strip wg0)

wg showconf imprime el dispositivo en vivo, incluida la clave privada, así que trata esa salida como un secreto y no la pegues en un ticket. wg-quick strip imprime el archivo sin las claves exclusivas de wg-quick, y por eso las dos salidas son comparables.

Una diferencia en la lista de peers significa que el archivo nunca se aplicó. Una diferencia limitada a claves o extremos que esperabas cambiar significa que algo lo aplicó en parte. Ninguna diferencia significa que la configuración está al día y el fallo está en otro sitio, lo que ya es un resultado útil.

Paga el coste del reinicio a propósito

Reiniciar la interfaz tira el túnel, y si ese túnel lleva tu sesión administrativa, el reinicio termina la sesión que lo pidió. Pon el handler detrás de una ventana de cambio, o ejecuta el playbook desde una ruta de gestión que no dependa de reiniciar la interfaz.

El coste es la razón por la que la gente recurre al reload. Es un instinto razonable, y se vuelve correcto cuando sabes qué cambios aplica de verdad un reload. Para cambios de peer y de claves en la unidad wg-quick de origen basta; para direccionamiento, enrutamiento y hooks no. Aclararlo una vez sale más barato que descubrirlo durante una ventana de cambio.

La documentación del módulo systemd_service explica la diferencia entre started, restarted y reloaded, y merece una lectura en lugar de deducirla de un resumen verde. Todo en este recorrido sale de esa única distinción.

Artículos relacionados