543 lines
24 KiB
Markdown
543 lines
24 KiB
Markdown
|
|
# Decision: Capa de automatizacion (punto 3)
|
||
|
|
|
||
|
|
## Contexto
|
||
|
|
|
||
|
|
Actualmente la operativa del PBS se gestiona con scripts bash en `/root/` (`modificar.sh`, `lista.sh`, `gc_jobs.sh`, `verify_jobs.sh`, `status_disk.sh`, etc.). Existe una clave SSH de `david@ansible` pero Ansible se ha usado muy poco (algun apt upgrade en batch). No hay experiencia real con playbooks ni roles. A 100-500 servidores, la forma actual no escala: scripts no versionados, sin idempotencia, sin audit trail, si el servidor se pierde se pierde toda la operativa.
|
||
|
|
|
||
|
|
Se desplegara un servidor nuevo desde cero donde se migraran VMs progresivamente. Ya existe un Forgejo con proyectos de desarrollo (solo git basico).
|
||
|
|
|
||
|
|
3 subcapas (Terraform/OpenTofu descartado):
|
||
|
|
- 3.1 Gestion de configuracion (Ansible + Semaphore)
|
||
|
|
- 3.2 Control de versiones y CI/CD (Forgejo existente + Actions)
|
||
|
|
- 3.3 Orquestacion de jobs (Semaphore + n8n futuro)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 3.1 Gestion de configuracion: Ansible
|
||
|
|
|
||
|
|
### Por que Ansible y no otras
|
||
|
|
|
||
|
|
| Herramienta | Modelo | Agente | Estado |
|
||
|
|
|-------------|--------|--------|--------|
|
||
|
|
| **Ansible** | Push (sin agente) | Solo SSH | Estandar de facto para infra Linux |
|
||
|
|
| **Puppet** | Pull (con agente) | Si (puppet-agent, ~200MB RAM) | En declive, comunidad menguante |
|
||
|
|
| **Chef** | Pull (con agente) | Si (chef-client) | Comprado por Progress, futuro incierto |
|
||
|
|
| **Salt** | Push/Pull | Opcional (salt-minion) | Bueno pero menor ecosistema |
|
||
|
|
|
||
|
|
**Ansible gana por**:
|
||
|
|
- Ya se usa en el entorno (clave SSH de `david@ansible`)
|
||
|
|
- Sin agente: solo necesita SSH, que ya esta configurado en todos los servidores
|
||
|
|
- Inventario dinamico desde Netbox (ya decidido en 1.1)
|
||
|
|
- Enorme ecosistema de colecciones para Proxmox (`community.general.proxmox*`)
|
||
|
|
- Curva de aprendizaje accesible para sysadmins (YAML, no Ruby ni DSL propios)
|
||
|
|
- Compatible con todo lo decidido: Wazuh, VictoriaMetrics, Loki, CrowdSec, Fail2ban
|
||
|
|
|
||
|
|
### De modificar.sh a Ansible: la transformacion
|
||
|
|
|
||
|
|
El script `modificar.sh` actual hace en secuencia:
|
||
|
|
1. Crear dataset ZFS con quota y reservation (multiplicador 6x)
|
||
|
|
2. Crear datastore en PBS
|
||
|
|
3. Crear usuario PBS
|
||
|
|
4. Setear password
|
||
|
|
5. Configurar ACL (DatastorePowerUser)
|
||
|
|
6. Crear sync job (dia aleatorio 11-20, 09:XX)
|
||
|
|
7. Crear verify job (outdated 30d, ignore-verified)
|
||
|
|
8. Opcionalmente eliminar sync job si "migrado"
|
||
|
|
|
||
|
|
Esto se transforma en un **role de Ansible** (`pbs_customer`) con tasks idempotentes:
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
# roles/pbs_customer/tasks/main.yml
|
||
|
|
---
|
||
|
|
- name: Crear dataset ZFS
|
||
|
|
community.general.zfs:
|
||
|
|
name: "pool9/{{ customer_name }}"
|
||
|
|
state: present
|
||
|
|
extra_zfs_properties:
|
||
|
|
quota: "{{ customer_size_gb * 6 }}G"
|
||
|
|
reservation: "{{ customer_size_gb * 5 }}G"
|
||
|
|
recordsize: "1M"
|
||
|
|
compression: "lz4"
|
||
|
|
atime: "off"
|
||
|
|
|
||
|
|
- name: Crear datastore PBS
|
||
|
|
ansible.builtin.uri:
|
||
|
|
url: "https://localhost:8007/api2/json/config/datastore"
|
||
|
|
method: POST
|
||
|
|
headers:
|
||
|
|
Authorization: "PBSAPIToken={{ pbs_api_token }}"
|
||
|
|
body_format: json
|
||
|
|
body:
|
||
|
|
name: "{{ customer_name }}"
|
||
|
|
path: "/pool9/{{ customer_name }}"
|
||
|
|
gc-schedule: "daily"
|
||
|
|
validate_certs: false
|
||
|
|
status_code: [200, 500] # 500 si ya existe
|
||
|
|
register: ds_result
|
||
|
|
|
||
|
|
- name: Crear usuario PBS
|
||
|
|
ansible.builtin.command:
|
||
|
|
cmd: >
|
||
|
|
proxmox-backup-manager user create
|
||
|
|
{{ customer_name }}@pbs
|
||
|
|
--comment "Cliente {{ customer_name }}"
|
||
|
|
register: user_result
|
||
|
|
failed_when: user_result.rc != 0 and 'already exists' not in user_result.stderr
|
||
|
|
|
||
|
|
- name: Setear password del usuario
|
||
|
|
ansible.builtin.command:
|
||
|
|
cmd: >
|
||
|
|
proxmox-backup-debug api set /access/password
|
||
|
|
--userid {{ customer_name }}@pbs
|
||
|
|
--password {{ customer_password }}
|
||
|
|
no_log: true # No mostrar password en logs
|
||
|
|
|
||
|
|
- name: Configurar ACL
|
||
|
|
ansible.builtin.command:
|
||
|
|
cmd: >
|
||
|
|
proxmox-backup-manager acl update
|
||
|
|
/datastore/{{ customer_name }}
|
||
|
|
DatastorePowerUser
|
||
|
|
--auth-id {{ customer_name }}@pbs
|
||
|
|
|
||
|
|
- name: Crear sync job
|
||
|
|
ansible.builtin.command:
|
||
|
|
cmd: >
|
||
|
|
proxmox-backup-manager sync-job create
|
||
|
|
{{ customer_name }}
|
||
|
|
--store {{ customer_name }}
|
||
|
|
--remote {{ sync_remote }}
|
||
|
|
--remote-store {{ customer_name }}
|
||
|
|
--schedule "*-{{ sync_day }} 09:{{ sync_minute }}"
|
||
|
|
--remove-vanished true
|
||
|
|
when: sync_server is defined and not sync_server.startswith('migrado')
|
||
|
|
register: sync_result
|
||
|
|
failed_when: sync_result.rc != 0 and 'already exists' not in sync_result.stderr
|
||
|
|
|
||
|
|
- name: Crear verify job
|
||
|
|
ansible.builtin.command:
|
||
|
|
cmd: >
|
||
|
|
proxmox-backup-manager verify-job create
|
||
|
|
v-{{ customer_name }}
|
||
|
|
--store {{ customer_name }}
|
||
|
|
--outdated-after 30
|
||
|
|
--ignore-verified true
|
||
|
|
register: verify_result
|
||
|
|
failed_when: verify_result.rc != 0 and 'already exists' not in verify_result.stderr
|
||
|
|
```
|
||
|
|
|
||
|
|
Variables desde Netbox (inventario dinamico):
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
# host_vars o custom fields de Netbox
|
||
|
|
customer_name: "acme"
|
||
|
|
customer_size_gb: 100
|
||
|
|
customer_password: "{{ lookup('hashi_vault', 'secret/pbs/acme') }}" # Fase 2
|
||
|
|
sync_server: "pbs3343.vpn9.com.es"
|
||
|
|
sync_day: 15
|
||
|
|
sync_minute: 37
|
||
|
|
```
|
||
|
|
|
||
|
|
### Playbooks base (Dia 1)
|
||
|
|
|
||
|
|
| Playbook | Que hace | Prioridad |
|
||
|
|
|----------|----------|-----------|
|
||
|
|
| `hardening-ssh.yml` | SSH hardening completo + cloud-init fix + Fail2ban | **Dia 1** |
|
||
|
|
| `deploy-wazuh-agent.yml` | Instalar y registrar agente Wazuh | **Dia 1** |
|
||
|
|
| `deploy-node-exporter.yml` | node_exporter + Alloy para logs | Semana 1 |
|
||
|
|
| `deploy-auditd.yml` | Reglas auditd para PBS/Proxmox | Semana 1 |
|
||
|
|
| `deploy-crowdsec.yml` | CrowdSec con collections SSH + Linux | Semana 2 |
|
||
|
|
| `pbs-customer.yml` | Provisionar/modificar cliente PBS | Semana 2 |
|
||
|
|
| `pbs-maintenance.yml` | GC, verify, optimizar ZFS en batch | Mes 1 |
|
||
|
|
| `lynis-audit.yml` | Ejecutar Lynis y recoger informes | Mes 1 |
|
||
|
|
|
||
|
|
### Ansible UI: Semaphore vs AWX
|
||
|
|
|
||
|
|
| Aspecto | Semaphore | AWX |
|
||
|
|
|---------|-----------|-----|
|
||
|
|
| Recursos | 1 vCPU, 512MB RAM | 4 vCPU, 8GB RAM (Kubernetes) |
|
||
|
|
| Complejidad | Docker compose simple | Necesita K8s o docker-compose complejo |
|
||
|
|
| RBAC | Basico (admin/user) | Completo (orgs, teams, permisos por recurso) |
|
||
|
|
| Inventario dinamico | Via CLI plugin | Nativo con sync automatico |
|
||
|
|
| Scheduling | Si | Si (mas potente) |
|
||
|
|
| API | Basica | REST completa |
|
||
|
|
| Audit log | Si | Si (mas detallado) |
|
||
|
|
| Ideal para | Equipos de 2-5 personas | Equipos de 5-20+ personas |
|
||
|
|
|
||
|
|
**Recomendacion**: **Semaphore** para empezar. Si el equipo crece mas alla de 5 personas o necesitais RBAC granular, migrar a AWX.
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
# docker-compose.yml de Semaphore
|
||
|
|
services:
|
||
|
|
semaphore:
|
||
|
|
image: semaphoreui/semaphore:latest
|
||
|
|
ports:
|
||
|
|
- "3000:3000"
|
||
|
|
environment:
|
||
|
|
SEMAPHORE_DB_DIALECT: bolt
|
||
|
|
SEMAPHORE_ADMIN_PASSWORD: "${SEMAPHORE_ADMIN_PASSWORD}"
|
||
|
|
SEMAPHORE_ADMIN_NAME: admin
|
||
|
|
SEMAPHORE_ADMIN_EMAIL: admin@empresa.com
|
||
|
|
SEMAPHORE_ADMIN: admin
|
||
|
|
volumes:
|
||
|
|
- ./data:/var/lib/semaphore
|
||
|
|
- ./config:/etc/semaphore
|
||
|
|
```
|
||
|
|
|
||
|
|
### Inventario dinamico desde Netbox
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
# inventory/netbox.yml
|
||
|
|
plugin: netbox.netbox.nb_inventory
|
||
|
|
api_endpoint: https://netbox.empresa.local
|
||
|
|
token: "{{ lookup('env', 'NETBOX_TOKEN') }}"
|
||
|
|
validate_certs: false
|
||
|
|
|
||
|
|
# Agrupar por rol
|
||
|
|
group_by:
|
||
|
|
- device_roles
|
||
|
|
- platforms
|
||
|
|
- regions
|
||
|
|
- sites
|
||
|
|
- tenants
|
||
|
|
|
||
|
|
# Custom fields como variables de host
|
||
|
|
compose:
|
||
|
|
pbs_commercial_size_gb: custom_fields.pbs_commercial_size_gb
|
||
|
|
pbs_quota_gb: custom_fields.pbs_quota_gb
|
||
|
|
pbs_sync_server: custom_fields.pbs_sync_server
|
||
|
|
ansible_host: primary_ip4.address | split('/') | first
|
||
|
|
```
|
||
|
|
|
||
|
|
Flujo completo:
|
||
|
|
```
|
||
|
|
ICSManager → API → Netbox (crea device + custom fields)
|
||
|
|
↓
|
||
|
|
Ansible lee inventario
|
||
|
|
↓
|
||
|
|
Ejecuta playbook pbs-customer.yml
|
||
|
|
↓
|
||
|
|
PBS provisionado + monitorizado
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 3.2 Control de versiones y CI/CD
|
||
|
|
|
||
|
|
### El problema
|
||
|
|
|
||
|
|
Todos los scripts operativos (`modificar.sh`, `lista.sh`, `gc_jobs.sh`, `verify_jobs.sh`, `status_disk.sh`, `enable-maintenance.sh`, etc.) estan en `/root/` sin control de versiones. Si:
|
||
|
|
- El servidor se pierde → se pierde toda la operativa
|
||
|
|
- Un tecnico modifica un script y rompe algo → no hay rollback
|
||
|
|
- Dos tecnicos modifican el mismo script → conflictos sin resolver
|
||
|
|
- No hay registro de quien cambio que ni cuando
|
||
|
|
|
||
|
|
### DECISION: Forgejo existente (ya desplegado)
|
||
|
|
|
||
|
|
Ya tenemos un Forgejo en produccion con proyectos de desarrollo. No hay que desplegar nada nuevo, solo ampliar su uso a infraestructura.
|
||
|
|
|
||
|
|
Funcionalidades actuales en uso: solo git basico (push, pull, branches).
|
||
|
|
Funcionalidades a activar: Forgejo Actions (CI/CD), branch protection, repos de infraestructura.
|
||
|
|
|
||
|
|
### Estructura de repositorios
|
||
|
|
|
||
|
|
```
|
||
|
|
empresa/
|
||
|
|
├── ansible-playbooks/ # Todos los playbooks y roles
|
||
|
|
│ ├── roles/
|
||
|
|
│ │ ├── pbs_customer/
|
||
|
|
│ │ ├── hardening_ssh/
|
||
|
|
│ │ ├── deploy_wazuh/
|
||
|
|
│ │ ├── deploy_node_exporter/
|
||
|
|
│ │ ├── deploy_alloy/
|
||
|
|
│ │ ├── deploy_crowdsec/
|
||
|
|
│ │ └── deploy_auditd/
|
||
|
|
│ ├── playbooks/
|
||
|
|
│ │ ├── site.yml
|
||
|
|
│ │ ├── pbs-customer.yml
|
||
|
|
│ │ ├── hardening.yml
|
||
|
|
│ │ └── maintenance.yml
|
||
|
|
│ ├── inventory/
|
||
|
|
│ │ └── netbox.yml
|
||
|
|
│ └── .forgejo/workflows/
|
||
|
|
│ └── lint.yml # ansible-lint en cada push
|
||
|
|
│
|
||
|
|
├── pbs-scripts/ # Scripts operativos (migrados de /root)
|
||
|
|
│ ├── gc_jobs.sh
|
||
|
|
│ ├── verify_jobs.sh
|
||
|
|
│ ├── status_disk.sh
|
||
|
|
│ └── pbs-mantenimiento-secuencial.sh
|
||
|
|
│
|
||
|
|
├── monitoring-config/ # Configuracion de monitoring
|
||
|
|
│ ├── grafana/dashboards/
|
||
|
|
│ ├── victoriametrics/
|
||
|
|
│ ├── vmagent/
|
||
|
|
│ ├── alertmanager/
|
||
|
|
│ └── loki/
|
||
|
|
│
|
||
|
|
├── docker-stacks/ # Docker compose de servicios
|
||
|
|
│ ├── dns-powerdns/
|
||
|
|
│ ├── vaultwarden/
|
||
|
|
│ ├── semaphore/
|
||
|
|
│ └── uptime-kuma/
|
||
|
|
│
|
||
|
|
└── docs/ # Documentacion como codigo
|
||
|
|
├── runbooks/
|
||
|
|
├── architecture/
|
||
|
|
└── onboarding/
|
||
|
|
```
|
||
|
|
|
||
|
|
### CI/CD con Forgejo Actions
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
# .forgejo/workflows/ansible-lint.yml
|
||
|
|
name: Lint Ansible
|
||
|
|
on: [push, pull_request]
|
||
|
|
jobs:
|
||
|
|
lint:
|
||
|
|
runs-on: ubuntu-latest
|
||
|
|
steps:
|
||
|
|
- uses: actions/checkout@v4
|
||
|
|
- name: Run ansible-lint
|
||
|
|
uses: ansible/ansible-lint-action@v6
|
||
|
|
with:
|
||
|
|
path: "playbooks/"
|
||
|
|
```
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
# .forgejo/workflows/deploy-hardening.yml
|
||
|
|
name: Deploy Hardening
|
||
|
|
on:
|
||
|
|
push:
|
||
|
|
branches: [main]
|
||
|
|
paths: ['roles/hardening_ssh/**', 'playbooks/hardening.yml']
|
||
|
|
jobs:
|
||
|
|
deploy:
|
||
|
|
runs-on: self-hosted # Runner en la VM de automatizacion
|
||
|
|
steps:
|
||
|
|
- uses: actions/checkout@v4
|
||
|
|
- name: Run hardening playbook
|
||
|
|
run: |
|
||
|
|
ansible-playbook -i inventory/netbox.yml playbooks/hardening.yml --diff
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 3.3 Infraestructura como codigo: DESCARTADO
|
||
|
|
|
||
|
|
### Terraform / OpenTofu / Pulumi: no aplica
|
||
|
|
|
||
|
|
Descartados porque:
|
||
|
|
- Los servidores son fisicos dedicados con VMs que viven meses o años
|
||
|
|
- No hay infraestructura efimera (crear/destruir continuamente)
|
||
|
|
- No hay multi-cloud (todo es Proxmox on-premise)
|
||
|
|
- Ansible cubre el 100% de lo que se necesita: configurar lo que ya existe
|
||
|
|
|
||
|
|
Si algun dia se necesita crear 50 VMs identicas de golpe (nueva sede, nuevo cluster), se puede reevaluar. Para ahora, añadiria complejidad sin beneficio.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 3.4 Orquestacion de jobs
|
||
|
|
|
||
|
|
### El problema actual
|
||
|
|
|
||
|
|
Los cron jobs actuales:
|
||
|
|
```bash
|
||
|
|
*/15 * * * * /root/gc_jobs.sh >> /var/log/gc_jobs.log 2>&1
|
||
|
|
*/30 * * * * /root/verify_jobs.sh >> /var/log/verify_jobs.log 2>&1
|
||
|
|
```
|
||
|
|
|
||
|
|
Funcionan en un solo servidor. A 100+ PBS:
|
||
|
|
- No hay visibilidad de que jobs corren donde
|
||
|
|
- Si un job falla, nadie se entera (log en el servidor local)
|
||
|
|
- No hay forma de pausar/cancelar un job sin SSH al servidor
|
||
|
|
- No hay RBAC (quien puede ejecutar que)
|
||
|
|
- No hay dependencias entre jobs
|
||
|
|
|
||
|
|
**Caso real de congestion PBS**: los GC y verify jobs programados con el scheduling nativo de PBS provocaban picos de IO que congestionaban el servidor. Solucion actual: scripts "caseros" (`gc_jobs.sh`, `verify_jobs.sh`) que comprueban si hay otro proceso corriendo antes de lanzar uno nuevo, limitando la concurrencia manualmente.
|
||
|
|
|
||
|
|
### DECISION 3.4 (confirmada)
|
||
|
|
|
||
|
|
#### Semaphore como scheduler (reemplaza cron)
|
||
|
|
|
||
|
|
Si ya usamos Semaphore como UI de Ansible (decidido en 3.1), podemos usarlo tambien para scheduling de jobs:
|
||
|
|
|
||
|
|
- **GC jobs**: playbook que consulta API de PBS, comprueba si hay GC corriendo, si no lanza el mas antiguo. Cada 15min en Semaphore.
|
||
|
|
- **Verify jobs**: misma logica. Comprueba si hay verify activo, si no lanza el siguiente. Cada 30min.
|
||
|
|
- **Mantenimiento**: playbook de mantenimiento secuencial, ejecutable manualmente desde la UI
|
||
|
|
- **Hardening**: playbook de hardening, ejecutable con boton en la UI
|
||
|
|
|
||
|
|
La logica de control de concurrencia actual (no lanzar si ya hay uno corriendo) se traduce directamente:
|
||
|
|
1. **Dentro del playbook**: consulta API de PBS → si hay tarea activa, exit limpio
|
||
|
|
2. **En Semaphore**: opcion "no ejecutar si la ejecucion anterior no ha terminado"
|
||
|
|
3. Ambas combinadas = mismo comportamiento que los scripts actuales
|
||
|
|
|
||
|
|
Ventajas sobre cron:
|
||
|
|
- Visibilidad: ves en la UI que se ejecuto, cuando, y si fallo
|
||
|
|
- Notificaciones: si un GC o verify falla, webhook a Telegram
|
||
|
|
- Control: pausar/cancelar jobs desde la web sin SSH
|
||
|
|
- Audit log de quien ejecuto que y cuando
|
||
|
|
- Los playbooks estan en git (Forgejo)
|
||
|
|
|
||
|
|
#### n8n para workflows reactivos (futuro, mes 3-6)
|
||
|
|
|
||
|
|
Herramienta de tipo "si pasa X, haz Y" con editor visual de workflows. Apuntada como futura, no prioritaria.
|
||
|
|
|
||
|
|
| Trigger | Accion |
|
||
|
|
|---------|--------|
|
||
|
|
| Wazuh detecta fichero nuevo en /usr/bin | Enviar alerta Telegram + ejecutar audit playbook |
|
||
|
|
| PBS datastore > 90% quota | Notificar al comercial del cliente |
|
||
|
|
| Nuevo cliente en Netbox (ICSManager) | Ejecutar playbook pbs-customer.yml |
|
||
|
|
| Certificado SSL expira en 14 dias | Ejecutar renovacion + notificar |
|
||
|
|
| Sync job fallido 2 veces seguidas | Escalar a nivel 2 de soporte |
|
||
|
|
|
||
|
|
n8n tiene nodos de IA (OpenAI, Ollama local) que permiten analisis automatizado de eventos. Ejemplo: Wazuh detecta actividad sospechosa → n8n pasa el evento a un LLM → analiza si es falso positivo → si es real, alerta con explicacion en lenguaje claro.
|
||
|
|
|
||
|
|
**Cuando introducir**: cuando Ansible + Semaphore esten rodando y el equipo tenga soltura. No antes del mes 3.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Resumen Capa 3 completa (DECISIONES FINALES)
|
||
|
|
|
||
|
|
```
|
||
|
|
┌─────────────────────────────────────────────────────┐
|
||
|
|
│ CAPA 3: AUTOMATIZACION │
|
||
|
|
├─────────────────────────────────────────────────────┤
|
||
|
|
│ │
|
||
|
|
│ 3.1 CONFIGURACION │
|
||
|
|
│ ┌───────────────────────────────────┐ │
|
||
|
|
│ │ Ansible (gestion de config) │ │
|
||
|
|
│ │ - Sin agente (solo SSH) │ │
|
||
|
|
│ │ - Roles: bootstrap, PBS customer,│ │
|
||
|
|
│ │ hardening, deploy agentes │ │
|
||
|
|
│ │ - Inventario: estatico → Netbox │ │
|
||
|
|
│ │ - UI: Semaphore (SSO Authentik) │ │
|
||
|
|
│ │ - API: integracion ICSManager │ │
|
||
|
|
│ └───────────────────────────────────┘ │
|
||
|
|
│ │
|
||
|
|
│ 3.2 VERSION CONTROL + CI/CD │
|
||
|
|
│ ┌───────────────────────────────────┐ │
|
||
|
|
│ │ Forgejo EXISTENTE (no desplegar) │ │
|
||
|
|
│ │ - Repos nuevos: infra/ansible, │ │
|
||
|
|
│ │ infra/pbs-scripts, infra/ │ │
|
||
|
|
│ │ monitoring-config, docker-stacks│ │
|
||
|
|
│ │ - Actions: lint ansible (mes 1-2)│ │
|
||
|
|
│ │ - Branch protection en main │ │
|
||
|
|
│ └───────────────────────────────────┘ │
|
||
|
|
│ │
|
||
|
|
│ 3.3 IaC: DESCARTADO │
|
||
|
|
│ ┌───────────────────────────────────┐ │
|
||
|
|
│ │ Terraform/OpenTofu/Pulumi: no │ │
|
||
|
|
│ │ Servidores permanentes, no cloud │ │
|
||
|
|
│ │ Ansible cubre el 100% │ │
|
||
|
|
│ └───────────────────────────────────┘ │
|
||
|
|
│ │
|
||
|
|
│ 3.4 ORQUESTACION (confirmada) │
|
||
|
|
│ ┌───────────────────────────────────┐ │
|
||
|
|
│ │ Semaphore (scheduling de jobs) │ │
|
||
|
|
│ │ - Reemplaza cron jobs │ │
|
||
|
|
│ │ - Control concurrencia PBS │ │
|
||
|
|
│ │ - Notif. fallos → Telegram │ │
|
||
|
|
│ │ n8n (workflows reactivos, mes 3+)│ │
|
||
|
|
│ │ - Futuro, con posible IA │ │
|
||
|
|
│ └───────────────────────────────────┘ │
|
||
|
|
│ │
|
||
|
|
└─────────────────────────────────────────────────────┘
|
||
|
|
|
||
|
|
Recursos adicionales:
|
||
|
|
- Semaphore: contenedor Docker en VM servicios, 512 MB RAM
|
||
|
|
- Forgejo: YA DESPLEGADO (no requiere recursos nuevos)
|
||
|
|
- n8n (futuro): contenedor Docker, 512 MB RAM
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Prioridades de despliegue Capa 3
|
||
|
|
|
||
|
|
Contexto: equipo con experiencia minima en Ansible (solo apt upgrade en batch). Forgejo ya existe con proyectos de desarrollo. Servidor nuevo desde cero.
|
||
|
|
|
||
|
|
| Prioridad | Que | Esfuerzo | Impacto |
|
||
|
|
|-----------|-----|----------|---------|
|
||
|
|
| **Dia 1** | Crear repos infra en Forgejo existente | 1h | Scripts versionados desde el minuto 0 |
|
||
|
|
| **Dia 1** | Migrar scripts de /root/ a repo git | 1h | Backup de toda la operativa |
|
||
|
|
| **Semana 1** | Primer playbook: apt upgrade en todos (lo que ya sabian) | 2h | Confianza con Ansible |
|
||
|
|
| **Semana 1** | Playbook bootstrap-server.yml (hardening + agentes) | 4h | Cada servidor nuevo nace seguro |
|
||
|
|
| **Semana 2** | Instalar Semaphore (SSO Authentik) | 2h | UI web para ejecutar playbooks |
|
||
|
|
| **Semana 2** | Playbook deploy-wazuh-agent.yml | 2h | Wazuh desplegado en masa |
|
||
|
|
| **Mes 1** | Inventario dinamico Netbox → Ansible | 1 dia | Fuente unica de verdad |
|
||
|
|
| **Mes 1** | Role pbs_customer (reemplazar modificar.sh) | 1 dia | Provisionamiento idempotente |
|
||
|
|
| **Mes 1** | Migrar cron jobs a Semaphore scheduling | 2h | Audit log, notificaciones de fallo |
|
||
|
|
| **Mes 1-2** | Forgejo Actions: ansible-lint en cada push | 2h | Validacion automatica |
|
||
|
|
| **Mes 1-2** | Branch protection en repos de infra | 30min | Review obligatorio |
|
||
|
|
| **Mes 3+** | n8n para workflows reactivos | 1 dia | Automatizacion de respuestas a eventos |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Diagrama del stack completo hasta ahora (Capas 1-3)
|
||
|
|
|
||
|
|
```
|
||
|
|
┌──────────────────┐
|
||
|
|
│ GRAFANA │
|
||
|
|
│ (UI unificada) │
|
||
|
|
└────────┬─────────┘
|
||
|
|
│
|
||
|
|
┌───────────────────┼───────────────────┐
|
||
|
|
│ │ │
|
||
|
|
┌─────────▼─────────┐ ┌──────▼──────┐ ┌─────────▼─────────┐
|
||
|
|
│ VictoriaMetrics │ │ Loki │ │ Wazuh Dashboard │
|
||
|
|
│ (metricas) │ │ (logs) │ │ (seguridad) │
|
||
|
|
└─────────┬─────────┘ └──────┬──────┘ └─────────┬─────────┘
|
||
|
|
│ │ │
|
||
|
|
┌─────────▼─────────┐ │ ┌─────────▼─────────┐
|
||
|
|
│ vmagent (scraper) │ │ │ Wazuh Manager │
|
||
|
|
└─────────┬─────────┘ │ └─────────┬─────────┘
|
||
|
|
│ │ │
|
||
|
|
╔══════════╪═══════════════════╪════════════════════╪══════════╗
|
||
|
|
║ Cada servidor de produccion: ║
|
||
|
|
║ ┌──────────────┐ ┌────────┐ ┌───────────┐ ┌─────────────┐ ║
|
||
|
|
║ │node_exporter │ │ Alloy │ │Wazuh Agent│ │ CrowdSec │ ║
|
||
|
|
║ │(metricas) │ │(logs) │ │(FIM+HIDS) │ │ + Fail2ban │ ║
|
||
|
|
║ │ 5MB RAM │ │ 30-50MB│ │ 50-100MB │ │ ~80MB │ ║
|
||
|
|
║ └──────────────┘ └────────┘ └───────────┘ └─────────────┘ ║
|
||
|
|
║ + auditd (ya instalado, 0 extra) ║
|
||
|
|
║ Total overhead por servidor: ~200-250MB RAM ║
|
||
|
|
╚═════════════════════════════════════════════════════════════╝
|
||
|
|
|
||
|
|
┌─────────────────┐ ┌──────────────────┐
|
||
|
|
│ Netbox (CMDB) │────▶│ Ansible │
|
||
|
|
│ ← ICSManager │ │ + Semaphore (UI) │
|
||
|
|
└─────────────────┘ │ + Forgejo (git) │
|
||
|
|
└──────────────────┘
|
||
|
|
|
||
|
|
┌─────────────────┐ ┌──────────────────┐
|
||
|
|
│ Uptime Kuma │ │ Vaultwarden │
|
||
|
|
│ (checks binarios│ │ (passwords equipo│
|
||
|
|
└─────────────────┘ └──────────────────┘
|
||
|
|
|
||
|
|
VMs centrales (modelo: 1 VM = 1 servicio, caja negra):
|
||
|
|
- VM Monitoring: 4 vCPU, 8-12 GB RAM, 200-500 GB disco
|
||
|
|
- VM Wazuh: 4 vCPU, 12 GB RAM, 100 GB disco
|
||
|
|
- VM Zammad: 2-3 vCPU, 4-6 GB RAM, 50 GB disco
|
||
|
|
- VM Authentik: 1-2 vCPU, 2-3 GB RAM, 20 GB disco
|
||
|
|
- VM Netbox: 1-2 vCPU, 2-3 GB RAM, 20 GB disco
|
||
|
|
- VM ICSManager: 1-2 vCPU, 2-3 GB RAM, 20 GB disco
|
||
|
|
- VM WildDuck: 1-2 vCPU, 2-3 GB RAM, 30-50 GB disco
|
||
|
|
- VM Outline: 1 vCPU, 1-2 GB RAM, 20 GB disco
|
||
|
|
- VM Servicios: 1-2 vCPU, 2-3 GB RAM, 20 GB disco
|
||
|
|
(Semaphore + Uptime Kuma + Technitium + Traefik, stateless)
|
||
|
|
- VM Bastion: 1 vCPU, 1 GB RAM, 20 GB disco
|
||
|
|
- VM WG Hub A: 1 vCPU, 512 MB RAM, 10 GB disco (+ NAT CGNAT)
|
||
|
|
- VM WG Hub B: 1 vCPU, 512 MB RAM, 10 GB disco
|
||
|
|
- VM PDM: 1 vCPU, 1-2 GB RAM, 20 GB disco (Proxmox Datacenter Manager)
|
||
|
|
- VM PMG: 1-2 vCPU, 2-3 GB RAM, 30 GB disco (Proxmox Mail Gateway)
|
||
|
|
- VM Forgejo: YA DESPLEGADA
|
||
|
|
- PowerDNS: ya existente
|
||
|
|
- PBS1 (Alemania): ya existente
|
||
|
|
- PBS2 (Polonia): servidor fisico nuevo
|
||
|
|
- PBS3 (opcional): por cliente premium
|
||
|
|
- Replica oficina: servidor Xeon 96GB existente (coste 0)
|
||
|
|
|
||
|
|
Total infra de gestion: ~24-32 vCPU, ~44-58 GB RAM, ~580-920 GB disco
|
||
|
|
Recomendacion servidor: 128 GB RAM, 8-12c/16-24t, 2x2TB NVMe
|
||
|
|
```
|