Ir al contenido
Q
QuoteNode

Installation

Instalar en un portátil local

Ejecuta QuoteNode localmente para evaluación sin exponerlo a clientes.

Instalar en un portátil local

Usa esta ruta cuando quieras probar QuoteNode en un único equipo. Es la forma más rápida de evaluar la aplicación, pero no es un despliegue orientado a clientes.

Cuándo usarlo

  • Quieres una instancia de demo o prueba.
  • Estás probando la creación de ofertas, PDFs, plantillas, productos y ajustes.
  • No necesitas que los clientes abran enlaces públicos de oferta desde otro dispositivo.

Qué no funcionará

  • Los enlaces públicos de oferta generados como http://localhost/... funcionan solo en el mismo portátil.
  • Los enlaces de correo normalmente no son útiles porque los destinatarios no pueden abrir localhost desde sus equipos.
  • HTTPS normalmente no está configurado para esta topología.
  • El portátil debe estar encendido y Docker debe estar en ejecución.

Requisitos previos

  • Docker Desktop o Docker Engine con Docker Compose v2.
  • Al menos 2,5 GB de RAM disponibles para el stack.
  • Al menos 10 GB de espacio libre en disco.

Comprueba tu configuración:

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 con los ajustes mínimos requeridos. Genera tus propios secretos — no uses los valores de ejemplo en producción:

# 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 — READ THIS BEFORE CONTINUING
# These values are UNIQUE to your installation.
# If you lose this file, you CANNOT regenerate the same secrets.
# 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

# Domain (for CORS and Caddy)
CORS_ALLOWED_ORIGINS=http://localhost
DOMAIN=localhost

# 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

Guarda tu archivo .env inmediatamente. El DB_ENCRYPTION_KEY cifra datos sensibles en reposo. Si lo pierdes, los campos cifrados (códigos MFA, contraseña SMTP, claves API) quedarán permanentemente ilegibles. Copia este archivo en un lugar seguro.

Paso 3 — Crear el archivo Docker Compose

Crea un archivo llamado docker-compose.yml:

services:
  postgres:
    image: postgres:18-alpine
    cpus: 2.0
    mem_limit: 384m
    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: 384m
    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: 2.0
    mem_limit: 1280m
    depends_on:
      postgres: { condition: service_healthy }
      gotenberg: { condition: service_healthy }
    env_file: .env
    environment:
      SPRING_PROFILES_ACTIVE: prod
      # Single-container eval (WEB_MAINTENANCE backup profile): the backend runs
      # scheduled backups in-process, so no separate backup-worker container is needed.
      # For production, split into a web backend + a dedicated backup-only worker.
      JOBS_MODE: all
      BACKUP_RUNTIME_PROFILE: WEB_MAINTENANCE
      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: 1.0
    mem_limit: 128m
    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 — Iniciar QuoteNode

docker compose up -d

Docker descargará las imágenes de contenedor (esto tarda unos minutos en el primer arranque). Observa el progreso del inicio:

docker compose logs -f backend

Espera hasta ver Started QuoteNodeApplication — eso significa que el backend está listo.

Paso 5 — Abrir QuoteNode

Navega a http://localhost 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 (Configuración > Mi perfil > Cambiar contraseña).

¿Qué está ejecutándose?

Tras docker compose up, tienes 4 contenedores:

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.

Comandos habituales

# Check if all services are running
docker compose ps

# View logs (all services)
docker compose logs -f

# View logs (backend only)
docker compose logs -f backend

# Stop QuoteNode
docker compose down

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

Mantener seguros tus secretos

Tu archivo .env contiene secretos criptográficos únicos para tu instalación:

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 y todos los campos PII si ENCRYPT_PII=truePermanentemente ilegible — no se puede descifrar sin la clave original
TIMING_TOKEN_SECRETTokens anti-timing-attackRegenerar — tokens existentes invalidados, usuarios se re-autentican
PUBLIC_LINK_PASSWORD_SESSION_SECRETSesiones de enlaces públicosRegenerar — sesiones activas expiran, los enlaces siguen funcionando

El secreto crítico es DB_ENCRYPTION_KEY. Todos los demás secretos se pueden regenerar con una molestia menor. Pero DB_ENCRYPTION_KEY cifra datos en reposo — perderlo significa que esos campos desaparecen para siempre.

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 de copia 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 (clientes, ofertas, productos, usuarios) serán completamente accesibles.
  4. Solo se pierden unos pocos campos: códigos MFA (los usuarios se vuelven a registrar), contraseña SMTP (volver a introducir en ajustes), clave API FX (volver a introducir en ajustes). Si ENCRYPT_PII=true estaba habilitado, los datos de clientes cifrados también se pierden.

Copias de seguridad

Esta configuración de un solo contenedor ejecuta las copias de seguridad programadas dentro del proceso del backend (JOBS_MODE: all), por lo que no necesitas un contenedor backup-worker independiente. La copia en sí se ejecuta como una tubería de shell (pg_dump → compresión → cifrado) fuera de la JVM, así que su coste de memoria es pequeño — por eso el backend en el portátil está dimensionado en 1280m en lugar de 1g.

Esto es aceptable para un portátil o una instancia de evaluación. Para un despliegue en producción, ejecuta un contenedor worker dedicado backup-only (JOBS_MODE: backup-only) junto a un backend web (JOBS_MODE: web) para que las copias de seguridad nunca compitan por la memoria con el tráfico web. Consulta Copia de seguridad y recuperación.

Migrar de portátil a servidor

No publiques enlaces de portátil a clientes. Cuando estés listo para un despliegue compartido o público, elige una de estas rutas:

Last reviewed: Recently