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
localhostdalle 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
.envimmediatamente. IlDB_ENCRYPTION_KEYcifra 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:
| Campo | Valore |
|---|---|
[email protected] | |
| Password | Admin123! |
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:
| Container | Cosa fa | Utilizzo RAM |
|---|---|---|
postgres | Archivia tutti i tuoi dati | ~256 MB |
backend | Server API Java, logica di business | ~512 MB – 1,5 GB |
gotenberg | Converte HTML in PDF (basato su Chromium) | ~200 MB |
frontend | Serve 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:
| Segreto | Cosa protegge | Se perso |
|---|---|---|
DB_PASSWORD | Accesso al database | Recuperabile — reimposta tramite strumenti di amministrazione PostgreSQL |
DB_ENCRYPTION_KEY | Codici MFA, password SMTP, chiave API FX e tutti i campi PII se ENCRYPT_PII=true | Permanentemente illeggibile — non può essere decifrato senza la chiave originale |
TIMING_TOKEN_SECRET | Token anti-timing-attack | Rigenera — token esistenti invalidati, gli utenti si ri-autenticano |
PUBLIC_LINK_PASSWORD_SESSION_SECRET | Sessioni dei link pubblici | Rigenera — 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. MaDB_ENCRYPTION_KEYcifra 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):
- Crea un nuovo
.envcon nuovi segreti. - Ripristina il database dal tuo backup.
- Tutti i dati di business (clienti, offerte, prodotti, utenti) saranno completamente accessibili.
- 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=trueera 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: