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:

Campo Valor
Email [email protected]
Contraseña Admin123!

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):

Dato Por qué importa
PostgreSQL data Base de datos principal de la aplicación
Uploads Imágenes de producto, logos, adjuntos
Generated PDFs Archivos de ofertas y documentos
Backups Archivos de backup locales (si el worker de backup está habilitado)
GeoIP database Datos opcionales de control de acceso

¿Qué está ejecutándose?

Contenedor Qué hace Uso de RAM
postgres Almacena todos tus datos ~256 MB
backend Servidor API Java, lógica de negocio ~512 MB – 1,5 GB
gotenberg Convierte HTML a PDF (basado en Chromium) ~200 MB
frontend Sirve la interfaz web + reverse proxy ~20 MB

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

Mantener seguros tus secretos

Secreto Qué protege Si se pierde
DB_PASSWORD Acceso a la base de datos Recuperable — reiniciar vía herramientas de administración PostgreSQL
DB_ENCRYPTION_KEY Códigos MFA, contraseña SMTP, clave API FX, campos PII Permanentemente ilegible
TIMING_TOKEN_SECRET Tokens anti-timing-attack Regenerar — los usuarios se re-autentican
PUBLIC_LINK_PASSWORD_SESSION_SECRET Sesiones de enlaces públicos Regenerar — 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