Installation
Auf einem lokalen Laptop installieren
QuoteNode lokal zur Evaluierung ausführen, ohne es für Kunden zugänglich zu machen.
Auf einem lokalen Laptop installieren
Verwenden Sie diesen Pfad, wenn Sie QuoteNode auf einem Computer ausprobieren möchten. Es ist der schnellste Weg, die Anwendung zu evaluieren, aber keine kundenseitige Bereitstellung.
Wann Sie diesen Pfad verwenden
- Sie möchten eine Demo- oder Testinstanz.
- Sie testen Angebotserstellung, PDFs, Vorlagen, Produkte und Einstellungen.
- Kunden müssen keine öffentlichen Angebotslinks von einem anderen Gerät öffnen.
Was nicht funktionieren wird
- Öffentliche Angebotslinks, die als
http://localhost/...generiert werden, funktionieren nur auf demselben Laptop. - E-Mail-Links sind meist nicht nützlich, weil Empfänger
localhostnicht von ihren Geräten öffnen können. - HTTPS ist für diese Topologie normalerweise nicht konfiguriert.
- Der Laptop muss eingeschaltet sein und Docker muss laufen.
Voraussetzungen
- Docker Desktop oder Docker Engine mit Docker Compose v2.
- Mindestens 2,5 GB RAM, die für den Stack verfügbar sind.
- Mindestens 10 GB freier Festplattenspeicher.
Überprüfen Sie Ihre Konfiguration:
docker --version # Should show 24.0+
docker compose version # Should show v2.x
Schritt 1 — Projektverzeichnis erstellen
mkdir quotenode && cd quotenode
Schritt 2 — Konfigurationsdatei erstellen
Erstellen Sie eine Datei namens .env mit den minimalen Pflichteinstellungen. Generieren Sie Ihre eigenen Secrets — verwenden Sie die Platzhalterwerte nicht in der Produktion:
# 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
# Die Client-IP wird hinter internen Proxys und CDNs (auch Cloudflare) automatisch erkannt — leer lassen.
# Nur für ein ungewöhnliches Proxy setzen, dessen Transport-Peer eine ÖFFENTLICHE Adresse ist (IP/CIDR oder Hostname).
SECURITY_TRUSTED_PROXIES=
# Application
LOG_LEVEL=INFO
SPRING_PROFILES_ACTIVE=prod
Speichern Sie Ihre
.env-Datei sofort. DerDB_ENCRYPTION_KEYverschlüsselt sensible Daten im Ruhezustand. Wenn Sie ihn verlieren, werden verschlüsselte Felder (MFA-Codes, SMTP-Passwort, API-Schlüssel) dauerhaft unlesbar. Kopieren Sie diese Datei an einen sicheren Ort.
Schritt 3 — Docker-Compose-Datei erstellen
Erstellen Sie eine Datei namens 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:
Schritt 4 — QuoteNode starten
docker compose up -d
Docker lädt die Container-Images herunter (beim ersten Start dauert das einige Minuten). Beobachten Sie den Startvorgang:
docker compose logs -f backend
Warten Sie, bis Sie Started QuoteNodeApplication sehen — das bedeutet, dass das Backend bereit ist.
Schritt 5 — QuoteNode öffnen
Navigieren Sie zu http://localhost in Ihrem Browser.
Standard-Anmeldedaten:
| Feld | Wert |
|---|---|
[email protected] | |
| Passwort | Admin123! |
Ändern Sie das Standardpasswort sofort nach dem Einloggen (Einstellungen > Mein Profil > Passwort ändern).
Was läuft gerade?
Nach docker compose up laufen 4 Container:
| Container | Aufgabe | RAM-Verbrauch |
|---|---|---|
postgres | Speichert alle Ihre Daten | ~256 MB |
backend | Java-API-Server, Geschäftslogik | ~512 MB – 1,5 GB |
gotenberg | Konvertiert HTML zu PDF (Chromium-basiert) | ~200 MB |
frontend | Stellt die Web-UI bereit + Reverse Proxy | ~20 MB |
Gesamt: ungefähr 1,5 – 2,5 GB RAM.
Häufige Befehle
# 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
Secrets sicher aufbewahren
Ihre .env-Datei enthält kryptografische Secrets, die einzigartig für Ihre Installation sind:
| Secret | Was es schützt | Bei Verlust |
|---|---|---|
DB_PASSWORD | Datenbankzugang | Wiederherstellbar — über PostgreSQL-Admintool zurücksetzen |
DB_ENCRYPTION_KEY | MFA-Codes, SMTP-Passwort, FX-API-Schlüssel und alle PII-Felder wenn ENCRYPT_PII=true | Dauerhaft unlesbar — ohne den Originalschlüssel nicht entschlüsselbar |
TIMING_TOKEN_SECRET | Anti-Timing-Angriff-Tokens | Neu generieren — bestehende Tokens ungültig, Benutzer authentifizieren sich neu |
PUBLIC_LINK_PASSWORD_SESSION_SECRET | Sitzungen für öffentliche Links | Neu generieren — aktive Sitzungen laufen ab, Links funktionieren weiterhin |
Das kritische Secret ist
DB_ENCRYPTION_KEY. Alle anderen Secrets können mit kleinen Umständen neu generiert werden. AberDB_ENCRYPTION_KEYverschlüsselt Daten im Ruhezustand — sein Verlust bedeutet, dass diese Felder für immer weg sind.
Wiederherstellung bei Verlust von .env
Wenn Sie Ihre .env-Datei verlieren, aber ein unverschlüsseltes Datenbank-Backup haben (der Standard-Backup-Modus):
- Erstellen Sie eine neue
.envmit neuen Secrets. - Stellen Sie die Datenbank aus Ihrem Backup wieder her.
- Alle Geschäftsdaten (Kunden, Angebote, Produkte, Benutzer) sind vollständig zugänglich.
- Nur wenige Felder gehen verloren: MFA-Codes (Benutzer registrieren sich erneut), SMTP-Passwort (in den Einstellungen neu eingeben), FX-API-Schlüssel (in den Einstellungen neu eingeben). Wenn
ENCRYPT_PII=trueaktiviert war, gehen auch verschlüsselte Kundendaten verloren.
Backups
Dieses Setup mit einem einzigen Container führt geplante Backups innerhalb des Backend-Prozesses aus (JOBS_MODE: all), sodass Sie keinen separaten backup-worker-Container benötigen. Das Backup selbst läuft als Shell-Pipeline (pg_dump → Komprimierung → Verschlüsselung) außerhalb der JVM, daher ist sein Speicherbedarf gering — deshalb ist das Backend auf dem Laptop mit 1280m statt 1g dimensioniert.
Das ist für einen Laptop oder eine Evaluierungsinstanz akzeptabel. Für eine Produktionsbereitstellung betreiben Sie einen dedizierten backup-only-Worker-Container (JOBS_MODE: backup-only) neben einem Web-Backend (JOBS_MODE: web), damit Backups nie mit dem Web-Traffic um Speicher konkurrieren. Siehe Backup & Wiederherstellung.
Vom Laptop auf einen Server umziehen
Veröffentlichen Sie keine Laptop-Links für Kunden. Wenn Sie bereit für eine gemeinsame oder öffentliche Bereitstellung sind, wählen Sie einen dieser Pfade: