Despliegue
Zentto se despliega en contenedores Docker gestionados mediante GitHub Actions con deploy automatico al hacer push a la rama main.
Arquitectura de produccion
Sección titulada «Arquitectura de produccion»| Componente | Valor |
|---|---|
| Servidor | Hetzner CX33 (Nuremberg) |
| IP | 178.104.56.185 |
| OS | Ubuntu 24.04 |
| Dominio | zentto.net (Cloudflare) |
| SSL | Let’s Encrypt (Certbot) |
| Reverse proxy | Nginx |
| Base de datos | PostgreSQL 16 (en host, no en Docker) |
| Contenedores | Docker con auto-restart via systemd |
Apps desplegadas
Sección titulada «Apps desplegadas»| App | Puerto | Subdominio | Repo |
|---|---|---|---|
| zentto-api | 4000 | api.zentto.net | zentto-web |
| zentto-frontend | 3000-3010 | zentto.net | zentto-web |
| zentto-notify | 5000 | notify.zentto.net | zentto-notify |
| notify-dashboard | 3100 | notify-dash.zentto.net | zentto-notify |
| broker-api | 4100 | broker.zentto.net | zentto-broker |
Archivos Docker
Sección titulada «Archivos Docker»| Archivo | Descripcion |
|---|---|
docker/Dockerfile.api | Imagen de la API Node.js |
docker/Dockerfile.frontend | Imagen del frontend con PM2 |
docker/pm2.config.cjs | Configuracion PM2 (puertos 3000-3010) |
docker-compose.yml | Compose para desarrollo local |
docker-compose.prod.yml | Compose para produccion (imagenes ghcr.io) |
PM2 Ecosystem
Sección titulada «PM2 Ecosystem»Las 15 micro-apps Next.js se sirven via PM2, cada una en su propio puerto:
| App | Puerto |
|---|---|
| shell | 3000 |
| ventas | 3001 |
| compras | 3002 |
| contabilidad | 3003 |
| inventario | 3004 |
| bancos | 3005 |
| nomina | 3006 |
| pos | 3007 |
| restaurante | 3008 |
| ecommerce | 3009 |
| auditoria | 3010 |
Las apps adicionales (crm, manufactura, flota, logistica) se asignan puertos siguientes.
CI/CD con GitHub Actions
Sección titulada «CI/CD con GitHub Actions»Pipeline de deploy
Sección titulada «Pipeline de deploy»Cada push a main dispara el pipeline:
Push a main --> Build Docker --> Push a ghcr.io --> SSH al servidor --> Pull + DeployWorkflows
Sección titulada «Workflows»| Workflow | Archivo | Trigger |
|---|---|---|
| Deploy API | deploy-api.yml | Push a main (cambios en web/api/) |
| Deploy Frontend | deploy-frontend.yml | Push a main (cambios en web/modular-frontend/) |
| Tests | test.yml | Push a cualquier rama |
| DB Governance | db-governance.yml | Push con cambios SQL |
| Hotfix | hotfix.yml | Manual (workflow_dispatch) |
Secrets de GitHub
Sección titulada «Secrets de GitHub»| Secret | Uso |
|---|---|
SSH_HOST | IP del servidor (178.104.56.185) |
SSH_USER | Usuario SSH (root) |
SSH_PRIVATE_KEY | Clave privada para SSH |
GITHUB_TOKEN | Token automatico para ghcr.io |
AUTH_SECRET | Secret de NextAuth para el frontend |
NOTIFY_API_KEY | API key de Zentto Notify |
Proceso de deploy (simplificado)
Sección titulada «Proceso de deploy (simplificado)»jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Build and push Docker image run: | docker build -f docker/Dockerfile.api -t ghcr.io/zentto-erp/zentto-web/api:latest . docker push ghcr.io/zentto-erp/zentto-web/api:latest - name: Deploy to server via SSH run: | ssh root@178.104.56.185 << 'EOF' docker pull ghcr.io/zentto-erp/zentto-web/api:latest docker stop zentto-api || true docker rm zentto-api || true docker run -d --name zentto-api --restart always \ --env-file /opt/zentto/.env.api \ -p 4000:4000 \ ghcr.io/zentto-erp/zentto-web/api:latest EOFNginx (Reverse Proxy)
Sección titulada «Nginx (Reverse Proxy)»Nginx en el servidor actua como reverse proxy y gestiona SSL. CORS se maneja a nivel Nginx con el flag always.
Configuracion principal:
zentto.net/www.zentto.net—> frontend (puerto 3000)api.zentto.net—> API (puerto 4000)notify.zentto.net—> Zentto Notify (puerto 5000)
Headers CORS configurados en Nginx:
add_header Access-Control-Allow-Origin $http_origin always;add_header Access-Control-Allow-Methods "GET,POST,PUT,DELETE,PATCH,OPTIONS" always;add_header Access-Control-Allow-Headers "Authorization,Content-Type" always;Base de datos
Sección titulada «Base de datos»PostgreSQL (Produccion)
Sección titulada «PostgreSQL (Produccion)»PostgreSQL corre directamente en el host (no en Docker) para mejor rendimiento:
| Parametro | Valor |
|---|---|
| Base de datos | zentto_prod |
| Usuario | zentto_app |
| Host (desde Docker) | 172.18.0.1 (Docker gateway) |
| Puerto | 5432 |
Configuracion de red Docker:
- Docker network:
172.18.0.0/16(gateway172.18.0.1) - UFW:
allow from 172.18.0.0/16 to any port 5432 - pg_hba.conf:
host zentto_prod zentto_app 172.18.0.0/16 scram-sha-256 PG_HOSTen.env.apidebe ser172.18.0.1(Docker gateway, NO localhost)
Despliegue de esquema PostgreSQL
Sección titulada «Despliegue de esquema PostgreSQL»# Desde ceropsql -U postgres -f web/api/sqlweb-pg/00_create_database.sqlpsql -U postgres -d datqboxweb -f web/api/sqlweb-pg/run_all.sql
# Actualizacion incremental (idempotente)psql -U zentto_app -d zentto_prod -f web/api/sqlweb-pg/run_all.sqlEl archivo run_all.sql es idempotente: usa CREATE OR REPLACE FUNCTION y CREATE TABLE IF NOT EXISTS.
Despliegue de esquema SQL Server
Sección titulada «Despliegue de esquema SQL Server»Abrir web/api/sqlweb/run_all.sql en SSMS y ejecutar. Usa directivas :r para incluir sub-scripts.
Orden de archivos PostgreSQL
Sección titulada «Orden de archivos PostgreSQL»00_create_database.sql -- Base + extensiones01_core_foundation.sql -- Schemas + tablas cfg/sec02_master_data.sql -- Customer, Supplier, Employee, Product03_accounting_core.sql -- Account, JournalEntry04_operations_core.sql -- AR, AP, Fiscal, POS, REST05_api_compat_bridge.sql -- Tablas legacy bridge06_seed_reference_data.sql -- Datos semilla07_pos_rest_extensions.sql -- Extensiones POS/Restaurante08_fin_hr_extensions.sql -- Extensiones Finanzas/RRHH09_canonical_maestros.sql -- Maestros canonicos10_canonical_documents.sql -- Documentos canonicos11_canonical_usuarios_fiscal.sql12_payment_ecommerce.sql -- Pagos y ecommerce13_triggers.sql -- Triggers14_fulltext_search.sql -- Busqueda full-text15_seed_contabilidad.sql -- Seed contabilidad16_seed_nomina.sql -- Seed nomina17_seed_ecommerce.sql -- Seed ecommerceincludes/sp/*.sql -- Funciones PL/pgSQLVariables de entorno
Sección titulada «Variables de entorno»API (web/api/.env)
Sección titulada «API (web/api/.env)»| Variable | Descripcion | Ejemplo |
|---|---|---|
DB_TYPE | Motor de BD activo | postgres |
PG_HOST | Host PostgreSQL | 172.18.0.1 |
PG_PORT | Puerto PostgreSQL | 5432 |
PG_DATABASE | Base de datos | zentto_prod |
PG_USER | Usuario PG | zentto_app |
PG_PASSWORD | Password PG | (secreto) |
JWT_SECRET | Secret para firmar JWT | (secreto) |
PORT | Puerto de la API | 4000 |
NODE_ENV | Ambiente | production |
CORS_ORIGIN | Origenes CORS | https://zentto.net |
NOTIFY_API_URL | URL de Zentto Notify | http://localhost:5000 |
NOTIFY_API_KEY | API key de Notify | (secreto) |
Frontend (web/modular-frontend/.env)
Sección titulada «Frontend (web/modular-frontend/.env)»| Variable | Descripcion | Ejemplo |
|---|---|---|
NEXT_PUBLIC_API_URL | URL de la API | https://api.zentto.net |
AUTH_SECRET | Secret de NextAuth | (secreto) |
NEXTAUTH_URL | URL base de NextAuth | https://zentto.net |
SSL con Certbot
Sección titulada «SSL con Certbot»# Instalacion inicial (en el servidor)certbot --nginx -d zentto.net -d www.zentto.net -d api.zentto.net
# Renovacion automatica (ya configurado via cron)certbot renew --quietDNS Cloudflare
Sección titulada «DNS Cloudflare»| Tipo | Nombre | Valor | Proxy |
|---|---|---|---|
| A | zentto.net | 178.104.56.185 | ON |
| A | www.zentto.net | 178.104.56.185 | ON |
| A | api.zentto.net | 178.104.56.185 | ON |
| A | notify.zentto.net | 178.104.56.185 | ON |
Setup del servidor (primera vez)
Sección titulada «Setup del servidor (primera vez)»# En el servidor como root:bash <(curl -sSL https://raw.githubusercontent.com/datqbox/zentto-web/main/scripts/server-setup.sh)Este script instala Docker, Nginx, Certbot, PostgreSQL y configura el firewall.
Comandos utiles en el servidor
Sección titulada «Comandos utiles en el servidor»# Ver todos los contenedoresdocker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
# Reiniciar un serviciodocker restart zentto-api
# Ver logs en tiempo realdocker logs -f zentto-api
# Health check manualcurl http://localhost:4000/health
# Ejecutar script de inicio completo/opt/zentto/start-services.sh
# Ver log de inicio del sistematail -f /var/log/zentto-startup.log