Soporte para FQDN #76
133
FQDN_AUTHORITATIVE.md
Normal file
@ -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
|
||||
|
fauno marked this conversation as resolved
|
||||
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
|
||||
|
Numerica marked this conversation as resolved
fauno
commented
no veo dónde sucede esto, ya lo hacía certbot? me preocupa en términos de privacidad hacer público que dos o más dominios están relacionados con la misma huerta, y que certbot haga cualquiera cuando agreguemos un dominio más. haría que certbot genere un certificado para cada dominio. si eso es muy complicado, usaría la flag no veo dónde sucede esto, ya lo hacía certbot? me preocupa en términos de privacidad hacer público que dos o más dominios están relacionados con la misma huerta, y que certbot haga cualquiera cuando agreguemos un dominio más. haría que certbot genere un certificado para cada dominio. si eso es muy complicado, usaría la flag `--expand` para aclarar que queres que se agreguen dominios a un certificado que ya existía. sino creo que hace la gilada esa de poner -0001 al final del archivo
fauno
commented
en el primer caso, hay que generar un archivo de configuración de nginx por cada dominio o hacer que el certificado se cargue desde la variable en el primer caso, hay que generar un archivo de configuración de nginx por cada dominio o hacer que el certificado se cargue desde la variable `$ssl_server_name`
Numerica
commented
interesante..
interesante..
- si, ya lo hacía certbot, estaba comentando desde que cambiamos a standalone. lo deja en un cron
- si, toma para todos los dominios. efectivamente es un problema cuando agregamos posteriormente dominios (en mi experiencia en Numérica). si lo podemos resolver con --expand creo que sería fácil y limpio, es lo que estamos haciendo.
- dominios independiente resolverían el tema que planteas de privacidad, lo evaluaremos
fauno
commented
ok le agregás el --expand por ahora? ok le agregás el --expand por ahora?
|
||||
```
|
||||
|
||||
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.
|
||||
|
Numerica marked this conversation as resolved
fauno
commented
guarda que esto implica que haya un subdominio guarda que esto implica que haya un subdominio `_acme-challenge` para todos los dominios solicitados
Numerica
commented
si, se estarían agregando más abajo en knsupdate si, se estarían agregando más abajo en knsupdate
|
||||
|
||||
## 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
|
||||
10
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:
|
||||
|
||||
@ -31,7 +31,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:
|
||||
@ -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:
|
||||
|
||||
@ -1,25 +1,27 @@
|
||||
{% for dns_server in dns_servers %}
|
||||
|
||||
server {{ dns_server }}
|
||||
zone abyaya.la.
|
||||
origin abyaya.la.
|
||||
zone {{ zone }}
|
||||
|
Numerica marked this conversation as resolved
fauno
commented
no habria que agregar el punto al final? no habria que agregar el punto al final?
fauno
commented
ah, el punto se lo agrega la extracción de la zona ah, el punto se lo agrega la extracción de la zona
|
||||
origin {{ zone }}
|
||||
ttl 60
|
||||
|
||||
del {{ vho }} a
|
||||
del {{ vho }} ns
|
||||
del {{ hostname }} a
|
||||
del {{ hostname }} ns
|
||||
add {{ hostname }} a {{ host_ip }}
|
||||
|
||||
add {{ vho }} a {{ host_ip }}
|
||||
|
||||
{% if vho != '@' and vho != 'www' %}
|
||||
add *.{{ vho }} a {{ host_ip }}
|
||||
{% if hostname != '@' and hostname != 'www' %}
|
||||
add *.{{ hostname }} a {{ host_ip }}
|
||||
{% else %}
|
||||
add {{ domain }} a {{ host_ip }}
|
||||
add *.{{ domain }} a {{ host_ip }}
|
||||
|
Numerica marked this conversation as resolved
Outdated
fauno
commented
ok, todo esto asume que todos los dominios estan gestionados por el mismo dns, cierto? ok, todo esto asume que todos los dominios estan gestionados por el mismo dns, cierto?
Numerica
commented
si, por ej el dominio kipu.latina.red lo delegué, puede hacerle mas, relacionado a esto quizas falte arreglar algo, que crea estar publicando estos registros en knsupdate tambien? en realidad debe escupirlos como una instruccion: "Copia esto en tu servidor DNS" si, por ej el dominio kipu.latina.red lo delegué, puede hacerle
```
dig kipu.latina.red NS
dig kipu.latina.red CNAME
```
mas, relacionado a esto quizas falte arreglar algo, que crea estar publicando estos registros en knsupdate tambien? en realidad debe escupirlos como una instruccion: "Copia esto en tu servidor DNS"
fauno
commented
a donde lo delegaste? lo que digo es que la delegación y el knsupdate a los knot de sutty solo es necesaria para HUERTA.abyaya.la, pero no para otros dominios a donde lo delegaste? lo que digo es que la delegación y el knsupdate a los knot de sutty solo es necesaria para HUERTA.abyaya.la, pero no para otros dominios
|
||||
{% endif %}
|
||||
|
||||
{% if vho == '@' %}
|
||||
{% if hostname == '@' %}
|
||||
add _acme-challenge a {{ host_ip }}
|
||||
add _acme-challenge ns _acme-challenge
|
||||
{% else %}
|
||||
add _acme-challenge.{{ vho }} a {{ host_ip }}
|
||||
add _acme-challenge.{{ vho }} ns _acme-challenge
|
||||
add _acme-challenge.{{ hostname }} a {{ host_ip }}
|
||||
add _acme-challenge.{{ hostname }} ns _acme-challenge
|
||||
{% endif %}
|
||||
|
||||
{% include "files/dns_extras/" ~ vhost.domains[0] ignore missing %}
|
||||
|
||||
21
roles/knsupdate/tasks/templates/dns_info.j2
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
========================================
|
||||
Configuracion de DNS requerida: {{ domain }}
|
||||
========================================
|
||||
Por favor configue los siguiente registros DNS en su proveedor:
|
||||
|
||||
{% 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 %}
|
||||
|
||||
========================================
|
||||
@ -1,14 +1,5 @@
|
||||
- set_fact:
|
||||
vho: >-
|
||||
{%- if vhost.domains[0] == 'abyaya.la' -%}
|
||||
@
|
||||
{%- elif vhost.domains[0].endswith('.abyaya.la') -%}
|
||||
{{ vhost.domains[0] | regex_replace('([a-z0-9]+)\\.abyaya\\.la', '\\1') }}
|
||||
{%- else -%}
|
||||
{{ vhost.domains[0] | regex_replace('\\.abyaya\\.la$', '') }}
|
||||
{%- endif -%}
|
||||
|
||||
- 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
|
||||
42
roles/knsupdate/tasks/update_domain.yml
Normal file
@ -0,0 +1,42 @@
|
||||
- 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
|
||||
|
fauno
commented
no entiendo para qué hacer todo esto, si le paso un dominio no entiendo para qué hacer todo esto, si le paso un dominio `sutty.coop.ar` o `sutty.nl` va a pensar que la zona es `.coop.ar.` y `.nl.`?
fauno
commented
o entiendo que pasandolo por la lista o entiendo que pasandolo por la lista `compound_tlds` obtiene que la zona es `sutty.coop.ar` siempre y cuando `.coop.ar` esté incluido en `compound_tlds`?
fauno
commented
en cualquier caso me parece raro tener que hacer todo esto, porque...
en cualquier caso me parece raro tener que hacer todo esto, porque...
* no podemos asumir que el dominio es la zona? entonces el fqdn `sutty.coop.ar` es una zona en knot que ya acepta actualizaciones desde el proxy.
* en el caso de `huerta.abyaya.la`, ya sabemos que la zona es `abyaya.la`.
* con eso, no haría falta tener una lista de tlds admitidos (tarea extra, confusión frente a dominios nuevos, configuraciones potencialmente rotas)
* de hecho, los dominios externos no necesitan knot para nada, porque esa configuración se puede hacer estáticamente. usamos knot para dar de alta huertas automáticamente, pero un dominio nuevo se configura una sola vez y ya.
Numerica
commented
la idea aqui era soportar fqdn que puedan ser compuestos, previendo que pasará con nuevaradio.org.ar y así está bien que esto no pase por knsupdate, pero es soporte para estos dominios a lo largo del código (las regex cachan si es fqdn o compuesto y ajustan las variables acorde) la idea aqui era soportar fqdn que puedan ser compuestos, previendo que pasará con __nuevaradio.org.ar__ y así
está bien que esto no pase por knsupdate, pero es soporte para estos dominios a lo largo del código (las regex cachan si es fqdn o compuesto y ajustan las variables acorde)
fauno
commented
entonces no entiendo la diferenciación que hacés entre fqdn y compuesto. para mi fqdn es cualquier dominio completo incluyendo (g)tld. la pregunta es por qué es necesario hacer todo esto si no es necesario hacer knsupdate para estos dominios entonces no entiendo la diferenciación que hacés entre fqdn y compuesto. para mi fqdn es cualquier dominio completo incluyendo (g)tld. `sutty.comun` es un fqdn, porque es un hostname dentro de un dominio, aunque su resolución no sea por dns publico.
la pregunta es por qué es necesario hacer todo esto si no es necesario hacer knsupdate para estos dominios
Numerica
commented
si. yo estoy mal con la nomenlclatura. me rediero a dominios externos (.org .com ...) si. yo estoy mal con la nomenlclatura. me rediero a dominios externos (.org .com ...)
|
||||
|
||||
- name: knsupdate for this domain
|
||||
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
|
||||
@ -3,3 +3,10 @@ dns_servers:
|
||||
- "athshe.sutty.nl"
|
||||
- "gethen.sutty.nl"
|
||||
- "ganam.sutty.nl"
|
||||
|
||||
compound_tlds:
|
||||
- com.ar
|
||||
- com.mx
|
||||
- com.br
|
||||
- org.ar
|
||||
- edu.ar
|
||||
@ -47,6 +47,24 @@
|
||||
loop_control:
|
||||
loop_var: domino
|
||||
|
fauno marked this conversation as resolved
Outdated
fauno
commented
me pregunto si es necesario agregar todo esto en vez de documentar y hacer explicito que hay que listar todos los dominios de una huerta me pregunto si es necesario agregar todo esto en vez de documentar y hacer explicito que hay que listar todos los dominios de una huerta
Numerica
commented
bueno digamos que ya está hecho y simplifica. tambien es retro-compatible entonces podes dejarlos si querés de hecho hice otra rama para unificar la definicio de nodo (que ahora siempre repetimos 3 veces llamandole igual 99.9% de las veces NODO.comun NODO.abayaya.la service_name: nodo, se reducen a una sola variable nodo #80 bueno digamos que ya está hecho y simplifica. tambien es retro-compatible entonces podes dejarlos si querés
de hecho hice otra rama para unificar la definicio de nodo (que ahora siempre repetimos 3 veces llamandole igual 99.9% de las veces NODO.comun NODO.abayaya.la service_name: nodo, se reducen a una sola variable nodo #80
|
||||
|
||||
- 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:
|
||||
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"
|
||||
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([]) }}"
|
||||
|
||||
- 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([]) }}"
|
||||
|
||||
creo que es confuso en la documentación decir que el dominio HUERTA.abyaya.la es automático y luego usar de ejemplo un subdominio de abyaya.la específico. creo que tendríamos que dejar los subdominios de abyaya.la reservados solo para huertas
Ah ok, aunque esa documentación es interna para nos, la eliminaremos en el merge
Los dominios* son para huertas, de hecho son el default, es opcional mencionarlos para retrocompatibilidad. en realidad ahora domains: servirá más para agregar dominios fqdn