From 63a21e5145a9e75f654ac24be1419c34f3a250ee Mon Sep 17 00:00:00 2001 From: Beta Date: Sat, 20 Sep 2025 22:29:45 -0300 Subject: [PATCH 01/23] probando multiples domains, deshabilitando momentaneamente https debido a que para este hay que arreglar la obtencion de certificados de DNS externos, es necesario en HTTP (80) pasar la variable a proxy_ssl_name ya que viene vacia y esto genera el error 500 responde tlsv1 unrecognized name (alert 112) --- abyayala.yml | 3 ++- roles/proxy/templates/default_proxy.conf | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/abyayala.yml b/abyayala.yml index 22117ea..d14d672 100644 --- a/abyayala.yml +++ b/abyayala.yml @@ -217,8 +217,9 @@ matrix: - service_name: kipu domains: - kipu.abyaya.la + - kipu.latina.red nodo: kipu.comun - force_https: yes + ssl: no - service_name: carabobolibre domains: diff --git a/roles/proxy/templates/default_proxy.conf b/roles/proxy/templates/default_proxy.conf index a2c8627..3ac080f 100644 --- a/roles/proxy/templates/default_proxy.conf +++ b/roles/proxy/templates/default_proxy.conf @@ -15,7 +15,7 @@ client_max_body_size 1G; proxy_ssl_verify off; proxy_ssl_server_name on; - proxy_ssl_name $ssl_server_name; + proxy_ssl_name $host; proxy_pass https://$comun_{{ vhost.nodo | replace(".", "") }}; -- 2.49.0 From 7f38023c7d7fa4f9b521af41a0328f957cc34540 Mon Sep 17 00:00:00 2001 From: Beta Date: Tue, 25 Nov 2025 14:30:07 -0300 Subject: [PATCH 02/23] =?UTF-8?q?feat:=20soporte=20para=20dominios=20FQDN?= =?UTF-8?q?=20con=20detecci=C3=B3n=20autom=C3=A1tica=20de=20zona=20DNS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Añade soporte completo para usar dominios FQDN externos (ejemplo.com, kipu.latina.red, etc.) además de subdominios .abyaya.la. Cambios principales: - Generación automática de subdominio .abyaya.la como alias - Detección automática de TLDs compuestos (.com.ar, .co.uk, etc.) - Actualización DNS multi-zona en Knot - Procesamiento de múltiples dominios por servicio - Certificados SSL para todos los dominios + wildcards La detección de tipo de dominio (FQDN vs subdominio) es completamente automática basada en el sufijo .abyaya.la. Ver FQDN_AUTHORITATIVE.md para documentación completa. --- FQDN_AUTHORITATIVE.md | 133 ++++++++++++++++++++ roles/knsupdate/tasks/templates/commands.j2 | 21 ++-- roles/knsupdate/tasks/update.yml | 12 +- roles/knsupdate/tasks/update_domain.yml | 36 ++++++ roles/knsupdate/vars/main.yml | 15 +++ roles/proxy/tasks/main.yml | 15 +++ 6 files changed, 217 insertions(+), 15 deletions(-) create mode 100644 FQDN_AUTHORITATIVE.md create mode 100644 roles/knsupdate/tasks/update_domain.yml diff --git a/FQDN_AUTHORITATIVE.md b/FQDN_AUTHORITATIVE.md new file mode 100644 index 0000000..7801bfb --- /dev/null +++ b/FQDN_AUTHORITATIVE.md @@ -0,0 +1,133 @@ +# Soporte para Dominios FQDN Autoritativos + +Esta feature añade soporte para usar dominios FQDN externos (ejemplo.com, kipu.latina.red, etc.) además de subdominios .abyaya.la. + +## Cambios Implementados + +### 1. Generación Automática de Subdominio Default + +Cuando se define un dominio FQDN, el sistema genera automáticamente un subdominio `.abyaya.la` basado en el `service_name` que funciona como alias. + +**Ejemplo:** +```yaml +- service_name: kipu + domains: + - kipu.latina.red + nodo: kipu.comun + force_https: yes +``` + +El sistema automáticamente añade `kipu.abyaya.la` a la lista de dominios, por lo que ambos dominios funcionarán y redirigirán al primero de la lista. + +### 2. Soporte para TLDs Compuestos + +El sistema detecta automáticamente TLDs compuestos como `.com.ar`, `.co.uk`, `.com.br`, etc., y extrae correctamente la zona DNS. + +**TLDs soportados:** +- com.ar, gov.ar, org.ar, gob.ar, net.ar, mil.ar, edu.ar +- com.mx +- co.uk +- com.br +- co.nz, net.nz, org.nz + +Para añadir más TLDs, editar `roles/knsupdate/vars/main.yml`. + +### 3. Actualización DNS Multi-Zona + +El sistema ahora actualiza correctamente el DNS en Knot para cada dominio según su tipo: + +- **Subdominios .abyaya.la**: Se actualizan en la zona `abyaya.la.` +- **FQDN autoritativos**: Se actualizan en su zona correspondiente (ej: `latina.red.`, `example.com.ar.`) + +La detección es **completamente automática** basada en el sufijo del dominio. + +## Uso + +### Caso Básico: Solo FQDN + +```yaml +- service_name: ejemplo + domains: + - ejemplo.latina.red + nodo: ejemplo.comun + force_https: yes +``` + +**Resultado:** +- `ejemplo.latina.red` → Dominio principal (detectado como FQDN) +- `ejemplo.abyaya.la` → Generado automáticamente como alias +- Ambos tienen certificados SSL wildcard +- Ambos redirigen al primero (ejemplo.latina.red) + +### Caso Avanzado: Múltiples Dominios + +```yaml +- service_name: miapp + domains: + - miapp.com.ar + - miapp.latina.red + - miapp.abyaya.la + nodo: miapp.comun + force_https: yes +``` + +**Resultado:** +- Los tres dominios funcionan +- Todos redirigen al primero (miapp.com.ar) +- Certificados SSL para cada dominio + wildcards +- DNS actualizado en zonas: `com.ar.`, `latina.red.`, `abyaya.la.` + +### Subdominios de FQDN + +```yaml +- service_name: api + domains: + - api.ejemplo.com.ar + nodo: api.comun + force_https: yes +``` + +**Resultado:** +- `api.ejemplo.com.ar` → Dominio principal (hostname: api, zona: com.ar.) +- `api.abyaya.la` → Generado automáticamente + +## Archivos Modificados + +1. **roles/proxy/tasks/main.yml**: Añade dominio default .abyaya.la automáticamente +2. **roles/knsupdate/vars/main.yml**: Lista de TLDs compuestos +3. **roles/knsupdate/tasks/update.yml**: Procesa múltiples dominios +4. **roles/knsupdate/tasks/update_domain.yml**: Nuevo archivo que detecta tipo de dominio +5. **roles/knsupdate/tasks/templates/commands.j2**: Usa zona y hostname dinámicos + +## Comportamiento de Certificados SSL + +Certbot obtiene certificados para **todos** los dominios listados más sus wildcards: + +```bash +certbot certonly -d ejemplo.com.ar -d *.ejemplo.com.ar -d ejemplo.abyaya.la -d *.ejemplo.abyaya.la +``` + +Usa el método `dns-standalone` que requiere que el proxy controle el DNS autoritativo. Esto funciona porque knsupdate actualiza Knot con todos los dominios. + +## Migración desde Configuración Anterior + +La configuración anterior sigue funcionando sin cambios: + +```yaml +- service_name: viejo + domains: + - viejo.abyaya.la + nodo: viejo.comun + force_https: yes +``` + +Todo funciona exactamente igual para subdominios .abyaya.la existentes. + +## Notas Técnicas + +- La detección de tipo de dominio es **completamente automática** basada en el sufijo `.abyaya.la` +- Los subdominios .abyaya.la siempre se generan automáticamente si no están presentes +- La zona DNS se detecta automáticamente considerando TLDs simples y compuestos +- Todos los dominios apuntan al mismo nodo en la VPN +- El primer dominio en la lista es considerado el principal para certificados SSL +- No se requiere ningún flag especial en la configuración diff --git a/roles/knsupdate/tasks/templates/commands.j2 b/roles/knsupdate/tasks/templates/commands.j2 index 45438b5..032e270 100644 --- a/roles/knsupdate/tasks/templates/commands.j2 +++ b/roles/knsupdate/tasks/templates/commands.j2 @@ -1,14 +1,19 @@ {% for dns_server in dns_servers %} server {{ dns_server }} -zone abyaya.la. -origin abyaya.la. +zone {{ zone }} +origin {{ zone }} ttl 60 -del {{ vho }} a -del {{ vho }} ns -add {{ vho }} a {{ host_ip }} -add *.{{ vho }} a {{ host_ip }} -add _acme-challenge.{{ vho }} a {{ host_ip }} -add _acme-challenge.{{ vho }} ns _acme-challenge +del {{ hostname }} a +del {{ hostname }} ns +add {{ hostname }} a {{ host_ip }} +{% if is_abyayala_subdomain %} +add *.{{ hostname }} a {{ host_ip }} +{% else %} +add {{ domain }} a {{ host_ip }} +add *.{{ domain }} a {{ host_ip }} +{% endif %} +add _acme-challenge.{{ hostname }} a {{ host_ip }} +add _acme-challenge.{{ hostname }} ns _acme-challenge {% if vhost.dns_extras is defined %} {% for dns_extra in vhost.dns_extras %} {{ dns_extra }} diff --git a/roles/knsupdate/tasks/update.yml b/roles/knsupdate/tasks/update.yml index b3783f3..a0e43c7 100644 --- a/roles/knsupdate/tasks/update.yml +++ b/roles/knsupdate/tasks/update.yml @@ -1,7 +1,5 @@ - - set_fact: - vho: "{{ vhost.domains[0] | regex_replace('([a-z0-9]+)\\.abyaya\\.la', '\\1')}}" - - - name: knsupdate - shell: knsupdate - args: - stdin: "{{ lookup('template', 'templates/commands.j2') }}" + - name: process each domain in the list + include_tasks: update_domain.yml + with_items: "{{ vhost.domains }}" + loop_control: + loop_var: domain diff --git a/roles/knsupdate/tasks/update_domain.yml b/roles/knsupdate/tasks/update_domain.yml new file mode 100644 index 0000000..d657d7d --- /dev/null +++ b/roles/knsupdate/tasks/update_domain.yml @@ -0,0 +1,36 @@ + - set_fact: + is_abyayala_subdomain: "{{ domain.endswith('.abyaya.la') }}" + + - name: extract zone and hostname for abyaya.la subdomains + set_fact: + zone: "abyaya.la." + hostname: "{{ domain | regex_replace('([a-z0-9-]+)\\.abyaya\\.la', '\\1') }}" + when: is_abyayala_subdomain + + - name: split domain into parts + set_fact: + domain_parts: "{{ domain.split('.') }}" + when: not is_abyayala_subdomain + + - name: detect if domain uses compound TLD + set_fact: + domain_suffix_2: "{{ domain_parts[-2:] | join('.') }}" + uses_compound_tld: "{{ domain_parts[-2:] | join('.') in compound_tlds }}" + when: not is_abyayala_subdomain + + - name: extract zone and hostname for FQDN with compound TLD + set_fact: + zone: "{{ domain_parts[-3:] | join('.') }}." + hostname: "{{ domain_parts[:-3] | join('.') if domain_parts | length > 3 else '@' }}" + when: not is_abyayala_subdomain and uses_compound_tld + + - name: extract zone and hostname for FQDN with simple TLD + set_fact: + zone: "{{ domain_parts[-2:] | join('.') }}." + hostname: "{{ domain_parts[:-2] | join('.') if domain_parts | length > 2 else '@' }}" + when: not is_abyayala_subdomain and not uses_compound_tld + + - name: knsupdate for this domain + shell: knsupdate + args: + stdin: "{{ lookup('template', 'templates/commands.j2') }}" diff --git a/roles/knsupdate/vars/main.yml b/roles/knsupdate/vars/main.yml index d81c409..d94b0cb 100644 --- a/roles/knsupdate/vars/main.yml +++ b/roles/knsupdate/vars/main.yml @@ -3,3 +3,18 @@ dns_servers: - "athshe.sutty.nl" - "gethen.sutty.nl" - "ganam.sutty.nl" + +compound_tlds: + - com.ar + - com.mx + - co.uk + - com.br + - gov.ar + - org.ar + - gob.ar + - net.ar + - mil.ar + - edu.ar + - co.nz + - net.nz + - org.nz diff --git a/roles/proxy/tasks/main.yml b/roles/proxy/tasks/main.yml index c713249..a981f91 100644 --- a/roles/proxy/tasks/main.yml +++ b/roles/proxy/tasks/main.yml @@ -48,6 +48,21 @@ loop_control: loop_var: domino + - name: add default abyaya.la subdomain if not present + set_fact: + matrix_loop_with_defaults: "{{ matrix_loop_with_defaults | default([]) | union([ item_with_default ]) }}" + vars: + has_abyayala_domain: "{{ item.domains | select('match', '.*\\.abyaya\\.la$') | list | length > 0 }}" + default_domain: "{{ item.service_name }}.abyaya.la" + domains_with_default: "{{ item.domains + [default_domain] if not has_abyayala_domain else item.domains }}" + item_with_default: "{{ item | combine({'domains': domains_with_default}) }}" + with_items: "{{ matrix_loop | default([]) }}" + + - name: update matrix_loop with defaults + set_fact: + matrix_loop: "{{ matrix_loop_with_defaults }}" + when: matrix_loop_with_defaults is defined + - name: certificates loop include_tasks: ../../certbot/tasks/certbot.yml with_items: "{{ matrix_loop | default([]) }}" -- 2.49.0 From 6253223fdfde8ff911b0e452498ebe67d42472fe Mon Sep 17 00:00:00 2001 From: Beta Date: Tue, 25 Nov 2025 14:45:59 -0300 Subject: [PATCH 03/23] fix: stream usa siempre dominio .abyaya.la por seguridad --- roles/proxy/templates/stream.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/proxy/templates/stream.conf b/roles/proxy/templates/stream.conf index a63eef6..bf54232 100644 --- a/roles/proxy/templates/stream.conf +++ b/roles/proxy/templates/stream.conf @@ -5,7 +5,7 @@ upstream ssh_{{ vhost.nodo | replace(".", "") }} { server { listen {{ vhost.ports[0] }}; - server_name .{{ vhost.domains | join(' .') }}; + server_name {{ vhost.service_name }}.abyaya.la; proxy_pass ssh_{{ vhost.nodo | replace(".", "") }}; } \ No newline at end of file -- 2.49.0 From 180a7f2ab6fb6a67cf7316ef82c9e1011c9ff1c2 Mon Sep 17 00:00:00 2001 From: Beta Date: Wed, 26 Nov 2025 13:11:09 -0300 Subject: [PATCH 04/23] recorto algunos tld innecesarios y le saco el no a ssl para otra cosa --- abyayala.yml | 1 - roles/knsupdate/vars/main.yml | 10 +--------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/abyayala.yml b/abyayala.yml index 71d3b1c..68c1fcb 100644 --- a/abyayala.yml +++ b/abyayala.yml @@ -206,7 +206,6 @@ matrix: domains: - kipu.latina.red nodo: kipu.comun - ssl: no ports: - 223 diff --git a/roles/knsupdate/vars/main.yml b/roles/knsupdate/vars/main.yml index d94b0cb..e8e1797 100644 --- a/roles/knsupdate/vars/main.yml +++ b/roles/knsupdate/vars/main.yml @@ -7,14 +7,6 @@ dns_servers: compound_tlds: - com.ar - com.mx - - co.uk - com.br - - gov.ar - org.ar - - gob.ar - - net.ar - - mil.ar - - edu.ar - - co.nz - - net.nz - - org.nz + - edu.ar \ No newline at end of file -- 2.49.0 From f180972d15d0ddac46e7a77f2cb09935b5df61ff Mon Sep 17 00:00:00 2001 From: Beta Date: Thu, 27 Nov 2025 16:27:55 -0300 Subject: [PATCH 05/23] fix: revertir proxy_ssl_name a $ssl_server_name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit El uso de $host en lugar de $ssl_server_name no es correcto ya que: - proxy_ssl_verify está deshabilitado, por lo que el SNI no importa - $ssl_server_name es el valor correcto para SNI en proxies SSL - $host causaba confusión innecesaria Revierte a la configuración estándar y correcta. --- roles/proxy/templates/default_proxy.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/proxy/templates/default_proxy.conf b/roles/proxy/templates/default_proxy.conf index 3ac080f..a2c8627 100644 --- a/roles/proxy/templates/default_proxy.conf +++ b/roles/proxy/templates/default_proxy.conf @@ -15,7 +15,7 @@ client_max_body_size 1G; proxy_ssl_verify off; proxy_ssl_server_name on; - proxy_ssl_name $host; + proxy_ssl_name $ssl_server_name; proxy_pass https://$comun_{{ vhost.nodo | replace(".", "") }}; -- 2.49.0 From 1a00b8a60c2066eb9b190b973515d70e6c7c9e17 Mon Sep 17 00:00:00 2001 From: Beta Date: Tue, 2 Dec 2025 17:44:30 -0300 Subject: [PATCH 06/23] expand en certbot para multiples dominios variables --- roles/certbot/tasks/certbot.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/certbot/tasks/certbot.yml b/roles/certbot/tasks/certbot.yml index 8b49fa7..6bf8c21 100644 --- a/roles/certbot/tasks/certbot.yml +++ b/roles/certbot/tasks/certbot.yml @@ -26,7 +26,7 @@ state: started volumes: - "{{ althost }}_certs_data:/etc/letsencrypt" - command: "--non-interactive --agree-tos --email {{ webmaster_email }} certonly --preferred-challenges dns --authenticator dns-standalone --dns-standalone-address={{ host_ip }} --dns-standalone-port=53 --dns-standalone-propagation-seconds=10 {% for domain in loop.domains %} -d {{ domain }} -d *.{{ domain }} {% endfor %}" + command: "--non-interactive --agree-tos --expand --email {{ webmaster_email }} certonly --preferred-challenges dns --authenticator dns-standalone --dns-standalone-address={{ host_ip }} --dns-standalone-port=53 --dns-standalone-propagation-seconds=10 {% for domain in loop.domains %} -d {{ domain }} -d *.{{ domain }} {% endfor %}" detach: no cleanup: yes ports: -- 2.49.0 From d94cfd89d0732aed6ee5c719f1d76d6b5387780d Mon Sep 17 00:00:00 2001 From: Beta Date: Tue, 2 Dec 2025 19:07:38 -0300 Subject: [PATCH 07/23] =?UTF-8?q?fix:=20asegurar=20que=20dominio=20.abyaya?= =?UTF-8?q?.la=20est=C3=A9=20siempre=20en=20domains[0]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modifica la lógica para garantizar que el dominio .abyaya.la siempre sea el primero en la lista de dominios, independientemente del orden definido en abyayala.yml. Esto es crítico para certificados SSL y configuraciones vhost que dependen de domains[0]. --- roles/proxy/tasks/main.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/roles/proxy/tasks/main.yml b/roles/proxy/tasks/main.yml index b33c928..d60418b 100644 --- a/roles/proxy/tasks/main.yml +++ b/roles/proxy/tasks/main.yml @@ -45,13 +45,16 @@ loop_control: loop_var: domino - - name: add default abyaya.la subdomain if not present + - name: ensure abyaya.la subdomain is always first in domains list set_fact: matrix_loop_with_defaults: "{{ matrix_loop_with_defaults | default([]) | union([ item_with_default ]) }}" vars: - has_abyayala_domain: "{{ item.domains | select('match', '.*\\.abyaya\\.la$') | list | length > 0 }}" + existing_abyayala_domains: "{{ item.domains | select('match', '.*\\.abyaya\\.la$') | list }}" + has_abyayala_domain: "{{ existing_abyayala_domains | length > 0 }}" default_domain: "{{ item.service_name }}.abyaya.la" - domains_with_default: "{{ item.domains + [default_domain] if not has_abyayala_domain else item.domains }}" + other_domains: "{{ item.domains | reject('match', '.*\\.abyaya\\.la$') | list }}" + abyayala_domain_to_use: "{{ existing_abyayala_domains[0] if has_abyayala_domain else default_domain }}" + domains_with_default: "{{ [abyayala_domain_to_use] + other_domains }}" item_with_default: "{{ item | combine({'domains': domains_with_default}) }}" with_items: "{{ matrix_loop | default([]) }}" -- 2.49.0 From be5f8fc5e7e0825d28c1c51f5563595f61e4d555 Mon Sep 17 00:00:00 2001 From: Beta Date: Mon, 15 Dec 2025 19:44:01 -0300 Subject: [PATCH 08/23] dns_extras en archivos con nombres de dominio principal, en roles/knsupdate/files/dns_extras --- roles/knsupdate/files/dns_extras/pilmaiken.abyaya.la | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 roles/knsupdate/files/dns_extras/pilmaiken.abyaya.la diff --git a/roles/knsupdate/files/dns_extras/pilmaiken.abyaya.la b/roles/knsupdate/files/dns_extras/pilmaiken.abyaya.la new file mode 100644 index 0000000..50f3357 --- /dev/null +++ b/roles/knsupdate/files/dns_extras/pilmaiken.abyaya.la @@ -0,0 +1,8 @@ +del pilmaiken mx +del pilmaiken txt +del pilmaiken spf +add pilmaiken mx 10 correspondencia.latina.red. +add pilmaiken txt "v=spf1 mx a:correspondencia.latina.red -all" +add pilmaiken spf "v=spf1 mx a:correspondencia.latina.red -all" +add dkim._domainkey.pilmaiken txt "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQ6JwPaawDzMXuscSgDpvipRFLGXSqgmvvI6jk18lcg0kK2lfxsvXGJ/6U7oCtKa35IEVzdigxD0o7DzklKxAsNIVbcExPJkFWzQuKuP6ATBESo7YUn7Z5qjfxBiNPS0FJp8XpbpUzN+zg/NTgmkggnwwC0tKgcEQ6HnI9AOa1LQIDAQAB" +add _dmarc.pilmaiken txt "v=DMARC1; p=reject; rua=mailto:postmaster@correspondencia.latina.red; ruf=mailto:postmaster@correspondencia.latina.red; adkim=s; aspf=s" -- 2.49.0 From f72983049dc7f3197e73c8e48337c349634d502c Mon Sep 17 00:00:00 2001 From: chasqui Date: Thu, 11 Dec 2025 18:40:38 -0600 Subject: [PATCH 09/23] deabajo nodo --- abyayala.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/abyayala.yml b/abyayala.yml index 55d3d62..53fbb9e 100644 --- a/abyayala.yml +++ b/abyayala.yml @@ -59,6 +59,7 @@ matrix: - samatuun - kaasavi - llavero + - deabajo - service_name: respaldos domains: @@ -231,4 +232,10 @@ matrix: domains: - llavero.abyaya.la nodo: llavero.comun - force_https: yes \ No newline at end of file + force_https: yes + + - service_name: deabajo + domains: + - deabajo.abyaya.la + nodo: deabajo.comun + force_https: yes -- 2.49.0 From 135edfe52799b35026154642fd44cffa9c8331ce Mon Sep 17 00:00:00 2001 From: Beta Date: Thu, 11 Dec 2025 22:32:10 -0300 Subject: [PATCH 10/23] fix: limpiar repositorios Docker antiguos antes de configurar deb822 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Soluciona conflicto APT causado por configuraciones de repositorio Docker duplicadas con valores Signed-By contradictorios. Ahora se eliminan los archivos de repositorio antiguos antes de agregar la configuración deb822. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- roles/althost/tasks/main.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/roles/althost/tasks/main.yml b/roles/althost/tasks/main.yml index a01a0e5..cbfa824 100644 --- a/roles/althost/tasks/main.yml +++ b/roles/althost/tasks/main.yml @@ -24,6 +24,14 @@ dest: /etc/apt/keyrings/docker.asc mode: '0644' + - name: remove old docker repository files to avoid conflicts + file: + path: "{{ item }}" + state: absent + loop: + - /etc/apt/sources.list.d/docker.list + - /etc/apt/sources.list.d/download_docker_com_linux_debian.list + - name: add docker repository with deb822 format deb822_repository: name: docker -- 2.49.0 From 838cc5833cac6044fe71afe38d9ce9d06e2aac38 Mon Sep 17 00:00:00 2001 From: Beta Date: Fri, 12 Dec 2025 11:09:48 -0300 Subject: [PATCH 11/23] fix: mover limpieza de repos Docker fuera del bloque installation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit La limpieza de repositorios Docker antiguos debe ejecutarse SIEMPRE, incluso cuando se usa --skip-tags=installation, para evitar conflictos APT antes de que knsupdate u otros roles intenten usar apt. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- roles/althost/tasks/main.yml | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/roles/althost/tasks/main.yml b/roles/althost/tasks/main.yml index cbfa824..822a7d4 100644 --- a/roles/althost/tasks/main.yml +++ b/roles/althost/tasks/main.yml @@ -1,6 +1,16 @@ # DOCKER CE this is specific for Debian # https://docs.docker.com/install/linux/docker-ce/debian/ # Soporta Debian 12 (bookworm) y Debian 13 (trixie) + + # Clean up conflicting Docker repositories first (always runs, even with --skip-tags=installation) + - name: remove old docker repository files to avoid APT conflicts + file: + path: "{{ item }}" + state: absent + loop: + - /etc/apt/sources.list.d/docker.list + - /etc/apt/sources.list.d/download_docker_com_linux_debian.list + - block: - name: "unattended upgrades" apt: @@ -24,14 +34,6 @@ dest: /etc/apt/keyrings/docker.asc mode: '0644' - - name: remove old docker repository files to avoid conflicts - file: - path: "{{ item }}" - state: absent - loop: - - /etc/apt/sources.list.d/docker.list - - /etc/apt/sources.list.d/download_docker_com_linux_debian.list - - name: add docker repository with deb822 format deb822_repository: name: docker -- 2.49.0 From 5c19e789c4599ec1c21acdc575e87157015b61ff Mon Sep 17 00:00:00 2001 From: Beta Date: Fri, 12 Dec 2025 11:35:23 -0300 Subject: [PATCH 12/23] =?UTF-8?q?fix:=20forzar=20conversi=C3=B3n=20a=20boo?= =?UTF-8?q?l=20en=20condicionales=20de=20certbot?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ansible requiere que las condicionales resulten en booleanos. Agregado filtro | bool para convertir explícitamente strings a booleanos en las evaluaciones de needs_cert, needs_vhost y obtain_cert. --- roles/certbot/tasks/certbot.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/roles/certbot/tasks/certbot.yml b/roles/certbot/tasks/certbot.yml index 6bf8c21..7f49871 100644 --- a/roles/certbot/tasks/certbot.yml +++ b/roles/certbot/tasks/certbot.yml @@ -10,9 +10,9 @@ register: vhost_stat - set_fact: - needs_cert: (loop.ssl | default(domains_default_ssl) ) or (loop.force_https | default(domains_default_force_https)) - needs_vhost: needs_cert and not vhost_stat.stat.exists - obtain_cert: needs_cert and not ssl_cert.stat.exists + needs_cert: ((loop.ssl | default(domains_default_ssl) | bool) or (loop.force_https | default(domains_default_force_https) | bool)) + needs_vhost: ((needs_cert | bool) and not vhost_stat.stat.exists) + obtain_cert: ((needs_cert | bool) and not ssl_cert.stat.exists) - name: certificate obtention block: -- 2.49.0 From d683f8bcd2c608a8b16caf692d256f893910d512 Mon Sep 17 00:00:00 2001 From: Beta Date: Fri, 12 Dec 2025 12:42:50 -0300 Subject: [PATCH 13/23] fix: envolver expresiones booleanas en templates Jinja2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Aplicar | bool al resultado final de cada expresión y envolver en sintaxis {{ }} para forzar evaluación correcta como booleanos. --- roles/certbot/tasks/certbot.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/roles/certbot/tasks/certbot.yml b/roles/certbot/tasks/certbot.yml index 7f49871..04c51fe 100644 --- a/roles/certbot/tasks/certbot.yml +++ b/roles/certbot/tasks/certbot.yml @@ -10,9 +10,9 @@ register: vhost_stat - set_fact: - needs_cert: ((loop.ssl | default(domains_default_ssl) | bool) or (loop.force_https | default(domains_default_force_https) | bool)) - needs_vhost: ((needs_cert | bool) and not vhost_stat.stat.exists) - obtain_cert: ((needs_cert | bool) and not ssl_cert.stat.exists) + needs_cert: "{{ ((loop.ssl | default(domains_default_ssl) | bool) or (loop.force_https | default(domains_default_force_https) | bool)) | bool }}" + needs_vhost: "{{ ((needs_cert | bool) and not vhost_stat.stat.exists) | bool }}" + obtain_cert: "{{ ((needs_cert | bool) and not ssl_cert.stat.exists) | bool }}" - name: certificate obtention block: -- 2.49.0 From 1fc58432dd501061dd27b2276480326265eb34a9 Mon Sep 17 00:00:00 2001 From: Beta Date: Fri, 12 Dec 2025 13:34:49 -0300 Subject: [PATCH 14/23] fix: aplicar | bool en when clause de obtain_cert --- roles/certbot/tasks/certbot.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/certbot/tasks/certbot.yml b/roles/certbot/tasks/certbot.yml index 04c51fe..3b361a6 100644 --- a/roles/certbot/tasks/certbot.yml +++ b/roles/certbot/tasks/certbot.yml @@ -36,7 +36,7 @@ - reload proxy register: cert_result - when: obtain_cert + when: obtain_cert | bool # RESET - set_fact: -- 2.49.0 From 66e3c6fcaffb4235a9c6ab7aa68a9aca7acbaf18 Mon Sep 17 00:00:00 2001 From: Beta Date: Fri, 12 Dec 2025 13:42:05 -0300 Subject: [PATCH 15/23] fix: separar set_fact para compatibilidad con Ansible 2.15+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit En Ansible 2.15+ las variables en el mismo set_fact se evalúan simultáneamente, no secuencialmente. Separar needs_cert en su propio set_fact antes de usarlo en needs_vhost y obtain_cert. --- roles/certbot/tasks/certbot.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/roles/certbot/tasks/certbot.yml b/roles/certbot/tasks/certbot.yml index 3b361a6..348ab90 100644 --- a/roles/certbot/tasks/certbot.yml +++ b/roles/certbot/tasks/certbot.yml @@ -11,8 +11,10 @@ - set_fact: needs_cert: "{{ ((loop.ssl | default(domains_default_ssl) | bool) or (loop.force_https | default(domains_default_force_https) | bool)) | bool }}" - needs_vhost: "{{ ((needs_cert | bool) and not vhost_stat.stat.exists) | bool }}" - obtain_cert: "{{ ((needs_cert | bool) and not ssl_cert.stat.exists) | bool }}" + + - set_fact: + needs_vhost: "{{ (needs_cert | bool and not vhost_stat.stat.exists) | bool }}" + obtain_cert: "{{ (needs_cert | bool and not ssl_cert.stat.exists) | bool }}" - name: certificate obtention block: -- 2.49.0 From f1d37f21f720770a085cbcbd3370d43d570f4e3c Mon Sep 17 00:00:00 2001 From: Beta Date: Fri, 12 Dec 2025 14:24:50 -0300 Subject: [PATCH 16/23] tageo como instalacion esto --- roles/knsupdate/tasks/main.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/roles/knsupdate/tasks/main.yml b/roles/knsupdate/tasks/main.yml index 7e3b166..41743da 100644 --- a/roles/knsupdate/tasks/main.yml +++ b/roles/knsupdate/tasks/main.yml @@ -2,5 +2,6 @@ apt: name: "knot-dnsutils" state: "present" - + tags: installation + - include_tasks: loop.yml -- 2.49.0 From 7d5044f1f10753b673764bd47f97690f468d929c Mon Sep 17 00:00:00 2001 From: Beta Date: Fri, 12 Dec 2025 15:15:22 -0300 Subject: [PATCH 17/23] feat: add support for root domain www.abyaya.la Add capability to route root domain (abyaya.la and www.abyaya.la) to sutty.comun while maintaining all existing subdomain routes. Changes: - Add no_wildcard flag support in certbot certificate generation - Split certificate obtention into two conditional paths: * Standard mode (with wildcard) for subdomains * No-wildcard mode for root domains - Add abyaya_root service in matrix routing to sutty.comun - Include implementation plan as README-root-domain.md Technical details: - Certificates for root domain will only include abyaya.la and www.abyaya.la (no *.abyaya.la wildcard) - Prevents certificate confusion between root and subdomains - Maintains clean separation of responsibilities - All existing subdomain certificates remain unchanged Generated with Claude Code --- README-root-domain.md | 94 +++++++++++++++++++++++++++++++++ abyayala.yml | 9 ++++ roles/certbot/tasks/certbot.yml | 26 ++++++++- 3 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 README-root-domain.md diff --git a/README-root-domain.md b/README-root-domain.md new file mode 100644 index 0000000..7cf3800 --- /dev/null +++ b/README-root-domain.md @@ -0,0 +1,94 @@ +# Plan: Añadir Soporte para Dominio Principal www.abyaya.la + +## Objetivo +Habilitar que el dominio raíz `abyaya.la` y `www.abyaya.la` apunten al servidor `sutty.comun`, mientras se mantienen funcionando todos los subdominios existentes (ej: `sutty.abyaya.la`, `marmite.abyaya.la`). + +## Estrategia de Desarrollo + +### Rama Tópica +Los cambios se implementarán en esta rama tópica: +- **Nombre de rama**: `root-domain` +- **Bifurcada desde**: `master` + +## Contexto Técnico + +### Arquitectura Actual +- **Certificados**: Cada servicio en `abyayala.yml` con `domains` + `nodo` genera un certificado con certbot: `-d DOMAIN -d *.DOMAIN` +- **Patron actual**: Todos los dominios siguen el patrón `subdomain.abyaya.la` (ej: `sutty.abyaya.la`) + +### Decisión de Diseño +Crear un **servicio separado** para el dominio raíz con un nuevo flag `no_wildcard: yes` que indica a certbot que NO solicite el certificado wildcard. Esto mantiene limpia la separación de responsabilidades: +- Servicio `sutty`: maneja `sutty.abyaya.la` y `*.sutty.abyaya.la` +- Servicio `abyaya_root`: maneja únicamente `abyaya.la` y `www.abyaya.la` (sin wildcard) + +## Cambios Implementados + +### 1. `roles/certbot/tasks/certbot.yml` +- Agregado flag `no_wildcard_mode` para detectar servicios que no requieren wildcard +- Dividido el bloque de certificados en dos tareas condicionales: + - Modo estándar (con wildcard): para subdominios + - Modo sin wildcard: para dominios raíz + +### 2. `abyayala.yml` +- Agregado servicio `abyaya_root` con: + - Dominios: `abyaya.la` y `www.abyaya.la` + - Enrutamiento a: `sutty.comun` + - Flag: `no_wildcard: yes` + - HTTPS forzado y compresión habilitada + +## Comandos de Despliegue + +### Despliegue completo +```bash +ansible-playbook deploy.yml -e "alt=abyayala host=hetzner" +``` + +### Despliegue solo del servicio nuevo (para testing) +```bash +ansible-playbook deploy.yml -e "alt=abyayala host=hetzner service=abyaya_root" +``` + +## Verificación Post-Despliegue + +### 1. Verificar certificado +```bash +ssh root@hetzner +ls -la /var/lib/docker/volumes/abyayala_certs_data/_data/live/abyaya.la/ +docker run --rm -v abyayala_certs_data:/etc/letsencrypt certbot/certbot certificates | grep abyaya.la +``` + +Debe contener: `abyaya.la`, `www.abyaya.la` (SIN `*.abyaya.la`) + +### 2. Verificar nginx +```bash +cat /opt/abyayala/proxy/vhosts/abyaya.la.conf +docker exec abyayala_proxy nginx -t +``` + +### 3. Verificar enrutamiento +```bash +curl -I http://abyaya.la # Debe redirigir a HTTPS +curl -I https://abyaya.la # Debe devolver 200 OK +curl -I https://www.abyaya.la # Debe devolver 200 OK +``` + +### 4. Verificar subdominios siguen funcionando +```bash +curl -I https://sutty.abyaya.la +curl -I https://marmite.abyaya.la +``` + +## Requisitos DNS + +Antes del despliegue, configurar: +``` +abyaya.la A +www.abyaya.la A +``` + +## Extensibilidad Futura + +Este patrón `no_wildcard: yes` puede reutilizarse para otros dominios raíz: +1. Agregar entrada en `abyayala.yml` con `no_wildcard: yes` +2. Desplegar con ansible-playbook +3. Configurar DNS diff --git a/abyayala.yml b/abyayala.yml index 53fbb9e..a075cd5 100644 --- a/abyayala.yml +++ b/abyayala.yml @@ -166,6 +166,15 @@ matrix: force_https: yes enable_compression: yes + - service_name: abyaya_root + domains: + - abyaya.la + - www.abyaya.la + nodo: sutty.comun + force_https: yes + enable_compression: yes + no_wildcard: yes + - service_name: mexe domains: - mexe.abyaya.la diff --git a/roles/certbot/tasks/certbot.yml b/roles/certbot/tasks/certbot.yml index 348ab90..b256e27 100644 --- a/roles/certbot/tasks/certbot.yml +++ b/roles/certbot/tasks/certbot.yml @@ -21,7 +21,10 @@ - set_fact: vhost: "{{ loop }}" - - name: fetch certificate with certbot container + - set_fact: + no_wildcard_mode: "{{ loop.no_wildcard | default(false) | bool }}" + + - name: fetch certificate with certbot container (with wildcard) docker_container: name: chencriptemos image: "{{ CERTBOT_image }}" @@ -31,12 +34,31 @@ command: "--non-interactive --agree-tos --expand --email {{ webmaster_email }} certonly --preferred-challenges dns --authenticator dns-standalone --dns-standalone-address={{ host_ip }} --dns-standalone-port=53 --dns-standalone-propagation-seconds=10 {% for domain in loop.domains %} -d {{ domain }} -d *.{{ domain }} {% endfor %}" detach: no cleanup: yes - ports: + ports: - "{{ host_ip }}:53:53/tcp" - "{{ host_ip }}:53:53/udp" notify: - reload proxy register: cert_result + when: not no_wildcard_mode | bool + + - name: fetch certificate with certbot container (without wildcard) + docker_container: + name: chencriptemos + image: "{{ CERTBOT_image }}" + state: started + volumes: + - "{{ althost }}_certs_data:/etc/letsencrypt" + command: "--non-interactive --agree-tos --email {{ webmaster_email }} certonly --preferred-challenges dns --authenticator dns-standalone --dns-standalone-address={{ host_ip }} --dns-standalone-port=53 --dns-standalone-propagation-seconds=10 {% for domain in loop.domains %} -d {{ domain }} {% endfor %}" + detach: no + cleanup: yes + ports: + - "{{ host_ip }}:53:53/tcp" + - "{{ host_ip }}:53:53/udp" + notify: + - reload proxy + register: cert_result + when: no_wildcard_mode | bool when: obtain_cert | bool -- 2.49.0 From fc76a7fb91c2b1ecff1737c1df6552306f48aaff Mon Sep 17 00:00:00 2001 From: Beta Date: Mon, 15 Dec 2025 19:45:54 -0300 Subject: [PATCH 18/23] refactor: rename no_wildcard to root and fix nginx vhost generation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename the flag from `no_wildcard` to `root` throughout the codebase for better semantics, and fix nginx configuration generation for root domains. Changes: 1. Renamed `no_wildcard` → `root` flag in: - abyayala.yml (abyaya_root service) - roles/certbot/tasks/certbot.yml (uses is_root_domain internally) - README-root-domain.md (documentation) 2. Fixed nginx vhost generation in roles/proxy/templates/: - vhost.conf: Handle root domains without leading dot in server_name * root: yes → `server_name abyaya.la www.abyaya.la;` (exact match) * root: no → `server_name .comun.abyaya.la;` (wildcard match) - stream.conf: Same logic for SSH proxy streams Problem fixed: - Previous: `.abyaya.la` matched all subdomains, conflicting with other vhosts (comun.abyaya.la, sutty.abyaya.la, etc.) - Now: `abyaya.la www.abyaya.la` matches only root domain exactly 🤖 Generated with Claude Code Co-Authored-By: Claude Sonnet 4.5 --- README-root-domain.md | 21 +++++++++++++-------- abyayala.yml | 2 +- roles/certbot/tasks/certbot.yml | 8 ++++---- roles/proxy/templates/stream.conf | 6 +++++- roles/proxy/templates/vhost.conf | 8 ++++++++ 5 files changed, 31 insertions(+), 14 deletions(-) diff --git a/README-root-domain.md b/README-root-domain.md index 7cf3800..075dc8c 100644 --- a/README-root-domain.md +++ b/README-root-domain.md @@ -17,23 +17,28 @@ Los cambios se implementarán en esta rama tópica: - **Patron actual**: Todos los dominios siguen el patrón `subdomain.abyaya.la` (ej: `sutty.abyaya.la`) ### Decisión de Diseño -Crear un **servicio separado** para el dominio raíz con un nuevo flag `no_wildcard: yes` que indica a certbot que NO solicite el certificado wildcard. Esto mantiene limpia la separación de responsabilidades: +Crear un **servicio separado** para el dominio raíz con un nuevo flag `root: yes` que indica a certbot que NO solicite el certificado wildcard. Esto mantiene limpia la separación de responsabilidades: - Servicio `sutty`: maneja `sutty.abyaya.la` y `*.sutty.abyaya.la` - Servicio `abyaya_root`: maneja únicamente `abyaya.la` y `www.abyaya.la` (sin wildcard) ## Cambios Implementados ### 1. `roles/certbot/tasks/certbot.yml` -- Agregado flag `no_wildcard_mode` para detectar servicios que no requieren wildcard +- Lee el flag `root` del servicio y lo mapea a variable `is_root_domain` - Dividido el bloque de certificados en dos tareas condicionales: - - Modo estándar (con wildcard): para subdominios - - Modo sin wildcard: para dominios raíz + - Modo estándar (con wildcard): para subdominios (`when: not is_root_domain`) + - Modo sin wildcard: para dominios raíz (`when: is_root_domain`) -### 2. `abyayala.yml` +### 2. `roles/proxy/templates/vhost.conf` +- Agregado condicional para manejar flag `root` +- Cuando `root: yes`: genera `server_name` sin punto prefijo (exacto) +- Cuando `root: no` (default): genera `server_name .domain` (con wildcard) + +### 3. `abyayala.yml` - Agregado servicio `abyaya_root` con: - Dominios: `abyaya.la` y `www.abyaya.la` - Enrutamiento a: `sutty.comun` - - Flag: `no_wildcard: yes` + - Flag: `root: yes` - HTTPS forzado y compresión habilitada ## Comandos de Despliegue @@ -88,7 +93,7 @@ www.abyaya.la A ## Extensibilidad Futura -Este patrón `no_wildcard: yes` puede reutilizarse para otros dominios raíz: -1. Agregar entrada en `abyayala.yml` con `no_wildcard: yes` +Este patrón `root: yes` puede reutilizarse para otros dominios raíz: +1. Agregar entrada en `abyayala.yml` con `root: yes` 2. Desplegar con ansible-playbook 3. Configurar DNS diff --git a/abyayala.yml b/abyayala.yml index a075cd5..073d7a3 100644 --- a/abyayala.yml +++ b/abyayala.yml @@ -173,7 +173,7 @@ matrix: nodo: sutty.comun force_https: yes enable_compression: yes - no_wildcard: yes + root: yes - service_name: mexe domains: diff --git a/roles/certbot/tasks/certbot.yml b/roles/certbot/tasks/certbot.yml index b256e27..50e9031 100644 --- a/roles/certbot/tasks/certbot.yml +++ b/roles/certbot/tasks/certbot.yml @@ -22,7 +22,7 @@ vhost: "{{ loop }}" - set_fact: - no_wildcard_mode: "{{ loop.no_wildcard | default(false) | bool }}" + is_root_domain: "{{ loop.root | default(false) | bool }}" - name: fetch certificate with certbot container (with wildcard) docker_container: @@ -40,9 +40,9 @@ notify: - reload proxy register: cert_result - when: not no_wildcard_mode | bool + when: not is_root_domain | bool - - name: fetch certificate with certbot container (without wildcard) + - name: fetch certificate with certbot container (without wildcard, root domain) docker_container: name: chencriptemos image: "{{ CERTBOT_image }}" @@ -58,7 +58,7 @@ notify: - reload proxy register: cert_result - when: no_wildcard_mode | bool + when: is_root_domain | bool when: obtain_cert | bool diff --git a/roles/proxy/templates/stream.conf b/roles/proxy/templates/stream.conf index bf54232..95ae361 100644 --- a/roles/proxy/templates/stream.conf +++ b/roles/proxy/templates/stream.conf @@ -5,7 +5,11 @@ upstream ssh_{{ vhost.nodo | replace(".", "") }} { server { listen {{ vhost.ports[0] }}; - server_name {{ vhost.service_name }}.abyaya.la; + {% if vhost.root | default(false) %} + server_name {{ vhost.domains | join(' ') }}; + {% else %} + server_name .{{ vhost.domains | join(' .') }}; + {% endif %} proxy_pass ssh_{{ vhost.nodo | replace(".", "") }}; } \ No newline at end of file diff --git a/roles/proxy/templates/vhost.conf b/roles/proxy/templates/vhost.conf index 647913e..c16ae05 100644 --- a/roles/proxy/templates/vhost.conf +++ b/roles/proxy/templates/vhost.conf @@ -1,12 +1,20 @@ map $http_host $comun_{{ vhost.nodo | replace(".", "") }} { hostnames; {% for domain in vhost.domains %} + {% if vhost.root | default(false) %} + {{ domain }} {{ vhost.nodo }}; + {% else %} .{{ domain }} {{ vhost.nodo }}; + {% endif %} {% endfor %} } server { + {% if vhost.root | default(false) %} + server_name {{ vhost.domains | join(' ') }}; + {% else %} server_name .{{ vhost.domains | join(' .') }}; + {% endif %} listen 80; -- 2.49.0 From 0a99c7f2d1c8e344c5c30a0151d7df69954c695c Mon Sep 17 00:00:00 2001 From: Beta Date: Mon, 15 Dec 2025 14:03:22 -0300 Subject: [PATCH 19/23] feat: implement webroot method for root domain SSL certificates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace dns-standalone with HTTP-01 webroot validation for root domains (when root: yes flag is set). This change improves reliability by avoiding DNS conflicts and simplifies the certificate obtention process. Changes: - Add acme_challenge.conf to serve .well-known/acme-challenge directory - Update certbot.yml to use --webroot for root domains instead of dns-standalone - Use official certbot/certbot:latest image for webroot (lighter, no DNS needed) - Add certbot_webroot volume shared between nginx and certbot containers - Configure vhost.conf to include ACME challenge location for root domains - Add certbot_webroot variable (/var/www/certbot) to proxy vars Benefits for root domains: - No port 53 conflicts with Knot DNS - Faster validation (HTTP vs DNS propagation) - More reliable and simpler error handling - Works with nginx already running on port 80 Wildcard domains continue using DNS-01 challenge as HTTP-01 does not support wildcard certificates. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- roles/certbot/tasks/certbot.yml | 10 ++++----- roles/proxy/templates/acme_challenge.conf | 25 +++++++++++++++++++++++ roles/proxy/templates/services.yml | 1 + roles/proxy/templates/vhost.conf | 5 +++++ roles/proxy/templates/volumes.yml | 1 + roles/proxy/vars/main.yml | 1 + 6 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 roles/proxy/templates/acme_challenge.conf diff --git a/roles/certbot/tasks/certbot.yml b/roles/certbot/tasks/certbot.yml index 50e9031..52d1570 100644 --- a/roles/certbot/tasks/certbot.yml +++ b/roles/certbot/tasks/certbot.yml @@ -42,19 +42,17 @@ register: cert_result when: not is_root_domain | bool - - name: fetch certificate with certbot container (without wildcard, root domain) + - name: fetch certificate with certbot container (without wildcard, root domain - using webroot) docker_container: name: chencriptemos - image: "{{ CERTBOT_image }}" + image: certbot/certbot:latest state: started volumes: - "{{ althost }}_certs_data:/etc/letsencrypt" - command: "--non-interactive --agree-tos --email {{ webmaster_email }} certonly --preferred-challenges dns --authenticator dns-standalone --dns-standalone-address={{ host_ip }} --dns-standalone-port=53 --dns-standalone-propagation-seconds=10 {% for domain in loop.domains %} -d {{ domain }} {% endfor %}" + - "{{ althost }}_certbot_webroot:{{ certbot_webroot }}" + command: "--non-interactive --agree-tos --email {{ webmaster_email }} certonly --webroot --webroot-path {{ certbot_webroot }} {% for domain in loop.domains %} -d {{ domain }} {% endfor %}" detach: no cleanup: yes - ports: - - "{{ host_ip }}:53:53/tcp" - - "{{ host_ip }}:53:53/udp" notify: - reload proxy register: cert_result diff --git a/roles/proxy/templates/acme_challenge.conf b/roles/proxy/templates/acme_challenge.conf new file mode 100644 index 0000000..0474dab --- /dev/null +++ b/roles/proxy/templates/acme_challenge.conf @@ -0,0 +1,25 @@ +# Let's Encrypt ACME challenge configuration +# This configuration serves the .well-known/acme-challenge directory +# for HTTP-01 validation when using webroot method + +location ^~ /.well-known/acme-challenge/ { + # Serve files from the certbot webroot + root {{ certbot_webroot }}; + + # Allow access to challenge files + allow all; + + # Ensure plain text content type + default_type "text/plain"; + + # Disable any authentication + auth_basic off; + + # Serve the challenge file directly + try_files $uri =404; +} + +# Deny access to other .well-known paths for security +location ~ /\.well-known/ { + deny all; +} diff --git a/roles/proxy/templates/services.yml b/roles/proxy/templates/services.yml index 082f378..0fdf499 100644 --- a/roles/proxy/templates/services.yml +++ b/roles/proxy/templates/services.yml @@ -19,3 +19,4 @@ - "certs_data:{{ nginx_certs_path }}:ro" - "{{ conf_path }}/nginx.conf:/etc/nginx/nginx.conf:ro" - "{{ stream_path }}:/etc/nginx/stream.d/" + - "certbot_webroot:{{ certbot_webroot }}" diff --git a/roles/proxy/templates/vhost.conf b/roles/proxy/templates/vhost.conf index c16ae05..46e1d7d 100644 --- a/roles/proxy/templates/vhost.conf +++ b/roles/proxy/templates/vhost.conf @@ -21,6 +21,11 @@ server { resolver 10.13.12.1 valid=300s; resolver_timeout 5s; +{% if vhost.root | default(false) %} + # ACME challenge for HTTP-01 validation (webroot method for root domains) + include conf/acme_challenge.conf; +{% endif %} + {% if not needs_vhost and ((vhost.ssl | default(domains_default_ssl) ) or (vhost.force_https | default(domains_default_force_https))) %} listen 443 ssl; diff --git a/roles/proxy/templates/volumes.yml b/roles/proxy/templates/volumes.yml index dab0d32..215cb6c 100644 --- a/roles/proxy/templates/volumes.yml +++ b/roles/proxy/templates/volumes.yml @@ -1 +1,2 @@ certs_data: + certbot_webroot: diff --git a/roles/proxy/vars/main.yml b/roles/proxy/vars/main.yml index 4a8ed0d..d541bb7 100644 --- a/roles/proxy/vars/main.yml +++ b/roles/proxy/vars/main.yml @@ -15,3 +15,4 @@ default_stream: roles/proxy/templates/stream.conf # certbot webmaster_email: webmaster@numerica.cl CERTBOT_image: numericalatina/certbot-wildcard +certbot_webroot: /var/www/certbot -- 2.49.0 From 7e12b7b20a4d575377575e490f187e9371e81e28 Mon Sep 17 00:00:00 2001 From: Beta Date: Mon, 15 Dec 2025 19:49:25 -0300 Subject: [PATCH 20/23] poner archivos de webroot --- abyayala.yml | 6 +++++- roles/proxy/tasks/main.yml | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/abyayala.yml b/abyayala.yml index 073d7a3..a621f15 100644 --- a/abyayala.yml +++ b/abyayala.yml @@ -214,10 +214,14 @@ matrix: - service_name: kipu domains: - - kipu.latina.red + - abyaya.la + - www.abyaya.la +# - kipu.abyaya.la nodo: kipu.comun ports: - 223 + force_https: yes + root: yes - service_name: carabobolibre domains: diff --git a/roles/proxy/tasks/main.yml b/roles/proxy/tasks/main.yml index d60418b..8ce8c1b 100644 --- a/roles/proxy/tasks/main.yml +++ b/roles/proxy/tasks/main.yml @@ -15,6 +15,7 @@ with_items: - "{{ stream_path }}" - "{{ conf_path }}" + - "{{ certbot_webroot }}" loop_control: loop_var: comun @@ -32,6 +33,7 @@ - common.conf - common_ssl.conf - nginx.conf + - acme_challenge.conf loop_control: loop_var: common -- 2.49.0 From a8b3a63807a06996c67817cd3c18f0a8a987063d Mon Sep 17 00:00:00 2001 From: Beta Date: Tue, 16 Dec 2025 00:30:09 -0300 Subject: [PATCH 21/23] se agrega expand en caso de certbot y se arregla condicion de Knsupdate (que sera solo para abyayala_subdomains). en la amtriz testeando en prod --- abyayala.yml | 10 +++++----- roles/certbot/tasks/certbot.yml | 4 ++-- roles/knsupdate/tasks/templates/commands.j2 | 5 +---- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/abyayala.yml b/abyayala.yml index a621f15..6e78f34 100644 --- a/abyayala.yml +++ b/abyayala.yml @@ -214,14 +214,14 @@ matrix: - service_name: kipu domains: - - abyaya.la - - www.abyaya.la -# - kipu.abyaya.la +# - abyaya.la +# - www.abyaya.la + - kipu.latina.red nodo: kipu.comun ports: - 223 - force_https: yes - root: yes + ssl: yes +# root: yes - service_name: carabobolibre domains: diff --git a/roles/certbot/tasks/certbot.yml b/roles/certbot/tasks/certbot.yml index 52d1570..f079a5c 100644 --- a/roles/certbot/tasks/certbot.yml +++ b/roles/certbot/tasks/certbot.yml @@ -31,7 +31,7 @@ state: started volumes: - "{{ althost }}_certs_data:/etc/letsencrypt" - command: "--non-interactive --agree-tos --expand --email {{ webmaster_email }} certonly --preferred-challenges dns --authenticator dns-standalone --dns-standalone-address={{ host_ip }} --dns-standalone-port=53 --dns-standalone-propagation-seconds=10 {% for domain in loop.domains %} -d {{ domain }} -d *.{{ domain }} {% endfor %}" + command: "--non-interactive --agree-tos --expand --email {{ webmaster_email }} certonly --preferred-challenges dns --authenticator dns-standalone --dns-standalone-address={{ host_ip }} --dns-standalone-port=53 --dns-standalone-propagation-seconds=10 {% for domain in loop.domains %} -d {{ domain }} -d *.{{ domain }} {% endfor %}" detach: no cleanup: yes ports: @@ -50,7 +50,7 @@ volumes: - "{{ althost }}_certs_data:/etc/letsencrypt" - "{{ althost }}_certbot_webroot:{{ certbot_webroot }}" - command: "--non-interactive --agree-tos --email {{ webmaster_email }} certonly --webroot --webroot-path {{ certbot_webroot }} {% for domain in loop.domains %} -d {{ domain }} {% endfor %}" + command: "--non-interactive --agree-tos --expand --email {{ webmaster_email }} certonly --webroot --webroot-path {{ certbot_webroot }} {% for domain in loop.domains %} -d {{ domain }} {% endfor %}" detach: no cleanup: yes notify: diff --git a/roles/knsupdate/tasks/templates/commands.j2 b/roles/knsupdate/tasks/templates/commands.j2 index b08cb57..5154ab7 100644 --- a/roles/knsupdate/tasks/templates/commands.j2 +++ b/roles/knsupdate/tasks/templates/commands.j2 @@ -9,11 +9,8 @@ del {{ hostname }} a del {{ hostname }} ns add {{ hostname }} a {{ host_ip }} -{% if is_abyayala_subdomain %} {# if vho != '@' and vho != 'www' #} +{% if hostname != '@' and hostname != 'www' %} add *.{{ hostname }} a {{ host_ip }} -{% else %} -add {{ domain }} a {{ host_ip }} -add *.{{ domain }} a {{ host_ip }} {% endif %} {% if hostname == '@' %} -- 2.49.0 From 216c81df39ee39d445c6cb8e50ca0d9d13a4651d Mon Sep 17 00:00:00 2001 From: Beta Date: Tue, 16 Dec 2025 00:27:40 -0300 Subject: [PATCH 22/23] feat: use knsupdate only for abyayala subdomains, display DNS config for external domains MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - knsupdate now only executes when is_abyayala_subdomain is true - For external domains, display DNS configuration instructions in console - Created dns_info.j2 template to show required DNS records for manual configuration - External domains now show: A records, wildcard A records, and ACME challenge NS delegation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- roles/knsupdate/tasks/templates/dns_info.j2 | 21 +++++++++++++++++++++ roles/knsupdate/tasks/update_domain.yml | 6 ++++++ 2 files changed, 27 insertions(+) create mode 100644 roles/knsupdate/tasks/templates/dns_info.j2 diff --git a/roles/knsupdate/tasks/templates/dns_info.j2 b/roles/knsupdate/tasks/templates/dns_info.j2 new file mode 100644 index 0000000..24db930 --- /dev/null +++ b/roles/knsupdate/tasks/templates/dns_info.j2 @@ -0,0 +1,21 @@ + +======================================== +DNS Configuration Required for: {{ domain }} +======================================== +Please configure the following DNS records in your DNS provider: + +{% if hostname == '@' %} +{{ zone | regex_replace('\\.$', '') }} IN A {{ host_ip }} +*.{{ zone | regex_replace('\\.$', '') }} IN A {{ host_ip }} + +_acme-challenge.{{ zone | regex_replace('\\.$', '') }} IN NS ns-acme.{{ zone | regex_replace('\\.$', '') }}. +ns-acme.{{ zone | regex_replace('\\.$', '') }} IN A {{ host_ip }} +{% else %} +{{ hostname }}.{{ zone | regex_replace('\\.$', '') }} IN A {{ host_ip }} +*.{{ hostname }}.{{ zone | regex_replace('\\.$', '') }} IN A {{ host_ip }} + +_acme-challenge.{{ hostname }}.{{ zone | regex_replace('\\.$', '') }} IN NS ns-acme.{{ hostname }}.{{ zone | regex_replace('\\.$', '') }}. +ns-acme.{{ hostname }}.{{ zone | regex_replace('\\.$', '') }} IN A {{ host_ip }} +{% endif %} + +======================================== diff --git a/roles/knsupdate/tasks/update_domain.yml b/roles/knsupdate/tasks/update_domain.yml index d657d7d..841342d 100644 --- a/roles/knsupdate/tasks/update_domain.yml +++ b/roles/knsupdate/tasks/update_domain.yml @@ -34,3 +34,9 @@ shell: knsupdate args: stdin: "{{ lookup('template', 'templates/commands.j2') }}" + when: is_abyayala_subdomain + + - name: display DNS configuration instructions for external domains + debug: + msg: "{{ lookup('template', 'templates/dns_info.j2') }}" + when: not is_abyayala_subdomain -- 2.49.0 From 89866df0bf31bf838a481a9cb3d73b9a5b271737 Mon Sep 17 00:00:00 2001 From: Beta Date: Tue, 16 Dec 2025 00:45:50 -0300 Subject: [PATCH 23/23] Soporte FQDN closes #76 --- roles/knsupdate/tasks/templates/commands.j2 | 3 +++ roles/knsupdate/tasks/templates/dns_info.j2 | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/roles/knsupdate/tasks/templates/commands.j2 b/roles/knsupdate/tasks/templates/commands.j2 index 5154ab7..8e85edc 100644 --- a/roles/knsupdate/tasks/templates/commands.j2 +++ b/roles/knsupdate/tasks/templates/commands.j2 @@ -11,6 +11,9 @@ add {{ hostname }} a {{ host_ip }} {% if hostname != '@' and hostname != 'www' %} add *.{{ hostname }} a {{ host_ip }} +{% else %} +add {{ domain }} a {{ host_ip }} +add *.{{ domain }} a {{ host_ip }} {% endif %} {% if hostname == '@' %} diff --git a/roles/knsupdate/tasks/templates/dns_info.j2 b/roles/knsupdate/tasks/templates/dns_info.j2 index 24db930..f46df2e 100644 --- a/roles/knsupdate/tasks/templates/dns_info.j2 +++ b/roles/knsupdate/tasks/templates/dns_info.j2 @@ -1,8 +1,8 @@ ======================================== -DNS Configuration Required for: {{ domain }} +Configuracion de DNS requerida: {{ domain }} ======================================== -Please configure the following DNS records in your DNS provider: +Por favor configue los siguiente registros DNS en su proveedor: {% if hostname == '@' %} {{ zone | regex_replace('\\.$', '') }} IN A {{ host_ip }} -- 2.49.0