01 fuente unica
Principio¶
La infraestructura y la configuración de SmallCountry se definen como código:
se escriben en code-server, se versionan en Forgejo, se planifican con OpenTofu, se despliegan mediante Forgejo Actions y se aplican declarativamente con Ansible usando roles idempotentes.
Cualquier cambio que no recorra este flujo completo es una divergencia que detiene el sistema y exige reconciliación humana.
Ciclo de vida de un cambio¶
-
**Escritura en code-server
Desde el entorno de desarrollo accesible por navegador se editan simultáneamente los módulos de OpenTofu, los roles de Ansible, la documentación y los prompts de IA. Es el único punto de entrada para cualquier modificación del sistema. -
**Versionado en Forgejo
Todo el código se aloja en el repositorio central, que actúa como fuente de verdad, registro OCI de imágenes y motor de CI/CD (integración y despliegue continuo).
El flujo de trabajo es:feature-branch → Pull Request → revisión humana → merge a main. -
**Planificación con OpenTofu
Cada Pull Request ejecutatofu plan. El resultado se compara con el estado real de Proxmox VE a través de su API (interfaz de programación).
Si existe deriva —cambios ejecutados fuera de Git— el flujo se detiene, se genera un commit forense en una ramaquarantiney se notifica al administrador. Este mecanismo garantiza que la deriva nunca quede sin auditar. -
**Aplicación declarativa con Ansible
Tras la creación o actualización de los LXC (contenedor ligero de Proxmox) por OpenTofu, Ansible entra en juego aplicando roles declarativos. Cada rol describe el estado final deseado (paquetes instalados, ficheros de configuración, contenedores Docker activos, certificados TLS (cifrado de comunicaciones) presentes) sin preocuparse del estado actual.
La idempotencia está verificada: ejecutar el mismo rol cien veces produce exactamente el mismo resultado seguro que ejecutarlo una sola vez. -
Consolidación
Al finalizar el despliegue, el estado real del sistema coincide exactamente con el declarado en Forgejo. Cualquier intervención manual futura que se salte este flujo será detectada como deriva y forzará una reconciliación documentada.
graph TD
subgraph Escritura [Escritura]
direction LR
A[code-server] --> B[Módulos OpenTofu / Roles Ansible / Documentación]
end
subgraph Versionado [Versionado]
direction LR
C[Forgejo] --> D[Pull Request]
D --> E[Revisión humana]
E --> F[Merge a main]
end
subgraph Planificacion [Planificación]
direction LR
G[Forgejo Actions] --> H[tofu plan]
H --> I[Detección de drift]
I --> J[¿Divergencia?]
J -->|Sí| K[Commit forense + notificación]
J -->|No| L[tofu apply]
end
subgraph Aplicacion [Aplicación declarativa]
direction LR
M[OpenTofu] --> N[Creación / actualización de LXCs]
N --> O[Ansible Semaphore]
O --> P[Roles declarativos idempotentes]
end
subgraph Consolidacion [Consolidación]
direction LR
Q[Estado real = Estado declarado] --> R[ZFS snapshot]
end
Escritura --> Versionado
Versionado --> Planificacion
Planificacion --> Aplicacion
Aplicacion --> Consolidacion
style Escritura fill:#f9a8d4,stroke:#c2185b,color:#000
style Versionado fill:#f48fb1,stroke:#c2185b,color:#000
style Planificacion fill:#90caf9,stroke:#1565c0,color:#000
style Aplicacion fill:#a5d6a7,stroke:#2e7d32,color:#000
style Consolidacion fill:#ffe082,stroke:#f57f17,color:#000
Ansible como motor declarativo¶
En SmallCountry, Ansible no se usa como un simple ejecutor de comandos, sino como garante del estado deseado. Cada servicio tiene su propio rol, estructurado según las mejores prácticas:
| Archivo / Carpeta | Propósito |
|---|---|
roles/authentik/tasks/main.yml |
Tareas declarativas: instalar paquetes, crear volúmenes, desplegar docker-compose |
roles/authentik/handlers/main.yml |
Acciones reactivas: reiniciar el servicio si cambia la configuración |
roles/authentik/templates/ |
Plantillas de configuración (authentik.conf.j2, docker-compose.yml.j2) |
roles/authentik/vars/main.yml |
Variables específicas del rol (versión de la imagen, puertos, secretos referenciados desde Vault) |
roles/authentik/meta/main.yml |
Dependencias: requiere que el rol docker esté aplicado primero |
| ### Propiedades clave |
| Propiedad | Descripción |
|---|---|
| Declaratividad estricta | Las tareas describen el estado final deseado, no los pasos para alcanzarlo. |
| Idempotencia real | Se emplean condiciones como creates, when o changed_when para que Ansible decida si debe actuar o si el estado ya es correcto, evitando reinicios innecesarios. |
| Roles atómicos y desacoplados | El rol authentik no sabe en qué red ni en qué LXC se ejecuta; esa información se la proporciona OpenTofu. Así se puede reutilizar el mismo rol en distintos entornos sin modificarlo. |
| Secretos como código | Las variables sensibles (contraseñas, tokens OIDC (protocolo de autenticación OpenID Connect), claves API) se generan, se cifran con Ansible Vault y se versionan en Forgejo. En el momento del despliegue se inyectan sin que nunca existan en texto plano en producción. |
| Separación de responsabilidades | OpenTofu crea y dimensiona el LXC (recursos, red, almacenamiento); Ansible lo provisiona (Docker, configuración, certificados). No se mezclan responsabilidades. |
Stack necesario¶
- code-server – Entorno de desarrollo desde navegador.
- Forgejo – Repositorio Git, CI/CD y registro OCI.
- OpenTofu – Infraestructura como código (módulos declarativos).
- Forgejo Actions – Pipelines de planificación y despliegue.
- Ansible + Semaphore – Configuración declarativa con roles.
- Ansible Vault – Cifrado de secretos.
- Script de detección de drift – Compara plan de OpenTofu con estado real de Proxmox VE.
- ZFS – Snapshots pre‑cambio para rollback instantáneo.
Relaciones con otros principios¶
- 2. Reconstruibilidad total desde cero: el repositorio central contiene todos los módulos y roles necesarios para regenerar el sistema desde un Proxmox limpio.
- 8. Observabilidad integral desde el origen: la configuración de los agentes de observabilidad se despliega con roles de Ansible versionados, asegurando que cada servicio nazca instrumentado.
- 11. Contención de recursos y degradación planificada: los límites de RAM/CPU de cada LXC están definidos en código OpenTofu y versionados aquí.
- 12. Conocimiento compartido y autonomía de las personas usuarias: la documentación (
docs.sc) se escribe en code-server, se versiona en Forgejo junto al código y se publica con MkDocs.
Flujo de remediación automática¶
Cuando el sistema detecta una degradación —un servicio caído, un recurso al límite, una métrica fuera de SLO (objetivo de nivel de servicio)— se activa una cadena de corrección que atraviesa todas las capas del ecosistema:
- SkyEye detecta — una alerta de Prometheus, un healthcheck fallido de Uptime Kuma, o una anomalía detectada por los agentes nocturnos de IA
- n8n interpreta — recibe el evento, consulta el runbook correspondiente y decide la acción (reiniciar servicio, escalar recurso, notificar)
- Semaphore ejecuta — lanza el playbook de Ansible apropiado de forma controlada y registrada
- Ansible converge — aplica el estado deseado de forma idempotente, devolviendo el sistema a su condición normal
Todo este flujo deja trazabilidad completa en Forgejo. Si en algún punto se requiere intervención humana, el sistema notifica y espera. La automatización acelera, pero nunca sustituye el criterio cuando la situación lo exige.
← Mecanismo 10: Perfiles de Energía | Principio 2: Reconstruibilidad total →