Aplicación Python diseñada para automatizar la actualización de registros DNS en Cloudflare y la sincronización de la IP del sistema en HestiaCP. Ideal para servidores con direcciones IP dinámicas, como aquellas obtenidas mediante PPPoE.
- Detectar la nueva IP externa después de la reconexión de PPP (IP en texto plano).
- Usar
/usr/local/hestia/bin/v-list-users json
para obtener todos los usuarios de HestiaCP. - Para cada usuario, usar
/usr/local/hestia/bin/v-list-web-domains <user> json
para obtener sus dominios. - Para cada dominio, actualizar todos los registros DNS (A) en Cloudflare para que apunten a la nueva IP.
- Saltar los dominios (obtenidos de v-list-web-domains) listados en una lista configurable de exclusión.
- Ejecutar
/usr/local/hestia/bin/v-update-sys-ip
para actualizar la IP del sistema en HestiaCP. - Registrar todas las actividades, éxitos y errores en
debian syslog
, identificando el componente fuente.
- Detección de IP Externa: Identifica automáticamente la nueva dirección IP pública del servidor.
- Integración con HestiaCP: Obtiene la lista de usuarios y sus dominios web directamente desde HestiaCP.
- Actualización de Cloudflare DNS: Modifica los registros DNS (A) en Cloudflare para que apunten a la nueva IP.
- Soporta la exclusión de dominios específicos.
- Maneja la obtención dinámica del ID de Zona si no se especifica uno global.
- Sincronización de IP en HestiaCP: Ejecuta el comando
/usr/local/hestia/bin/v-update-sys-ip
para informar a HestiaCP sobre el cambio de IP. - Logging Detallado: Registra todas las operaciones importantes y errores en
syslog
para facilitar el seguimiento y la depuración.
- Servidor con HestiaCP (probado en Debian 12).
- Python 3.x.
- Conexión a Internet para consultar servicios de IP y la API de Cloudflare.
- Cuenta de Cloudflare gestionando los DNS de los dominios alojados en HestiaCP.
La aplicación se configura mediante variables de entorno, gestionadas a través de un archivo .env
.
Nota importante sobre la ubicación de
.env
:
- En desarrollo, el archivo
.env
se busca primero junto al código fuente.- En producción, si no se encuentra el archivo
.env
local, la aplicación intentará cargar automáticamente/etc/hestia-pppoe/.env
como último recurso.- Esto permite mantener una configuración centralizada y segura para entornos productivos.
- Crear archivo
.env
: Copie el archivo de ejemplo.env.example
a.env
en la raíz del proyecto:cp .env.example .env
- Editar
.env
: Modifique las siguientes variables según su configuración:CLOUDFLARE_API_TOKEN
: TOKEN de API de Cloudflare. Obtenga uno en https://dash.cloudflare.com/profile/api-tokensCLOUDFLARE_API_BASE_URL
: URL base de la API de Cloudflare (valor predeterminado:https://api.cloudflare.com/client/v4
)CLOUDFLARE_ZONE_ID
: ID de Zona de Cloudflare (opcional, si no se especifica, se obtendrá dinámicamente)V_LIST_USERS_PATH
: Ruta al comando de HestiaCP para obtener la lista de usuarios (valor predeterminado:/usr/local/hestia/bin/v-list-users
)V_LIST_WEB_DOMAINS_PATH
: Ruta al comando de HestiaCP para obtener la lista de dominios web de un usuario (valor predeterminado:/usr/local/hestia/bin/v-list-web-domains
)V_UPDATE_SYS_IP_PATH
: Ruta al comando de HestiaCP para actualizar la IP del sistema (valor predeterminado:/usr/local/hestia/bin/v-update-sys-ip
)CLOUDFLARE_EXCLUDED_DOMAINS
: Dominios excluidos de la actualización de Cloudflare DNS (valor predeterminado: lista vacía)
El script está diseñado para ser empaquetado como un único binario ejecutable para Linux usando shiv
.
-
Instalar dependencias de compilación (en su máquina de desarrollo o en un entorno Debian 12):
pip install shiv
-
Generar el binario: Ejecute el script de compilación proporcionado:
# Asegúrese de que el script tenga permisos de ejecución chmod +x scripts/build.sh bash scripts/build.sh
./hestia-pppoe/scripts/build.sh [opciones]
Opciones principales:
-i
,--include-env
Incluye el archivo.env
dentro del binario generado.-n
,--no-env
No incluye ni copia ningún archivo.env
(deberá gestionar las variables de entorno por otros medios).- (sin opciones) Copia el archivo
.env
externo junto al binario en la carpeta de salida.
Ejemplos de uso:
- Empaquetar incluyendo
.env
en el binario:./hestia-pppoe/scripts/build.sh --include-env
- Empaquetar sin ningún
.env
(solo variables externas):./hestia-pppoe/scripts/build.sh --no-env
- Empaquetar con
.env
externo (por defecto):./hestia-pppoe/scripts/build.sh
El binario generado (ej. hestia_updater
) debe ser copiado al servidor HestiaCP.
Para automatizar su ejecución tras un cambio de IP (por ejemplo, al establecer una conexión PPPoE), se puede enlazar en el directorio /etc/ppp/ip-up.d/
.
- Copiar el binario al servidor:
sudo cp dist/linux/hestia_updater /usr/local/bin/hestia_updater sudo chmod +x /usr/local/bin/hestia_updater
Nota sobre .env
en producción: Cuando se ejecuta desde /etc/ppp/ip-up.d/
, el script podría no encontrar el archivo .env
si no se especifica la ruta correcta o si el directorio de trabajo no es la raíz del proyecto. Considere:
- Colocar el archivo .env
en una ubicación accesible y conocida.
- Modificar el script hestia_updater
para buscar .env
en una ruta absoluta o relativa a la ubicación del script.
- O, preferiblemente para producción, gestionar las variables de entorno a través del entorno de ejecución del script ip-up.d
o mediante un archivo de configuración de systemd si se gestiona como un servicio.
Las dependencias de Python se listan en requirements.txt
. Las principales son:
python-dotenv
: Para cargar la configuración desde el archivo.env
.requests
: Para realizar solicitudes HTTP a los servicios de IP y a la API de Cloudflare.shiv
: Para el empaquetado (dependencia de desarrollo/compilación).
Instalar dependencias para desarrollo:
pip install -r requirements.txt
Esta sección proporciona detalles técnicos sobre las interacciones con HestiaCP y la API de Cloudflare que pueden ser útiles para el desarrollo, la depuración o la comprensión profunda del funcionamiento de la aplicación.
La aplicación interactúa con los siguientes comandos de la CLI de HestiaCP. Se asume que estos comandos están disponibles en el PATH
del sistema donde se ejecuta el script y que el script tiene los permisos necesarios para ejecutarlos (generalmente se ejecuta como root
cuando es invocado por /etc/ppp/ip-up.d/
).
-
v-list-users json
- Propósito: Obtener una lista de todos los usuarios gestionados por HestiaCP.
- Uso: Se ejecuta como
v-list-users json
. - Salida Esperada (JSON): Un objeto JSON donde cada clave es un nombre de usuario y el valor es un objeto con detalles del usuario. La aplicación solo utiliza las claves (nombres de usuario).
{ "admin": { ... detalles ... }, "user1": { ... detalles ... } }
-
v-list-web-domains <username> json
- Propósito: Obtener una lista de todos los dominios web asociados a un usuario específico.
- Uso: Se ejecuta como
v-list-web-domains <nombre_de_usuario> json
. - Salida Esperada (JSON): Un objeto JSON donde cada clave es un nombre de dominio y el valor es un objeto con detalles del dominio. La aplicación solo utiliza las claves (nombres de dominio).
{ "domain1.com": { ... detalles ... }, "sub.domain2.com": { ... detalles ... } }
-
v-update-sys-ip
- Propósito: Informar a HestiaCP sobre un cambio en la dirección IP principal del sistema. Este comando actualiza internamente las configuraciones de red de HestiaCP y los servicios que gestiona (DNS local, Apache, Nginx, etc.).
- Uso: Se ejecuta como
v-update-sys-ip
. - Salida Esperada: Este comando no produce salida. La aplicación verifica el código de retorno del proceso: un código
0
indica éxito, cualquier otro valor indica un error.
La aplicación utiliza la API v4 de Cloudflare para gestionar los registros DNS. Se enfoca exclusivamente en registros de tipo A
(IPv4).
- Autenticación: Se utiliza un Token de API de Bearer (
CLOUDFLARE_API_TOKEN
) con permisos para leer información de la zona y leer/editar registros DNS. - Base URL:
https://api.cloudflare.com/client/v4
Endpoints Principales Utilizados:
-
GET /zones
- Propósito: Obtener el
zone_id
para un nombre de dominio si no se ha proporcionado uno globalmente (CLOUDFLARE_ZONE_ID
). - Parámetros Clave:
name=<domain_name>
,status=active
. - Respuesta Exitosa Esperada (JSON): Un objeto con
"success": true
y un array"result"
que contiene objetos de zona. Se utiliza elid
de la primera zona devuelta.{ "result": [ { "id": "CLOUDFLARE_ZONE_ID_EXAMPLE", "name": "example.com", ... } ], "success": true, "errors": [], "messages": [] }
- Propósito: Obtener el
-
GET /zones/{zone_id}/dns_records
- Propósito: Listar los registros DNS existentes de tipo
A
para un nombre de dominio específico dentro de una zona. - Parámetros Clave:
name=<full_domain_name>
,type=A
. - Respuesta Exitosa Esperada (JSON): Objeto con
"success": true
y"result"
siendo un array de objetos de registro DNS.Si no existen registros,{ "result": [ { "id": "CLOUDFLARE_RECORD_ID_EXAMPLE", "type": "A", "name": "example.com", "content": "192.0.2.1", ... } ], "success": true, ... }
"result"
será un array vacío.
- Propósito: Listar los registros DNS existentes de tipo
-
PUT /zones/{zone_id}/dns_records/{record_id}
- Propósito: Actualizar un registro DNS existente (tipo
A
). - Payload (JSON): Contiene
type
,name
,content
(la nueva IP),ttl
.{ "type": "A", "name": "example.com", "content": "198.51.100.5", "ttl": 120 }
- Respuesta Exitosa Esperada (JSON): Objeto con
"success": true
y"result"
con el detalle del registro actualizado.
- Propósito: Actualizar un registro DNS existente (tipo
-
POST /zones/{zone_id}/dns_records
- Propósito: Crear un nuevo registro DNS (tipo
A
). - Payload (JSON): Similar al de
PUT
. - Respuesta Exitosa Esperada (JSON): Objeto con
"success": true
y"result"
con el detalle del registro creado.
- Propósito: Crear un nuevo registro DNS (tipo
Manejo de Errores de la API de Cloudflare:
- La aplicación verifica la clave
"success"
en la respuesta JSON. Si esfalse
, se considera un error. - Los detalles del error se extraen del array
"errors"
en la respuesta, que típicamente contiene objetos concode
ymessage
. - También se manejan excepciones de red (
requests.exceptions.RequestException
) y errores de decodificación JSON.