Installation
Instalar en un servidor Linux de red local
Ejecuta QuoteNode en un servidor Linux interno para un equipo de oficina o solo VPN.
Instalar en un servidor Linux de red local
Usa esta ruta cuando QuoteNode deba ejecutarse en un servidor Linux interno, VM o mini-PC accesible desde la red de oficina o VPN.
Cuándo usarlo
- Varios usuarios internos necesitan una instancia compartida estable.
- No se requiere acceso público para clientes.
- Prefieres un host Linux sobre Docker Desktop.
Qué no funcionará
- Los enlaces públicos de oferta funcionan solo para usuarios que pueden alcanzar la dirección del servidor.
- La entrega de correo puede funcionar con SMTP, pero los destinatarios fuera de la red local no pueden abrir enlaces internos.
- El HTTPS interno con certificado autofirmado puede mostrar advertencias del navegador a menos que tu organización confíe en la autoridad certificadora.
Requisitos previos
- Ubuntu, Debian u otra distribución Linux mantenida.
- Docker Engine 24.0+ y Docker Compose v2.
- IP estática o reserva DHCP para el servidor.
- Acceso SSH para operadores.
- Al menos 2 GB de RAM y 10 GB de espacio libre en disco.
- Almacenamiento de backup fuera del volumen principal de Docker.
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. Reemplaza 192.168.1.20 con la IP LAN real de tu servidor o el nombre DNS interno (p. ej. crm.internal):
# 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
# LAN URL — replace with your server IP or internal DNS name
CORS_ALLOWED_ORIGINS=http://192.168.1.20
DOMAIN=192.168.1.20
# 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
Si despliegas detrás de un proxy inverso interno con HTTPS, usa el origen HTTPS en su lugar:
CORS_ALLOWED_ORIGINS=https://crm.internal.example
DOMAIN=crm.internal.example
Guarda tu archivo
.envinmediatamente. Guarda una copia fuera de este servidor. Si pierdesDB_ENCRYPTION_KEY, los campos cifrados quedan permanentemente ilegibles.
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 — Iniciar QuoteNode
docker compose up -d
Docker descargará las imágenes al primer arranque. Observa el inicio:
docker compose logs -f backend
Espera hasta ver Started QuoteNodeApplication.
Paso 5 — Abrir QuoteNode
Navega a http://192.168.1.20 (o la dirección de tu servidor) desde cualquier dispositivo en la red local.
Credenciales de acceso por defecto:
| Campo | Valor |
|---|---|
[email protected] | |
| Contraseña | Admin123! |
Cambia la contraseña por defecto inmediatamente tras iniciar sesión.
¿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.
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
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 |
El secreto crítico es
DB_ENCRYPTION_KEY. Guarda copias de.envfuera de este servidor. Ver Solución de problemas de instalación para los pasos de recuperación.
Siguientes pasos recomendados
- Configura backups programados y prueba una restauración.
- Prueba la generación de PDF después del primer despliegue.
- Usa servidor público Ubuntu o Coolify cuando los enlaces públicos de oferta deban funcionar para clientes.