Installation
Installare su un server Linux LAN
Esegui QuoteNode su un server Linux interno per un ufficio o un team solo VPN.
Installare su un server Linux LAN
Usa questo percorso quando QuoteNode deve girare su un server Linux interno, VM o mini-PC raggiungibile dalla rete dell’ufficio o dalla VPN.
Quando usarlo
- Più utenti interni necessitano di un’istanza condivisa stabile.
- L’accesso da parte di clienti pubblici non è richiesto.
- Preferisci un host Linux a Docker Desktop.
Cosa non funzionerà
- I link pubblici delle offerte funzionano solo per gli utenti che possono raggiungere l’indirizzo del server.
- La consegna email può funzionare con SMTP, ma i destinatari al di fuori della LAN non possono aprire i link interni.
- L’HTTPS interno con certificato self-signed può mostrare avvisi del browser a meno che la tua organizzazione non consideri attendibile l’autorità di certificazione.
Prerequisiti
- Ubuntu, Debian o un’altra distribuzione Linux mantenuta.
- Docker Engine 24.0+ e Docker Compose v2.
- Un IP statico o una prenotazione DHCP per il server.
- Accesso SSH per gli operatori.
- Almeno 2 GB di RAM e 10 GB di spazio libero su disco.
- Storage di backup al di fuori del volume Docker principale.
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. Sostituisci 192.168.1.20 con l’IP LAN reale del tuo server o il nome DNS interno (es. 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
# 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
Se deployi dietro un reverse proxy interno con HTTPS, usa invece l’origine HTTPS:
CORS_ALLOWED_ORIGINS=https://crm.internal.example
DOMAIN=crm.internal.example
Salva il tuo file
.envimmediatamente. Conserva una copia al di fuori di questo server. Se perdiDB_ENCRYPTION_KEY, i campi cifrati diventano permanentemente illeggibili.
Passo 3 — Creare il file Docker Compose
Crea un file chiamato 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:
Passo 4 — Avviare QuoteNode
docker compose up -d
Docker scaricherà le immagini al primo avvio. Monitora il lancio:
docker compose logs -f backend
Attendi di vedere Started QuoteNodeApplication.
Passo 5 — Aprire QuoteNode
Naviga su http://192.168.1.20 (o l’indirizzo del tuo server) da qualsiasi dispositivo sulla LAN.
Credenziali di accesso predefinite:
| Campo | Valore |
|---|---|
[email protected] | |
| Password | Admin123! |
Cambia la password predefinita immediatamente dopo aver effettuato l’accesso.
Cosa è in esecuzione?
| 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 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
Mantenere al sicuro i tuoi segreti
| 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, campi PII | Permanentemente illeggibile |
TIMING_TOKEN_SECRET | Token anti-timing-attack | Rigenera — gli utenti si ri-autenticano |
PUBLIC_LINK_PASSWORD_SESSION_SECRET | Sessioni dei link pubblici | Rigenera — le sessioni attive scadono |
Il segreto critico è
DB_ENCRYPTION_KEY. Conserva backup di.enval di fuori di questo server. Vedi Risoluzione dei problemi di installazione per i passaggi di ripristino.
Passi successivi consigliati
- Configura backup pianificati e testa un ripristino.
- Testa la generazione PDF dopo il primo deployment.
- Usa Server pubblico Ubuntu o Coolify quando i link pubblici delle offerte devono funzionare per i clienti.