Files
Milton Gonzalez fa4ddbe164 feat: version 2.2.0 -- boton real de actualizacion (auto-update)
POST /api/updater/apply dispara scripts/apply-update.sh (backup +
git pull + migraciones + build + restart) en un proceso separado.
Apagado por defecto: solo se activa si el servidor define
UPDATE_APP_DIR/UPDATE_BACKEND_SERVICE/UPDATE_FRONTEND_SERVICE en su
backend/.env. Sin esa config, el panel se comporta igual que antes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 12:18:12 -05:00

10 KiB

Deploy Web - project.linkedcorp.net

Arquetipo B (dos servicios separados). Primer deploy realizado el 2026-09-06.


Instalación automatizada en un servidor NUEVO

scripts/install.sh automatiza todo lo de esta sección para un servidor Debian/Ubuntu nuevo: verifica requisitos (Node.js, npm, cliente mysql, systemd, espacio, puertos libres), pregunta dominio/puertos y datos de base de datos (MariaDB local — se instala sola si hace falta — o un servidor existente), crea la base + usuario, genera backend/.env con secretos aleatorios, instala dependencias, corre migraciones + catálogos, compila el frontend y crea/arranca los servicios systemd.

# En el servidor nuevo, ya con el repo clonado en /opt/apps/project.linkedcorp.net/source:
cd /opt/apps/project.linkedcorp.net/source
sudo scripts/install.sh

No configura el reverse proxy/TLS (paso 11 más abajo, específico de cada proveedor) ni crea ningún usuario: el primer registro público en /registro se vuelve superadministrador solo — no hace falta create-admin.js en instalaciones nuevas.

Las secciones de abajo son la referencia manual (lo que hace el script paso a paso) — útiles para entender el porqué de cada cosa o para resolver un problema puntual sin volver a correr todo.

Requisito para el panel "Actualizaciones" (Configuración → superadmin): el servidor instalado necesita poder llegar por HTTPS a gitea.linkedcorp.net de forma anónima (repo público + vista anónima habilitada en Gitea) para poder consultar el CHANGELOG.md y las migraciones nuevas. No requiere ningún token ni credencial. Si no hay conectividad a Gitea, ese panel simplemente muestra el error al buscar actualizaciones — el resto de la app funciona igual.


Primer despliegue en producción (ya ejecutado — referencia)

1. Entrar al servidor

ssh deploy@192.168.222.3 -p 2203

2. Crear estructura de directorios

sudo mkdir -p /opt/apps/project.linkedcorp.net/{source,backend,frontend,storage,logs}
sudo chown -R deploy:deploy /opt/apps/project.linkedcorp.net

3. Clonar el repositorio

cd /opt/apps/project.linkedcorp.net/source
git clone http://[gitea_user]:[token]@gitea.linkedcorp.net/mgonzalez/project.linkedcorp.net.git .
git remote set-url origin http://gitea.linkedcorp.net/mgonzalez/project.linkedcorp.net.git   # sin token en claro

4. Crear el .env de producción

nano /opt/apps/project.linkedcorp.net/backend/.env

Variables reales (valores sensibles solo en el archivo del servidor, nunca en git):

PORT=4019
NODE_ENV=production
DB_HOST=192.168.222.32
DB_PORT=3306
DB_NAME=project_linkedcorp
DB_USER=project_linkedcorp
DB_PASSWORD=[generada por crear-db-prod.sh]
JWT_SECRET=[openssl rand -hex 32]
JWT_EXPIRES=8h
CORS_ORIGIN=https://project.linkedcorp.net
STORAGE_ROOT=/opt/apps/project.linkedcorp.net/storage

Nunca copiar el .env de desarrollo.

5. Instalar dependencias del backend

cd /opt/apps/project.linkedcorp.net/source/backend
npm install --omit=dev
cp -r node_modules /opt/apps/project.linkedcorp.net/backend/

6. Compilar el frontend y publicar el runtime

El frontend es un proceso separado (serve sirviendo el build). Runtime propio en frontend/ con un package.json minimo (solo depende de serve) — evita copiar todo node_modules de Vite:

cd /opt/apps/project.linkedcorp.net/source/frontend
npm install
npm run build
cp -r dist /opt/apps/project.linkedcorp.net/frontend/dist

cat > /opt/apps/project.linkedcorp.net/frontend/package.json <<'EOF'
{ "name": "project-linkedcorp-frontend-runtime", "private": true, "version": "1.0.0",
  "dependencies": { "serve": "^14.2.6" } }
EOF
cd /opt/apps/project.linkedcorp.net/frontend && npm install --omit=dev

En un redeploy solo hace falta reemplazar frontend/dist (borrar y volver a copiar) — el node_modules del runtime frontend no cambia salvo que cambie la version de serve.

7. Ejecutar migración de base de datos

cd /opt/apps/project.linkedcorp.net/source/backend
set -a && source /opt/apps/project.linkedcorp.net/backend/.env && set +a
node src/scripts/migrate-db.js

8. Inicializar datos

# Catalogos base (roles, prioridades, estados, tipos de proyecto) — sin datos de ejemplo en produccion:
node src/scripts/seed-db.js

# Usuario Administrador inicial (clave fuerte generada, se muestra UNA sola vez):
node src/scripts/create-admin.js "Nombre Apellido" correo@linkedcorp.net

9. Crear el servicio systemd del backend

# /etc/systemd/system/project-linkedcorp-backend.service
[Unit]
Description=project.linkedcorp.net backend
After=network.target

[Service]
Type=simple
User=deploy
WorkingDirectory=/opt/apps/project.linkedcorp.net/source/backend
ExecStart=/usr/bin/node src/server.js
EnvironmentFile=/opt/apps/project.linkedcorp.net/backend/.env
Restart=on-failure
RestartSec=5
StandardOutput=append:/opt/apps/project.linkedcorp.net/logs/backend.log
StandardError=append:/opt/apps/project.linkedcorp.net/logs/backend-error.log

[Install]
WantedBy=multi-user.target

10. Crear el servicio systemd del frontend

# /etc/systemd/system/project-linkedcorp-frontend.service
[Unit]
Description=project.linkedcorp.net frontend
After=network.target

[Service]
Type=simple
User=deploy
WorkingDirectory=/opt/apps/project.linkedcorp.net/frontend
ExecStart=/usr/bin/node node_modules/.bin/serve -s dist -l 5196
Restart=on-failure
RestartSec=5
StandardOutput=append:/opt/apps/project.linkedcorp.net/logs/frontend.log
StandardError=append:/opt/apps/project.linkedcorp.net/logs/frontend-error.log

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable project-linkedcorp-backend project-linkedcorp-frontend
sudo systemctl start project-linkedcorp-backend project-linkedcorp-frontend
sudo systemctl status project-linkedcorp-backend project-linkedcorp-frontend

11. Configurar Nginx Proxy Manager

Proxy Host:

Campo Valor
Domain project.linkedcorp.net
Forward Hostname/IP 192.168.222.3
Forward Port 5196 (frontend)
Scheme http
SSL Let's Encrypt, Force SSL

Custom Location:

Campo Valor
Location /api
Forward Hostname/IP 192.168.222.3
Forward Port 4019 (backend)
Scheme http

12. Verificar

curl http://127.0.0.1:4019/health
curl -o /dev/null -w "%{http_code}\n" http://127.0.0.1:5196/
curl https://project.linkedcorp.net/api/auth/login -X POST -H 'Content-Type: application/json' -d '{...}'

12.5 Habilitar el botón "Actualizar" (auto-actualización, opcional)

Por defecto el panel Configuración → Actualizaciones solo informa. Para que el botón "Actualizar" aplique el cambio solo (backup + git pull + migraciones + build + restart), hace falta en el servidor:

# 1. sudo (si no esta instalado) y permiso acotado para el usuario deploy — SOLO reiniciar
#    estos dos servicios puntuales, nada mas.
sudo apt-get install -y sudo   # si el servidor no lo trae (ej. instalaciones minimas de Debian)
echo 'deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart <backend-service>, /usr/bin/systemctl restart <frontend-service>' \
  | sudo tee /etc/sudoers.d/deploy-update-<dominio>
sudo visudo -c   # valida sintaxis antes de confiar en el archivo

# 2. copiar el script fuera de source/ (donde vive el runtime, no el checkout de git)
mkdir -p /opt/apps/<dominio>/scripts
cp /opt/apps/<dominio>/source/scripts/apply-update.sh /opt/apps/<dominio>/scripts/
chmod +x /opt/apps/<dominio>/scripts/apply-update.sh

# 3. agregar al backend/.env (el de runtime, NO el de source/backend)
cat >> /opt/apps/<dominio>/backend/.env <<EOF
UPDATE_APP_DIR=/opt/apps/<dominio>
UPDATE_BACKEND_SERVICE=<backend-service>
UPDATE_FRONTEND_SERVICE=<frontend-service>
EOF

sudo systemctl restart <backend-service>

Importante: el script (scripts/apply-update.sh) hace git reset --hard sobre source/ mientras corre — por eso tiene que ejecutarse SIEMPRE desde la copia en $UPDATE_APP_DIR/scripts/, nunca desde dentro de source/scripts/ directamente. Cada vez que el script cambie en un release, hay que repetir el paso 2 (copiarlo de nuevo) en un deploy manual — el propio update automático no se autoactualiza a sí mismo.

13. Limpiar archivos .md del source

find /opt/apps/project.linkedcorp.net/source -type f -iname '*.md' -delete

Pendiente al 2026-09-06: no ejecutado en el primer deploy (bloqueado por el entorno del agente que hizo el despliegue). Ejecutar manualmente o en el proximo deploy.


Actualizaciones (deploys posteriores)

  1. Cambios en desarrollo, npm run build local OK.
  2. Si corresponde, subir version (VERSIONADO.md): actualizar VERSION y CHANGELOG.md.
  3. git add . && git commit -m "..." && git push origin main.
  4. ssh deploy@192.168.222.3 -p 2203
  5. cd /opt/apps/project.linkedcorp.net/source && git fetch origin main && git reset --hard origin/main
  6. Si cambio el backend:
    cd backend && npm install --omit=dev
    cp -r node_modules /opt/apps/project.linkedcorp.net/backend/
    
  7. Si cambio el frontend:
    cd ../frontend && npm install && npm run build
    rm -rf /opt/apps/project.linkedcorp.net/frontend/dist
    cp -r dist /opt/apps/project.linkedcorp.net/frontend/dist
    
  8. Si cambio el schema de BD:
    cd ../backend
    set -a && source /opt/apps/project.linkedcorp.net/backend/.env && set +a
    node src/scripts/migrate-db.js
    
  9. Confirmar DB_HOST=192.168.222.32 en el .env de produccion antes de reiniciar.
  10. Reiniciar servicios:
    sudo systemctl restart project-linkedcorp-backend
    sudo systemctl restart project-linkedcorp-frontend
    
  11. Confirmar cambio de PID (si cambio el backend):
    ps -ef | grep 'node src/server.js' | grep -v grep
    
  12. Verificar: curl http://127.0.0.1:4019/health.
  13. Limpiar .md: find /opt/apps/project.linkedcorp.net/source -type f -iname '*.md' -delete.

No tocar durante deploy

  • /opt/apps/project.linkedcorp.net/backend/.env
  • /opt/apps/project.linkedcorp.net/storage/
  • /opt/apps/project.linkedcorp.net/logs/

Notas

  • .env de produccion nunca se versiona ni se copia desde desarrollo.
  • BD de produccion siempre 192.168.222.32; desarrollo siempre 192.168.222.20. Confirmar antes de cada deploy.
  • create-admin.js es idempotente por email (ON DUPLICATE KEY UPDATE) — reutilizable para resetear la clave del admin si hace falta (genera una nueva clave fuerte cada vez que se corre).