Volver a la wiki

Hetzner STAGE (178.104.131.173) — inventario y plan de réplica

Hetzner STAGE (178.104.131.173) — inventario y plan de réplica

Servidor “compartido” del equipo. Empezó como entorno de pruebas de CreaRack-Pro y fue acumulando responsabilidades hasta convertirse en componente operativo. Esta página es el inventario actualizado y el playbook de réplica si hay que levantarlo desde cero.

Si STAGE cae, la lista de impactos está en § 3. No es solo “el staging” — hospeda el panel Dokploy con el que se gestiona PROD, los backups de DR del workspace, y un mirror DR de la wiki. Hay que rehidratarlo rápido.

⚠️ Actualización 05-07-2026 (s201 · F3 de la migración a OPS): todos los crons del Bibliotecario/deploy/watchdog/heartbeat que hospedaba este servidor se migraron a crearack-ops (s193, 03-07) y la limpieza F3 ya se ejecutó: en STAGE quedan SOLO Dokploy, el entorno staging de Pro, los crons de dr-backups (crontab de root + purge) y el mirror DR (nginx :8090). Los /opt migrados, los /etc/cron.d comentados y las deploy keys viejas (staging-bib-reindex + hetzner-reindex ×2) ya no existen. Inventario del servidor nuevo: concept--infra--ops-server.


1. Hardware y red

AtributoValor
ProveedorHetzner Cloud
TipoCX23 (compartido)
Recursos1 vCPU, 4 GB RAM, 40 GB NVMe
OSUbuntu 24.04.4 LTS
Hostnamecrearack-staging
IP pública178.104.131.173
Acceso SSHssh root@178.104.131.173 (key-only, según política)

Disco: a 30/04/2026 está al 84% lleno (30 GB / 38 GB). No urgente pero ya en zona de atención. Causa principal: backups DR del workspace acumulándose (~5 MB/día). Mitigación implementada: cron de purga >90 días (ver § 4).


2. Servicios hospedados

2.1 CreaRack-Pro · entorno staging completo

Stack desplegado por Dokploy (proyecto crearackpro), exactamente la misma topología que PROD pero con BD independiente.

ContenedorImagenPuerto internoFunción
crearackpro-crearackpro-oyvenu-web-1crearackpro-crearackpro-oyvenu-web (build local)8000 → hostDjango + Daphne ASGI
crearackpro-crearackpro-oyvenu-worker-1crearackpro-crearackpro-oyvenu-worker—Huey worker
crearackpro-crearackpro-oyvenu-pgbouncer-1edoburu/pgbouncer:latest5432PG connection pooler
crearackpro-crearackpro-oyvenu-db-1postgres:18-alpine5432Postgres staging
crearackpro-crearackpro-oyvenu-cache-1valkey/valkey:7.2-alpine6379Cache + Huey broker
crearackpro-crearackpro-oyvenu-victoriametrics-1victoriametrics/victoria-metrics:v1.106.18428Metrics TSDB

Acceso web del staging: puerto 8000 del host. Sin TLS público — alcance interno. NO contiene datos de clientes.

2.2 Dokploy (panel de orquestación de PROD + STAGE)

ContenedorImagenPuerto
dokploy.1.qzhdwqqncwtp8g107axcrdf7gdokploy/dokploy:v0.28.83000 → host
dokploy-traefiktraefik:v3.6.780, 443 → host
dokploy-redisredis:76379 (interno)
dokploy-postgrespostgres:165432 (interno)

Crítico: el panel Dokploy en https://178.104.131.173:3000 (o el dominio que se configure) es desde donde se gestionan los entornos del proyecto, incluyendo PROD. Si STAGE cae, no hay panel para gestionar PROD — habría que ir a SSH PROD directamente. Postgres y Redis de Dokploy guardan el estado del panel (proyectos, env vars, deploys).

Modo Docker Swarm activo (Dokploy lo requiere — ver infra_dokploy_swarm.md). Puertos Swarm internos: 2377 + 7946.

2.3 Crons del Bibliotecario (Supercontexto) — MIGRADOS A OPS

Ya no viven aquí. Migrados a crearack-ops en s193 (03-07-2026) y borrados de STAGE en la limpieza F3 (s201, 05-07-2026): bib-reindex (AST Pro + communities + extras), bib-reindex-ws (ts/supercontext/claude-method/chunks/wiki), biblioteca-crons (lint/curator/utility/drift/escriba/enrich), cf-pages-deploy y cron-heartbeat. Detalle e inventario: concept--infra--ops-server + AUTOMATISMOS.md §4.

2.4 Crons de Disaster Recovery (workspace)

Root crontab:

0 0 * * * /opt/dr-backups/cron-dr-backup.sh    >> /opt/dr-backups/cron.log 2>&1
0 3 * * 0 /opt/dr-backups/cron-gdrive-sync.sh  >> /opt/dr-backups/cron.log 2>&1
0 8 * * * /opt/dr-backups/cron-stale-check.sh  >> /opt/dr-backups/cron.log 2>&1
CronHoraQué hace
cron-dr-backup.sh00:00 UTC diarioGET https://workspace.crearack.com/api/maintenance/export → JSON con todo el D1 → /opt/dr-backups/backup-YYYY-MM-DD.json
cron-gdrive-sync.shDomingo 03:00 UTCrclone sync /opt/dr-backups/*.json gdrive:CreaRackSL/backups/workspace (offsite)
cron-stale-check.sh08:00 UTC diarioPOST https://workspace.crearack.com/api/maintenance/stale-check → log a activity_log del workspace

Dependencias:

2.5 Workspace mirror DR (nginx puerto 8090)

/etc/nginx/sites-enabled/workspace-mirror:

server {
    listen 8090;
    root /opt/workspace-mirror/site;
    auth_basic "CreaRackSL DR Mirror";
    auth_basic_user_file /etc/nginx/.htpasswd;
    # ... try_files + cache headers + security headers
}

Sirve una copia estática del workspace (/opt/workspace-mirror/site/) para acceso de emergencia si Cloudflare Pages cae. Auth básica con /etc/nginx/.htpasswd. Acceso: http://178.104.131.173:8090.

2.6 Watchdog GitHub Actions push triggers — MIGRADO A OPS

Ya no vive aquí (migrado s193, borrado de STAGE en F3 s201). Corre en crearack-ops cada 5 min; desde s201 vigila ci.yml (Pro) y post-merge-ingest.yml (workspace) — cf-pages-deploy.yml salió del par al migrar el deploy al cron de OPS (workflow disabled → dispatch 422). Fuente: scripts/gh-actions-watchdog.sh del repo workspace.

2.7 Servicios sistema

2.8 Puertos abiertos

PuertoServicioQuién
22SSHsshd
80, 443Traefik HTTP/HTTPSDokploy ingress
3000Dokploy paneldocker-proxy
8000CreaRack-Pro staging webdocker-proxy
8090Workspace mirror DRnginx
2377, 7946Docker Swarmdockerd (cluster mgmt)

3. Impacto si STAGE cae

Servicio caídoImpactoTiempo hasta dolor
Dokploy panelNo hay UI para gestionar PROD ni STAGE; deploys via panel imposibles. SSH directo a PROD sigue funcionandoInmediato
DR backups workspaceNO se exporta el D1 ese día → ventana sin snapshot24 h por día caído
DR Google Drive syncBackups offsite no se actualizanSemana siguiente
DR stale checkSin alertas de docs desactualizados24 h por día caído
Workspace DR mirror (8090)Plan B de la wiki si CF Pages cae no existeSolo si CF Pages cae a la vez
CreaRack-Pro stagingSin entorno test antes de promocionar a PRODInmediato pero no bloquea desarrollo

4. Procedimiento de réplica (recovery from zero)

Pasos para levantar un STAGE nuevo desde cero. Asumimos que el actual es irrecuperable.

4.1 Provisionar máquina

  1. Hetzner Console → crear servidor CX23 con Ubuntu 24.04 LTS.
  2. Asignar IP estática y configurar DNS si aplica.
  3. Subir SSH key del equipo durante la creación.
  4. Hardening básico:
    • apt update && apt upgrade -y
    • apt install -y unattended-upgrades fail2ban nginx jq curl
    • SSH PermitRootLogin prohibit-password, deshabilitar password auth.
    • UFW o Hetzner Cloud Firewall: 22, 80, 443, 3000, 8000, 8090.
    • qemu-guest-agent (vendor integration).

4.2 Docker + Dokploy + Swarm

  1. Instalar Docker Engine (oficial) + plugin compose.
  2. docker swarm init (Dokploy lo requiere).
  3. Restaurar volúmenes Docker desde backup Hetzner snapshot, o instalar Dokploy limpio (curl -sSL https://dokploy.com/install.sh | sh) y restaurar:
    • dokploy-postgres data dir → estado del panel (proyectos, deploys, env vars).
    • dokploy-redis data dir → caché.
  4. Re-conectar la nueva instancia al proyecto en Dokploy (mismo Git repo + env vars). En el peor caso reconfigurar manualmente desde la página crearack-tech--admin--dokploy-internals.

4.3 CreaRack-Pro staging

Si Dokploy se restauró, los servicios crearackpro-* se redespliegan automáticamente al detectar el commit más reciente. BD: si se restauró desde snapshot, datos intactos; si arranca limpio, ejecutar migraciones (docker exec ... python manage.py migrate).

4.4 Bibliotecario (bib-reindex) — YA NO APLICA

Los crons del Bibliotecario viven en crearack-ops desde s193; al replicar STAGE no hay que restaurarlos aquí. Su playbook de réplica está en concept--infra--ops-server.

4.5 DR backups + Google Drive

mkdir -p /opt/dr-backups
chmod 700 /opt/dr-backups

# Token API workspace
echo "<MAINTENANCE_TOKEN>" > /opt/dr-backups/.token
chmod 600 /opt/dr-backups/.token

# Scripts (en repo workspace bajo scripts/cron-*.sh)
scp scripts/cron-dr-backup.sh scripts/cron-gdrive-sync.sh scripts/cron-stale-check.sh root@<NEW_IP>:/opt/dr-backups/
chmod +x /opt/dr-backups/cron-*.sh

# rclone — config gdrive remote (auth headless desde otro PC)
apt install rclone
rclone config  # crear remote "gdrive" tipo Google Drive

# Crontab root
( crontab -l 2>/dev/null; cat <<EOF
0 0 * * * /opt/dr-backups/cron-dr-backup.sh    >> /opt/dr-backups/cron.log 2>&1
0 3 * * 0 /opt/dr-backups/cron-gdrive-sync.sh  >> /opt/dr-backups/cron.log 2>&1
0 8 * * * /opt/dr-backups/cron-stale-check.sh  >> /opt/dr-backups/cron.log 2>&1
EOF
) | crontab -

# Si hay backups históricos en Google Drive, restaurar localmente para continuidad
rclone copy gdrive:CreaRackSL/backups/workspace /opt/dr-backups/

4.6 Workspace DR mirror (nginx 8090)

# Site dir
mkdir -p /opt/workspace-mirror/site

# htpasswd
htpasswd -c /etc/nginx/.htpasswd <user>

# Configuración nginx
cat > /etc/nginx/sites-available/workspace-mirror <<'EOF'
server {
    listen 8090;
    server_name _;
    root /opt/workspace-mirror/site;
    index index.html;
    auth_basic "CreaRackSL DR Mirror";
    auth_basic_user_file /etc/nginx/.htpasswd;
    location / { try_files $uri $uri/ $uri/index.html =404; }
    location /_astro/ { expires 30d; add_header Cache-Control "public, immutable"; }
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    error_page 404 /404.html;
}
EOF
ln -s /etc/nginx/sites-available/workspace-mirror /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx

# Sembrar mirror — descargar build estático del workspace y descomprimir en /opt/workspace-mirror/site
# (proceso documentado en workspace--guias--disaster-recovery-workspace)

4.7 Watchdog GH Actions

mkdir -p /opt/gh-actions-watchdog
chmod 700 /opt/gh-actions-watchdog

# PAT fine-grained con Actions: write en ambos repos
echo "<GH_PAT>" > /opt/gh-actions-watchdog/.token
chmod 600 /opt/gh-actions-watchdog/.token

# Script (versionado en el repo workspace bajo scripts/gh-actions-watchdog.sh)
scp scripts/gh-actions-watchdog.sh root@<NEW_IP>:/opt/gh-actions-watchdog/watchdog.sh
chmod +x /opt/gh-actions-watchdog/watchdog.sh

cat > /etc/cron.d/gh-actions-watchdog <<'EOF'
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
*/5 * * * * root /opt/gh-actions-watchdog/watchdog.sh >> /opt/gh-actions-watchdog/watchdog.log 2>&1
EOF
chmod 644 /etc/cron.d/gh-actions-watchdog

4.8 Cron de purga DR backups

Para no llenar disco (los offsite están en Drive):

cat > /etc/cron.d/dr-backups-purge <<'EOF'
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# Sábados 04:30 UTC: borrar JSON locales >90 días (los offsite siguen en Drive)
30 4 * * 6 root find /opt/dr-backups -name 'backup-*.json' -type f -mtime +90 -delete
EOF
chmod 644 /etc/cron.d/dr-backups-purge

5. Tokens y credenciales que viven aquí

ArchivoContenidoCómo regenerar
/opt/bib-reindex/.tokenBIB_MCP_TOKEN para escribir en el MCP del workspacerunbook--infra--rotate-mcp-token
/opt/dr-backups/.tokenToken de la API maintenance del workspaceVariable MAINTENANCE_API_TOKEN en CF Pages workspace
/opt/gh-actions-watchdog/.tokenGitHub PAT (fine-grained, Actions: write)https://github.com/settings/tokens — fine-grained
/etc/nginx/.htpasswdUsuario+hash para auth básica del mirrorhtpasswd -c /etc/nginx/.htpasswd <user>
~/.config/rclone/rclone.conf (root)OAuth tokens Google Driverclone config con auth headless
Deploy key SSH para clone de /opt/crearack-proRead-only sobre el repoGitHub Settings → Deploy keys → repo CreaRack-Pro

6. Rutina mensual de verificación

  1. SSH login funciona y uptime razonable.
  2. df -h / < 90% (purgar manualmente si no, hay margen para >90 días aún).
  3. docker ps muestra los 12 contenedores (8 CreaRack-Pro — web, worker, db, pgbouncer, cache, victoriametrics, vmalert, alertmanager — + 4 Dokploy/Traefik). (Eran 10 hasta mediados de 2026; actualizado 18-08-2026 tras el reboot de kernel.)
  4. ls -lt /opt/dr-backups/backup-*.json | head -3 → último backup hoy o ayer.
  5. curl -s -o /dev/null -w '%{http_code}' http://localhost:8090/ → 401 (el mirror DR vive y pide credenciales; 000/timeout = nginx caído).
  6. fail2ban-client status sshd → sin bans excesivos.

(Los pasos antiguos 5-6 — /opt/bib-reindex y /opt/gh-actions-watchdog — se retiraron el 18-08-2026: esos crons migraron a OPS en s193/s201 y sus /opt ya no existen aquí; su verificación vive en concept--infra--ops-server.)


7. Histórico

Véase también

Subir