Vai al contenuto
Q
QuoteNode

Installation

Installare con Portainer, QNAP o NAS

Distribuisci QuoteNode su un NAS o su un host Docker gestito da Portainer con istruzioni di configurazione complete.

Installare con Portainer, QNAP o NAS

Usa questo percorso se esegui Docker tramite Portainer, QNAP Container Station, Synology o una piattaforma simile. L’interfaccia esatta differisce in base al vendor, ma lo stack Docker Compose sottostante è identico.

Quando usarlo

  • Gestisci già stack Docker tramite un’interfaccia di gestione dei container.
  • Capisci come la piattaforma mappa volumi e porte.
  • Puoi verificare i backup al di fuori dell’interfaccia NAS.

Cosa potrebbe non funzionare

  • I link pubblici non funzionano al di fuori della LAN a meno che NAT, DNS, proxy e HTTPS non siano configurati.
  • Le modalità di sospensione del NAS possono interrompere il servizio.
  • Alcune interfacce Docker dei NAS riscrivono file compose o variabili d’ambiente; verifica lo stack renderizzato prima di farvi affidamento.
  • I backup archiviati solo sullo stesso NAS non proteggono contro i guasti del NAS.

Prerequisiti

  • Supporto Docker Compose v2 nella tua piattaforma.
  • Supporto di volumi persistenti per dati PostgreSQL, upload, PDF e backup.
  • Almeno 2 GB di RAM disponibili e 10 GB di spazio libero su disco.
  • Un URL stabile: IP LAN per uso interno, o dominio pubblico dietro un reverse proxy per i link dei clienti.

Passo 1 — Creare il file di configurazione

Crea un file .env (o imposta le variabili tramite l’interfaccia ambiente della tua piattaforma). Sostituisci l’URL con il tuo indirizzo NAS reale o dominio pubblico:

Per un deployment 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

# L'IP del client viene rilevato automaticamente dietro proxy interni e CDN (incluso Cloudflare) — lascia vuoto.
# Imposta solo per un proxy insolito il cui peer di trasporto è un indirizzo PUBBLICO da considerare attendibile (IP/CIDR o hostname).
SECURITY_TRUSTED_PROXIES=

# Application
LOG_LEVEL=INFO
SPRING_PROFILES_ACTIVE=prod

Per un dominio pubblico dietro un reverse proxy:

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

Salva il tuo .env immediatamente. Se perdi DB_ENCRYPTION_KEY, i campi cifrati diventano permanentemente illeggibili.

Passo 2 — Creare lo stack Docker Compose

Usa l’editor di stack in Portainer o nell’interfaccia Docker del tuo NAS, oppure crea un file 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:

Conflitti di porte: Se il tuo NAS usa già la porta 80 o 443, cambia il lato sinistro del mapping ports (es. "8080:80") e aggiorna CORS_ALLOWED_ORIGINS di conseguenza (es. http://nas.local:8080).

Passo 3 — Distribuire e verificare

Avvia lo stack tramite l’interfaccia della piattaforma o via SSH:

docker compose up -d
docker compose logs -f backend

Attendi di vedere Started QuoteNodeApplication.

Passo 4 — Aprire QuoteNode

Naviga al tuo URL NAS (es. http://nas.local o https://crm.example.com).

Credenziali di accesso predefinite:

CampoValore
Email[email protected]
PasswordAdmin123!

Cambia la password predefinita immediatamente dopo aver effettuato l’accesso.

Checklist di persistenza

Verifica che questi elementi siano mappati su volumi persistenti (non su storage effimero del container):

DatoPerché conta
PostgreSQL dataDatabase applicativo principale
UploadsImmagini prodotto, logo, allegati
Generated PDFsFile di offerta e documenti
BackupsArchivi di backup locali (se il worker di backup è abilitato)
GeoIP databaseDati opzionali di controllo accessi

Cosa è in esecuzione?

ContainerCosa faUtilizzo RAM
postgresArchivia tutti i tuoi dati~256 MB
backendServer API Java, logica di business~512 MB – 1,5 GB
gotenbergConverte HTML in PDF (basato su Chromium)~200 MB
frontendServe l’interfaccia web + reverse proxy~20 MB

Totale: circa 1,5 – 2,5 GB di RAM.

Mantenere al sicuro i tuoi segreti

SegretoCosa proteggeSe perso
DB_PASSWORDAccesso al databaseRecuperabile — reimposta tramite strumenti di amministrazione PostgreSQL
DB_ENCRYPTION_KEYCodici MFA, password SMTP, chiave API FX, campi PIIPermanentemente illeggibile
TIMING_TOKEN_SECRETToken anti-timing-attackRigenera — gli utenti si ri-autenticano
PUBLIC_LINK_PASSWORD_SESSION_SECRETSessioni dei link pubbliciRigenera — le sessioni attive scadono

Conserva backup di .env al di fuori del NAS. Un guasto del NAS che distrugge la tua unica copia di DB_ENCRYPTION_KEY rende i dati cifrati irrecuperabili.

Passi successivi consigliati

  • Configura backup in una posizione esterna al NAS.
  • Testa la generazione PDF dopo il primo deployment.
  • Se vuoi un percorso di deployment pubblico più agevole, considera Coolify su un VPS.

Last reviewed: Recently