Ir al contenido
Q
QuoteNode

Installation

Instalar con Portainer, QNAP o NAS

Despliega QuoteNode en un NAS o en un host Docker gestionado por Portainer con instrucciones de configuración completas.

Instalar con Portainer, QNAP o NAS

Usa esta ruta si ejecutas Docker a través de Portainer, QNAP Container Station, Synology o una plataforma similar. La interfaz exacta difiere según el fabricante, pero el stack Docker Compose subyacente es el mismo.

Cuándo usarlo

  • Ya operas stacks Docker a través de una interfaz de gestión de contenedores.
  • Entiendes cómo la plataforma mapea volúmenes y puertos.
  • Puedes verificar backups fuera de la interfaz del NAS.

Qué puede no funcionar

  • Los enlaces públicos no funcionan fuera de la LAN a menos que NAT, DNS, proxy y HTTPS estén configurados.
  • Los modos de suspensión del NAS pueden interrumpir el servicio.
  • Algunas UIs Docker de NAS reescriben archivos compose o variables de entorno; verifica el stack renderizado antes de confiar en él.
  • Los backups almacenados solo en el mismo NAS no protegen contra un fallo del NAS.

Requisitos previos

  • Soporte de Docker Compose v2 en tu plataforma.
  • Soporte de volúmenes persistentes para datos PostgreSQL, subidas, PDFs y backups.
  • Al menos 2 GB de RAM disponibles y 10 GB de espacio libre en disco.
  • Una URL estable: IP de red local para uso interno, o dominio público detrás de un proxy inverso para enlaces de clientes.

Paso 1 — Crear el archivo de configuración

Crea un archivo .env (o define variables a través de la interfaz de entorno de tu plataforma). Reemplaza la URL con tu dirección NAS real o dominio público:

Para un despliegue solo NAS interno:

# 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

# Internal NAS URL
CORS_ALLOWED_ORIGINS=http://nas.local
DOMAIN=nas.local

# 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

Para un dominio público detrás de un proxy inverso:

CORS_ALLOWED_ORIGINS=https://crm.example.com
DOMAIN=crm.example.com

Guarda tu .env inmediatamente. Si pierdes DB_ENCRYPTION_KEY, los campos cifrados quedan permanentemente ilegibles.

Paso 2 — Crear el stack Docker Compose

Usa el editor de stacks en Portainer o en la interfaz Docker de tu NAS, o crea un archivo 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:

Conflictos de puertos: Si tu NAS ya usa el puerto 80 o 443, cambia el lado izquierdo del mapeo ports (ej. "8080:80") y actualiza CORS_ALLOWED_ORIGINS en consecuencia (ej. http://nas.local:8080).

Paso 3 — Desplegar y verificar

Inicia el stack a través de la interfaz de tu plataforma o vía SSH:

docker compose up -d
docker compose logs -f backend

Espera hasta ver Started QuoteNodeApplication.

Paso 4 — Abrir QuoteNode

Navega a tu URL del NAS (ej. http://nas.local o https://crm.example.com).

Credenciales de acceso por defecto:

CampoValor
Email[email protected]
ContraseñaAdmin123!

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

Lista de verificación de persistencia

Verifica que estos elementos estén mapeados a volúmenes persistentes (no a almacenamiento efímero del contenedor):

DatoPor qué importa
PostgreSQL dataBase de datos principal de la aplicación
UploadsImágenes de producto, logos, adjuntos
Generated PDFsArchivos de ofertas y documentos
BackupsArchivos de backup locales (si el worker de backup está habilitado)
GeoIP databaseDatos opcionales de control de acceso

¿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~20 MB

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

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 backups de .env fuera del NAS. Un fallo del NAS que destruya tu única copia de DB_ENCRYPTION_KEY hace los datos cifrados irrecuperables.

Siguientes pasos recomendados

  • Configura backups en una ubicación fuera del NAS.
  • Prueba la generación de PDF después del primer despliegue.
  • Si quieres una ruta de despliegue público más sencilla, considera Coolify en un VPS.

Last reviewed: Recently