Ir al contenido
Q
QuoteNode

Installation

Instalar en un servidor público Ubuntu

Despliega QuoteNode en un servidor Ubuntu público con dominio, HTTPS, SMTP, backups y firewall básico.

Instalar en un servidor público Ubuntu

Usa esta ruta para un despliegue en producción accesible por los clientes a través de un dominio público.

Cuándo usarlo

  • Los clientes externos deben abrir enlaces públicos de oferta.
  • Los mensajes de correo deben contener enlaces funcionales.
  • Quieres control directo sobre el servidor en lugar de una capa PaaS.

Qué no funcionará sin la configuración correcta

  • Los enlaces públicos fallan si DNS no apunta al servidor.
  • Los enlaces públicos fallan si la URL del navegador difiere de la configuración CORS.
  • La emisión del certificado HTTPS falla si los puertos 80/443 están bloqueados.
  • Los enlaces de correo fallan si SMTP falta o si los mensajes son rechazados por el proveedor de correo del destinatario.
  • Los despliegues con IP doméstica dinámica necesitan DDNS y reenvío de puertos del router; un VPS suele ser más sencillo.

Requisitos previos

  • Servidor Ubuntu LTS o VPS.
  • Registro DNS público, por ejemplo crm.example.com, apuntando al servidor.
  • Puertos 80 y 443 abiertos desde internet.
  • Docker Engine 24.0+ y Docker Compose v2.
  • Cuenta SMTP para la entrega de correo.
  • Al menos 4 GB de RAM y 20 GB de espacio libre en disco (recomendados para producción).
  • Destino de backup y un procedimiento de restauración.

Verifica Docker:

docker --version        # Should show 24.0+
docker compose version  # Should show v2.x

Paso 1 — Crear un directorio de proyecto

mkdir quotenode && cd quotenode

Paso 2 — Crear el archivo de configuración

Crea un archivo llamado .env. Reemplaza crm.example.com con tu dominio real:

# Database
DB_URL=jdbc:postgresql://postgres:5432/quotenode
DB_USERNAME=quotenode
DB_PASSWORD=change-me-to-something-random-32-chars
DB_NAME=quotenode

# ============================================================
# SECURITY SECRETS — UNIQUE to this installation.
# SAVE THIS FILE and keep a secure backup.
# ============================================================
DB_ENCRYPTION_KEY=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
TIMING_TOKEN_SECRET=change-me-timing-secret-min-32-chars
PUBLIC_LINK_PASSWORD_SESSION_SECRET=change-me-session-secret-min-32

# Public domain — replace with your real domain
CORS_ALLOWED_ORIGINS=https://crm.example.com
DOMAIN=crm.example.com

# Email delivery
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USERNAME[email protected]
SMTP_PASSWORD=your-smtp-password
SMTP_AUTH=true
SMTP_STARTTLS=true

# Notification preference links (must match your public domain)
NOTIFICATIONS_PUBLIC_PREFERENCES_URL=https://crm.example.com/notifications/preferences

# La IP del cliente se detecta automáticamente tras proxies internos y CDNs (incluido Cloudflare) — déjalo vacío.
# Defínelo solo para un proxy inusual cuyo par de transporte sea una dirección PÚBLICA a confiar (IP/CIDR o nombre de host).
SECURITY_TRUSTED_PROXIES=

# Application
LOG_LEVEL=INFO
SPRING_PROFILES_ACTIVE=prod

Haz backup de tu archivo .env antes del primer uso en producción. Guárdalo en un gestor de contraseñas o en una caja fuerte física. El DB_ENCRYPTION_KEY es crítico — perderlo significa que los datos cifrados desaparecen para siempre.

Alternativa SMTP: Puedes omitir las variables SMTP_* del .env y configurar el correo más tarde en Configuración > SMTP de correo dentro de QuoteNode. El panel de administración almacena la contraseña SMTP cifrada con DB_ENCRYPTION_KEY, manteniéndola fuera de tu archivo .env.

Paso 3 — Crear el archivo Docker Compose

Crea un archivo llamado docker-compose.yml:

services:
  postgres:
    image: postgres:18-alpine
    cpus: 4.0
    mem_limit: 512m
    environment:
      POSTGRES_DB: ${DB_NAME}
      POSTGRES_USER: ${DB_USERNAME}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      PGDATA: /var/lib/postgresql/data   # required for the postgres:18 image
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${DB_USERNAME}"]
      interval: 10s
      timeout: 5s
      retries: 10
    restart: unless-stopped

  gotenberg:
    image: gotenberg/gotenberg:8
    cpus: 2.0
    mem_limit: 448m
    environment:
      LOG_LEVEL: info
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://localhost:3000/health"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped

  backend:
    image: ghcr.io/lesisty7/quotenode/quotenode-api:latest
    cpus: 4.0
    mem_limit: 1792m
    depends_on:
      postgres: { condition: service_healthy }
      gotenberg: { condition: service_healthy }
    env_file: .env
    environment:
      SPRING_PROFILES_ACTIVE: prod
      JOBS_MODE: web
      PDF_ENABLED: "true"
      PDF_GOTENBERG_URL: http://gotenberg:3000
    volumes:
      - backend_uploads:/app/data/uploads
      - backend_pdfs:/app/data/pdfs
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://localhost:8080/health"]
      interval: 15s
      timeout: 10s
      retries: 5
      start_period: 45s
    restart: unless-stopped

  frontend:
    image: ghcr.io/lesisty7/quotenode/quotenode-frontend:latest
    cpus: 2.0
    mem_limit: 192m
    depends_on:
      backend: { condition: service_healthy }
    ports:
      - "80:80"
      - "443:443"
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://localhost:80/"]
      interval: 15s
      timeout: 5s
      retries: 3
    restart: unless-stopped

volumes:
  postgres_data:
  backend_uploads:
  backend_pdfs:

Paso 4 — Configurar el firewall

Abre solo lo necesario:

ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable

No expongas PostgreSQL públicamente. Se queda en la red Docker.

Paso 5 — Iniciar QuoteNode

docker compose up -d

Observa el inicio:

docker compose logs -f backend

Espera hasta ver Started QuoteNodeApplication. El contenedor frontend (Caddy) obtendrá automáticamente un certificado Let’s Encrypt para tu dominio.

Paso 6 — Abrir QuoteNode

Navega a https://crm.example.com en tu navegador.

Credenciales de acceso por defecto:

CampoValor
Email[email protected]
ContraseñaAdmin123!

Cambia la contraseña por defecto inmediatamente tras iniciar sesión.

Comprobaciones post-despliegue

  1. Iniciar sesión y cambiar la contraseña admin.
  2. Crear una oferta de prueba.
  3. Generar un PDF.
  4. Crear y abrir un enlace público desde otro dispositivo.
  5. Si SMTP está configurado, enviar una notificación de prueba y verificar que los enlaces del correo funcionan.

¿Qué está ejecutándose?

ContenedorQué haceUso de RAM
postgresAlmacena todos tus datos~256 MB
backendServidor API Java, lógica de negocio~512 MB – 1,5 GB
gotenbergConvierte HTML a PDF (basado en Chromium)~200 MB
frontendSirve la interfaz web + reverse proxy (Caddy con auto-HTTPS)~20 MB

Total: aproximadamente 1,5 – 2,5 GB de RAM.

Comandos habituales

# Check service status
docker compose ps

# View logs
docker compose logs -f backend

# Stop QuoteNode
docker compose down

# Update to the latest version
docker compose pull && docker compose up -d

Lista de verificación de actualización

Antes de cada actualización:

  1. Confirmar la versión actual de la aplicación en el área de administración.
  2. Hacer backup de .env.
  3. Ejecutar o verificar un backup fresco de la base de datos.
  4. Descargar las nuevas imágenes y reiniciar.
  5. Comprobar la salud del backend, inicio de sesión, generación de PDF y un enlace público de oferta.

Mantener seguros tus secretos

SecretoQué protegeSi se pierde
DB_PASSWORDAcceso a la base de datosRecuperable — reiniciar vía herramientas de administración PostgreSQL
DB_ENCRYPTION_KEYCódigos MFA, contraseña SMTP, clave API FX, campos PIIPermanentemente ilegible
TIMING_TOKEN_SECRETTokens anti-timing-attackRegenerar — los usuarios se re-autentican
PUBLIC_LINK_PASSWORD_SESSION_SECRETSesiones de enlaces públicosRegenerar — las sesiones activas expiran

Guarda .env en un gestor de contraseñas (1Password, Bitwarden). Para máxima seguridad, imprime los secretos y guarda la copia impresa en una caja fuerte física. Nunca hagas commit de .env en el control de versiones.

Recuperación si se pierde .env

Si pierdes tu archivo .env pero tienes una copia de seguridad de base de datos no cifrada (el modo por defecto):

  1. Crea un nuevo .env con nuevos secretos.
  2. Restaura la base de datos desde tu copia de seguridad.
  3. Todos los datos de negocio serán accesibles.
  4. Perdidos: códigos MFA (los usuarios se vuelven a registrar), contraseña SMTP (volver a introducir), clave API FX (volver a introducir). Si ENCRYPT_PII=true estaba habilitado, los datos de clientes cifrados también se pierden.

Last reviewed: Recently