Ir al contenido

Despliegue

Zentto se despliega en contenedores Docker gestionados mediante GitHub Actions con deploy automatico al hacer push a la rama main.

ComponenteValor
ServidorHetzner CX33 (Nuremberg)
IP178.104.56.185
OSUbuntu 24.04
Dominiozentto.net (Cloudflare)
SSLLet’s Encrypt (Certbot)
Reverse proxyNginx
Base de datosPostgreSQL 16 (en host, no en Docker)
ContenedoresDocker con auto-restart via systemd
AppPuertoSubdominioRepo
zentto-api4000api.zentto.netzentto-web
zentto-frontend3000-3010zentto.netzentto-web
zentto-notify5000notify.zentto.netzentto-notify
notify-dashboard3100notify-dash.zentto.netzentto-notify
broker-api4100broker.zentto.netzentto-broker
ArchivoDescripcion
docker/Dockerfile.apiImagen de la API Node.js
docker/Dockerfile.frontendImagen del frontend con PM2
docker/pm2.config.cjsConfiguracion PM2 (puertos 3000-3010)
docker-compose.ymlCompose para desarrollo local
docker-compose.prod.ymlCompose para produccion (imagenes ghcr.io)

Las 15 micro-apps Next.js se sirven via PM2, cada una en su propio puerto:

AppPuerto
shell3000
ventas3001
compras3002
contabilidad3003
inventario3004
bancos3005
nomina3006
pos3007
restaurante3008
ecommerce3009
auditoria3010

Las apps adicionales (crm, manufactura, flota, logistica) se asignan puertos siguientes.

Cada push a main dispara el pipeline:

Push a main --> Build Docker --> Push a ghcr.io --> SSH al servidor --> Pull + Deploy
WorkflowArchivoTrigger
Deploy APIdeploy-api.ymlPush a main (cambios en web/api/)
Deploy Frontenddeploy-frontend.ymlPush a main (cambios en web/modular-frontend/)
Teststest.ymlPush a cualquier rama
DB Governancedb-governance.ymlPush con cambios SQL
Hotfixhotfix.ymlManual (workflow_dispatch)
SecretUso
SSH_HOSTIP del servidor (178.104.56.185)
SSH_USERUsuario SSH (root)
SSH_PRIVATE_KEYClave privada para SSH
GITHUB_TOKENToken automatico para ghcr.io
AUTH_SECRETSecret de NextAuth para el frontend
NOTIFY_API_KEYAPI key de Zentto Notify
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
EOF

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;

PostgreSQL corre directamente en el host (no en Docker) para mejor rendimiento:

ParametroValor
Base de datoszentto_prod
Usuariozentto_app
Host (desde Docker)172.18.0.1 (Docker gateway)
Puerto5432

Configuracion de red Docker:

  • Docker network: 172.18.0.0/16 (gateway 172.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_HOST en .env.api debe ser 172.18.0.1 (Docker gateway, NO localhost)
Ventana de terminal
# Desde cero
psql -U postgres -f web/api/sqlweb-pg/00_create_database.sql
psql -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.sql

El archivo run_all.sql es idempotente: usa CREATE OR REPLACE FUNCTION y CREATE TABLE IF NOT EXISTS.

Abrir web/api/sqlweb/run_all.sql en SSMS y ejecutar. Usa directivas :r para incluir sub-scripts.

00_create_database.sql -- Base + extensiones
01_core_foundation.sql -- Schemas + tablas cfg/sec
02_master_data.sql -- Customer, Supplier, Employee, Product
03_accounting_core.sql -- Account, JournalEntry
04_operations_core.sql -- AR, AP, Fiscal, POS, REST
05_api_compat_bridge.sql -- Tablas legacy bridge
06_seed_reference_data.sql -- Datos semilla
07_pos_rest_extensions.sql -- Extensiones POS/Restaurante
08_fin_hr_extensions.sql -- Extensiones Finanzas/RRHH
09_canonical_maestros.sql -- Maestros canonicos
10_canonical_documents.sql -- Documentos canonicos
11_canonical_usuarios_fiscal.sql
12_payment_ecommerce.sql -- Pagos y ecommerce
13_triggers.sql -- Triggers
14_fulltext_search.sql -- Busqueda full-text
15_seed_contabilidad.sql -- Seed contabilidad
16_seed_nomina.sql -- Seed nomina
17_seed_ecommerce.sql -- Seed ecommerce
includes/sp/*.sql -- Funciones PL/pgSQL
VariableDescripcionEjemplo
DB_TYPEMotor de BD activopostgres
PG_HOSTHost PostgreSQL172.18.0.1
PG_PORTPuerto PostgreSQL5432
PG_DATABASEBase de datoszentto_prod
PG_USERUsuario PGzentto_app
PG_PASSWORDPassword PG(secreto)
JWT_SECRETSecret para firmar JWT(secreto)
PORTPuerto de la API4000
NODE_ENVAmbienteproduction
CORS_ORIGINOrigenes CORShttps://zentto.net
NOTIFY_API_URLURL de Zentto Notifyhttp://localhost:5000
NOTIFY_API_KEYAPI key de Notify(secreto)
VariableDescripcionEjemplo
NEXT_PUBLIC_API_URLURL de la APIhttps://api.zentto.net
AUTH_SECRETSecret de NextAuth(secreto)
NEXTAUTH_URLURL base de NextAuthhttps://zentto.net
Ventana de terminal
# 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 --quiet
TipoNombreValorProxy
Azentto.net178.104.56.185ON
Awww.zentto.net178.104.56.185ON
Aapi.zentto.net178.104.56.185ON
Anotify.zentto.net178.104.56.185ON
Ventana de terminal
# 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.

Ventana de terminal
# Ver todos los contenedores
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
# Reiniciar un servicio
docker restart zentto-api
# Ver logs en tiempo real
docker logs -f zentto-api
# Health check manual
curl http://localhost:4000/health
# Ejecutar script de inicio completo
/opt/zentto/start-services.sh
# Ver log de inicio del sistema
tail -f /var/log/zentto-startup.log