Avances – Joseanía

Diario de proyecto – Joseanía | Zitadel Inmobiliaria

Infraestructura, automatización y backend

Periodo: 02 mar → 25 abr 2026

Entrada 01
02 – 10 Mar 2026 Fase 1 · Planificación y análisis

Definición del proyecto

Arrancamos con una fase de planificación conjunta. La idea es diseñar e implantar la infraestructura tecnológica completa de una inmobiliaria ficticia llamada Zitadel Inmobiliaria. En esta semana inicial definimos los objetivos del proyecto, repartimos las áreas de trabajo y trazamos la arquitectura general que guiaría todo el desarrollo.

Entrada 02
11 – 20 Mar 2026 Fase 2 · Diseño de arquitectura

Diseñando la infraestructura: VMs, redes y almacenamiento

Mientras Iria diseña la arquitectura de red y las VLANs, yo me centro en diseñar la capa de infraestructura: qué máquinas virtuales necesitamos y qué recursos tendrá cada una.

VMs definidas para el proyecto

Definimos el mapa completo de máquinas virtuales que componen Zitadel:

VM IDNombreFunciónIP
200Central-NodeNodo de gestión, Terraform, Ansible10.0.10.200
201FirewallOPNsense (gestión de red)
202ZabbixMonitorización10.0.20.202
203WordPressPortal web + Docker10.0.30.203
204MariaDBBase de datos10.0.40.204
205TeampassGestor de credenciales
206TraefikProxy inverso + SSL
207BastionAcceso SSH controlado
Proxmox VE Git Arquitectura
Decisión de diseño: Separar MariaDB en su propia VM dentro de la VLAN de base de datos (10.0.40.204) es fundamental para la seguridad: solo el servidor WordPress podrá conectarse a ella, y únicamente por el puerto específico de MySQL.
Entrada 03
21 – 30 Mar 2026 Fase 3 · Hardware y virtualización

Despliegue de VMs con Terraform: infraestructura como código

Con Proxmox ya instalado y configurado por Iria, llega el momento de automatizar el aprovisionamiento de todas las máquinas virtuales con Terraform. El objetivo es que cualquier VM pueda recrearse desde cero ejecutando un solo comando.

Proveedor utilizado: bpg/proxmox

El proveedor bpg/proxmox permite comunicarse con la API de Proxmox directamente desde Terraform. Las credenciales nunca van en texto plano: la contraseña se pasa como variable de entorno marcada como sensible.

# variables.tf — gestión segura de credenciales
variable "pm_password" {
  description = "Password de acceso a la API de Proxmox"
  sensitive   = true
}

# main.tf — proveedor y ejemplo de creación de VM Central-Node
terraform {
  required_providers {
    proxmox = {
      source  = "bpg/proxmox"
      version = "0.46.4"
    }
  }
}

provider "proxmox" {
  endpoint = "https://192.168.1.220:8006/"
  username = "root@pam"
  password = var.pm_password
  insecure = true
}

resource "proxmox_virtual_environment_vm" "central_node" {
  name      = "Central-Node"
  node_name = "pve"
  vm_id     = 200
  # ... resto de configuración
}
Lección aprendida: Siempre marcar las variables con contraseñas como sensitive = true en Terraform. De lo contrario, aparecen en texto plano en los logs de terraform plan y terraform apply, lo que es un riesgo de seguridad grave.
Entrada 04
08 – 15 Abr 2026 Fase 5 · Base de datos

Base de datos con MariaDB: diseño e implementación

Una vez la red está operativa, llega el momento de desplegar la base de datos. El motor elegido es MariaDB, una solución de código abierto derivada de MySQL, muy estable y perfectamente compatible con WordPress. MariaDB vive en la VM 204, dentro de la VLAN de base de datos (10.0.40.204), la zona más protegida de toda la red.

¿Por qué MariaDB en su propia VM?

Aislar la base de datos en su propia máquina virtual tiene varias ventajas clave: si el servidor web es comprometido, el atacante no tiene acceso directo a los datos; los recursos de CPU y RAM se asignan de forma independiente; y los backups de la VM se pueden hacer sin afectar a otros servicios.

Usuario de aplicación con mínimos privilegios

No se usa el usuario root desde WordPress. Creamos un usuario específico con solo los permisos necesarios sobre la base de datos del proyecto:

-- Usuario de aplicación (principio de mínimo privilegio)
CREATE USER 'wp_user'@'10.0.30.%' IDENTIFIED BY 'contraseña_segura';
GRANT SELECT, INSERT, UPDATE, DELETE ON zitadel.* TO 'wp_user'@'10.0.30.%';
FLUSH PRIVILEGES;

Conexión con WordPress

La base de datos de WordPress se configuró mediante variables de entorno en Docker Compose, evitando que las credenciales aparezcan en texto plano en el código fuente. La conexión entre contenedores se realiza por la red interna de Docker.

MariaDB SQL Seguridad BD
Entrada 05
12 – 22 Abr 2026 Fase 6 · Despliegue web

WordPress en Docker: backend, contenedores y variables de entorno

El despliegue web es una de las partes fundamentales del proyecto, ya que es cuando finalmente se prueba que todo funciona correctamente. Aunque Iria se encarga del frontend (tema, contenidos y ajustes visuales de WordPress), yo me encargo del backend técnico: preparar la VM, desplegar el stack de contenedores y asegurar que WordPress conecta correctamente con la base de datos.

Arquitectura del stack

El sistema web se divide en dos contenedores que se comunican por una red interna de Docker:

  • Contenedor WordPress: basado en wordpress:apache, sirve la web con Apache + PHP 8.2.
  • Contenedor MariaDB: basado en mariadb:10.11, almacena todos los datos de WordPress.

Los datos persisten mediante volúmenes Docker: ./wp-data para los archivos de WordPress (temas, uploads) y ./db-data para los datos de la base de datos. Así, aunque se destruyan los contenedores, los datos no se pierden.

docker-compose.yml

services:
 
  db:
    image: mariadb:10.11
    container_name: wp_db
    restart: always
    command: --skip-name-resolve        # evita resolución DNS inversa → más rápido
    environment:
      MYSQL_DATABASE:      wordpress
      MYSQL_USER:          wpuser
      MYSQL_PASSWORD:      wppass
      MYSQL_ROOT_PASSWORD: rootpass
    volumes:
      - ./db-data:/var/lib/mysql
      - ./backup.sql:/docker-entrypoint-initdb.d/backup.sql  # importa BD al arrancar
 
  wordpress:
    image: wordpress:php8.2-apache
    container_name: wp_web
    restart: always
    ports:
      - "80:80"
      - "443:443"
    extra_hosts:
      - "zitadel.a24iriabc.iesteis.gal:127.0.0.1"   # resolución local del dominio
    environment:
      WORDPRESS_DB_HOST:     db
      WORDPRESS_DB_USER:     wpuser
      WORDPRESS_DB_PASSWORD: wppass
      WORDPRESS_DB_NAME:     wordpress
      WORDPRESS_CONFIG_EXTRA: |
        define('FS_METHOD',         'direct');
        define('WP_MEMORY_LIMIT',     '512M');
        define('WP_MAX_MEMORY_LIMIT', '512M');
        define('DISABLE_WP_CRON',      true);
        define('WP_HOME',    'https://zitadel.a24iriabc.iesteis.gal');
        define('WP_SITEURL', 'https://zitadel.a24iriabc.iesteis.gal');
 
        /* $$ evita que Docker interprete $ como variable de entorno */
        if (isset($$_SERVER['HTTP_X_FORWARDED_PROTO'])
            && $$_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
            $$_SERVER['HTTPS'] = 'on';
        }
    volumes:
      - ./wp-data:/var/www/html
      - ./apache2/000-default-ssl.conf:/etc/apache2/sites-available/000-default-ssl.conf
      - ./apache2/certs:/etc/apache2/ssl
    depends_on:
      - db
    command: >
      bash -c "
        a2enmod ssl rewrite headers &&
        a2ensite 000-default-ssl &&
        chown -R www-data:www-data /var/www/html &&
        docker-entrypoint.sh apache2-foreground
      "

Adaptación para proxy inverso (Traefik + HTTPS)

Como el tráfico llega a WordPress a través de Traefik (proxy inverso con SSL), fue necesario añadir la variable $_SERVER['HTTPS'] = 'on' para que WordPress entienda que está sirviendo bajo HTTPS, aunque el contenedor reciba la petición en HTTP por la red interna. Sin esto, WordPress generaba bucles de redirección o rompía los recursos CSS/JS.

Docker Docker Compose WordPress MariaDB Variables de entorno
Entrada 06
15 – 30 Abr 2026 Fase 7 · Automatización

Ansible: automatizando la configuración de toda la infraestructura

Con Terraform ya se crean las VMs. Ahora toca Ansible para configurarlas: instalar paquetes, copiar archivos de configuración y levantar servicios.

Inventario (inventory.ini)

El inventario define los grupos de hosts y las variables de conexión. Ansible entra en las máquinas usando las llaves SSH que Terraform inyectó al crear las VMs:

[all:vars]
ansible_user                 = admin
ansible_ssh_private_key_file = ~/.ssh/id_rsa

[zabbix]
zabbix    ansible_host=10.0.20.202

[wordpress]
wordpress ansible_host=10.0.30.203

[mariadb]
mariadb   ansible_host=10.0.40.204

playbook.yml — estructura general

El playbook está dividido en cinco bloques:

#BloqueHostsQué hace
1PreparaciónlocalhostClona el repositorio de GitHub y asegura que rsync está disponible
2DockerallInstala Docker Engine + Compose plugin en todas las VMs
3MariaDBmariadbDespliega dos bases de datos: WordPress y Zabbix
4WordPresswordpressSincroniza el repo, genera el compose e inicia el contenedor web
5ZabbixzabbixDespliega server, frontend web y agente de Zabbix
Ansible Docker Compose MariaDB WordPress Zabbix rsync IaC
Flujo completo de despliegue: terraform apply crea las VMs → ansible-playbook playbook.yml clona el repo, instala Docker en todas las máquinas, levanta MariaDB con los datos importados, despliega WordPress contra la BD remota y deja Zabbix completamente operativo. Todo desde un solo comando.
Entrada 07
A lo largo del proyecto Transversal · Gestión del repositorio

Control de versiones: cómo hemos gestionado el repositorio del proyecto

La gestión del repositorio es una tarea que cruza todo el proyecto. Como responsable del control de versiones, me encargué de establecer el flujo de trabajo en Git y mantener el repositorio organizado y operativo.

Estructura actual del repositorio

iac-deployment-lab/
├── terraform/
│   ├── main.tf                # Proveedor Proxmox y definición de VMs
│   ├── variables.tf           # Variables (contraseñas marcadas como sensitive)
│   └── modules/
│       └── vm/
│           ├── main.tf
│           └── variables.tf
├── ansible/
│   ├── inventory.ini          # Inventario de hosts por VLAN
│   └── playbook.yml           # Configuración de los servidores
└── wordpress-docker-proyecto/ # Submódulo: stack web dockerizado
    └── docker-compose.yml
    ...
Git Control de versiones Buenas prácticas