Vai al contenuto
Q
QuoteNode

Installation

Installare su un laptop locale

Esegui QuoteNode localmente per valutazione senza esporlo ai clienti.

Installare su un laptop locale

Usa questo percorso quando vuoi provare QuoteNode su un unico computer. È il modo più veloce per valutare l’applicazione, ma non è un deployment rivolto ai clienti.

Quando usarlo

  • Vuoi un’istanza demo o di prova.
  • Stai testando la creazione di offerte, i PDF, i template, i prodotti e le impostazioni.
  • Non hai bisogno che i clienti aprano link pubblici delle offerte da un altro dispositivo.

Cosa non funzionerà

  • I link pubblici delle offerte generati come http://localhost/... funzionano solo sullo stesso laptop.
  • I link email di solito non sono utili perché i destinatari non possono aprire localhost dalle loro macchine.
  • HTTPS normalmente non è configurato per questa topologia.
  • Il laptop deve essere acceso e Docker deve essere in esecuzione.

Prerequisiti

  • Docker Desktop o Docker Engine con Docker Compose v2.
  • Almeno 2,5 GB di RAM disponibili per lo stack.
  • Almeno 10 GB di spazio libero su disco.

Controlla la configurazione:

docker --version        # Should show 24.0+
docker compose version  # Should show v2.x

Passo 1 — Creare una directory di progetto

mkdir quotenode && cd quotenode

Passo 2 — Creare il file di configurazione

Crea un file chiamato .env con le impostazioni minime richieste. Genera i tuoi segreti — non usare i valori segnaposto in produzione:

# 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

# 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

Salva il tuo file .env immediatamente. Il DB_ENCRYPTION_KEY cifra i dati sensibili a riposo. Se lo perdi, i campi cifrati (codici MFA, password SMTP, chiavi API) diventano permanentemente illeggibili. Copia questo file in un posto sicuro.

Passo 3 — Creare il file Docker Compose

Crea un file chiamato 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:

Passo 4 — Avviare QuoteNode

docker compose up -d

Docker scaricherà le immagini dei container (al primo avvio ci vogliono alcuni minuti). Monitora l’avanzamento dell’avvio:

docker compose logs -f backend

Attendi di vedere Started QuoteNodeApplication — significa che il backend è pronto.

Passo 5 — Aprire QuoteNode

Naviga su http://localhost nel tuo browser.

Credenziali di accesso predefinite:

CampoValore
Email[email protected]
PasswordAdmin123!

Cambia la password predefinita immediatamente dopo aver effettuato l’accesso (Impostazioni > Il mio profilo > Cambia password).

Cosa è in esecuzione?

Dopo docker compose up, hai 4 container:

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.

Comandi comuni

# 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

Mantenere al sicuro i tuoi segreti

Il tuo file .env contiene segreti crittografici unici per la tua installazione:

SegretoCosa proteggeSe perso
DB_PASSWORDAccesso al databaseRecuperabile — reimposta tramite strumenti di amministrazione PostgreSQL
DB_ENCRYPTION_KEYCodici MFA, password SMTP, chiave API FX e tutti i campi PII se ENCRYPT_PII=truePermanentemente illeggibile — non può essere decifrato senza la chiave originale
TIMING_TOKEN_SECRETToken anti-timing-attackRigenera — token esistenti invalidati, gli utenti si ri-autenticano
PUBLIC_LINK_PASSWORD_SESSION_SECRETSessioni dei link pubbliciRigenera — le sessioni attive scadono, i link continuano a funzionare

Il segreto critico è DB_ENCRYPTION_KEY. Tutti gli altri segreti possono essere rigenerati con un piccolo disagio. Ma DB_ENCRYPTION_KEY cifra i dati a riposo — perderlo significa che quei campi sono andati per sempre.

Ripristino se .env è perso

Se perdi il tuo file .env ma hai un backup del database non cifrato (la modalità di backup predefinita):

  1. Crea un nuovo .env con nuovi segreti.
  2. Ripristina il database dal tuo backup.
  3. Tutti i dati di business (clienti, offerte, prodotti, utenti) saranno completamente accessibili.
  4. Solo pochi campi vengono persi: codici MFA (gli utenti si re-iscrivono), password SMTP (reinserire nelle impostazioni), chiave API FX (reinserire nelle impostazioni). Se ENCRYPT_PII=true era abilitato, anche i dati cliente cifrati vengono persi.

Backup

Questa configurazione a contenitore singolo esegue i backup pianificati all’interno del processo del backend (JOBS_MODE: all), quindi non serve un contenitore backup-worker separato. Il backup stesso viene eseguito come pipeline di shell (pg_dump → compressione → cifratura) fuori dalla JVM, perciò il suo costo di memoria è ridotto — è per questo che il backend sul portatile è dimensionato a 1280m anziché 1g.

È accettabile per un portatile o un’istanza di valutazione. Per un deployment di produzione, esegui un contenitore worker dedicato backup-only (JOBS_MODE: backup-only) accanto a un backend web (JOBS_MODE: web) in modo che i backup non competano mai con il traffico web per la memoria. Consulta Backup e ripristino.

Passare da laptop a server

Non pubblicare link da laptop ai clienti. Quando sei pronto per un deployment condiviso o pubblico, scegli uno di questi percorsi:

Last reviewed: Recently