Przejdź do treści
Q
QuoteNode

Installation

Instalacja na lokalnym laptopie

Uruchom QuoteNode lokalnie w celu ewaluacji, bez udostępniania klientom.

Instalacja na lokalnym laptopie

Wybierz tę ścieżkę, gdy chcesz wypróbować QuoteNode na jednym komputerze. To najszybszy sposób na ewaluację aplikacji, ale nie jest to wdrożenie dostępne dla klientów.

Kiedy użyć

  • Chcesz uruchomić demo lub instancję próbną.
  • Testujesz tworzenie ofert, PDF-y, szablony, produkty i ustawienia.
  • Nie potrzebujesz, aby klienci otwierali publiczne linki do ofert z innego urządzenia.

Co nie zadziała

  • Publiczne linki do ofert generowane jako http://localhost/... działają tylko na tym samym laptopie.
  • Linki w e-mailach nie będą użyteczne, bo odbiorcy nie mogą otworzyć localhost ze swoich maszyn.
  • HTTPS nie jest normalnie konfigurowany w tej topologii.
  • Laptop musi być włączony, a Docker uruchomiony.

Wymagania

  • Docker Desktop lub Docker Engine z Docker Compose v2.
  • Co najmniej 2,5 GB RAM dostępne dla stacku.
  • Co najmniej 10 GB wolnego miejsca na dysku.

Sprawdź konfigurację:

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

Krok 1 — Utwórz katalog projektu

mkdir quotenode && cd quotenode

Krok 2 — Utwórz plik konfiguracyjny

Utwórz plik .env z minimalnymi wymaganymi ustawieniami. Wygeneruj własne sekrety — nie używaj wartości zastępczych w produkcji:

# 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

# IP klienta jest wykrywane automatycznie za wewnętrznymi proxy i CDN (w tym Cloudflare) — zostaw puste.
# Ustaw tylko dla nietypowego proxy, którego peer transportowy ma adres PUBLICZNY do zaufania (IP/CIDR lub nazwa hosta).
SECURITY_TRUSTED_PROXIES=

# Application
LOG_LEVEL=INFO
SPRING_PROFILES_ACTIVE=prod

Zapisz plik .env natychmiast. DB_ENCRYPTION_KEY szyfruje wrażliwe dane. Jeśli go stracisz, zaszyfrowane pola (kody MFA, hasło SMTP, klucze API) staną się trwale nieczytelne. Skopiuj ten plik w bezpieczne miejsce.

Krok 3 — Utwórz plik Docker Compose

Utwórz plik 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:

Krok 4 — Uruchom QuoteNode

docker compose up -d

Docker pobierze obrazy kontenerów (za pierwszym razem zajmie to kilka minut). Obserwuj postęp:

docker compose logs -f backend

Poczekaj aż zobaczysz Started QuoteNodeApplication — to oznacza, że backend jest gotowy.

Krok 5 — Otwórz QuoteNode

Przejdź do http://localhost w przeglądarce.

Domyślne dane logowania:

PoleWartość
Email[email protected]
HasłoAdmin123!

Zmień domyślne hasło natychmiast po zalogowaniu (Settings > My Profile > Change Password).

Co działa?

Po docker compose up masz 4 kontenery:

KontenerFunkcjaUżycie RAM
postgresPrzechowuje wszystkie dane~256 MB
backendSerwer API Java, logika biznesowa~512 MB – 1,5 GB
gotenbergKonwersja HTML do PDF (oparty na Chromium)~200 MB
frontendSerwuje UI + reverse proxy~20 MB

Łącznie: około 1,5 – 2,5 GB RAM.

Przydatne polecenia

# 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

Bezpieczeństwo sekretów

Plik .env zawiera sekrety kryptograficzne unikalne dla tej instalacji:

SekretCo chroniJeśli utracony
DB_PASSWORDDostęp do bazy danychOdzyskiwalny — reset przez narzędzia admin PostgreSQL
DB_ENCRYPTION_KEYKody MFA, hasło SMTP, klucz API FX, pola PII przy ENCRYPT_PII=trueTrwale nieczytelny — nie da się odszyfrować bez oryginalnego klucza
TIMING_TOKEN_SECRETTokeny anty-timing-attackRegenerowalny — użytkownicy logują się ponownie
PUBLIC_LINK_PASSWORD_SESSION_SECRETSesje linków publicznychRegenerowalny — aktywne sesje wygasają

Krytyczny sekret to DB_ENCRYPTION_KEY. Wszystkie inne sekrety można zregenerować z niewielkim utrudnieniem. Ale DB_ENCRYPTION_KEY szyfruje dane — utrata oznacza, że te pola przepadają na zawsze.

Odzyskiwanie po utracie .env

Jeśli stracisz .env, ale masz niezaszyfrowaną kopię zapasową bazy (domyślny tryb):

  1. Utwórz nowy .env z nowymi sekretami.
  2. Przywróć bazę z kopii zapasowej.
  3. Wszystkie dane biznesowe (klienci, oferty, produkty, użytkownicy) będą dostępne.
  4. Utracone: kody MFA (użytkownicy rejestrują się ponownie), hasło SMTP (wprowadź ponownie), klucz API FX. Jeśli ENCRYPT_PII=true było włączone, dane klientów też przepadają.

Kopie zapasowe

Ta konfiguracja jednokontenerowa wykonuje zaplanowane kopie zapasowe wewnątrz procesu backendu (JOBS_MODE: all), więc nie potrzebujesz osobnego kontenera backup-worker. Sama kopia działa jako potok powłoki (pg_dump → kompresja → szyfrowanie) poza JVM, więc jej koszt pamięciowy jest niewielki — dlatego backend na laptopie ma rozmiar 1280m, a nie 1g.

Jest to akceptowalne dla laptopa lub instancji ewaluacyjnej. We wdrożeniu produkcyjnym uruchom dedykowany kontener backup-only (JOBS_MODE: backup-only) obok backendu webowego (JOBS_MODE: web), aby kopie zapasowe nigdy nie konkurowały o pamięć z ruchem webowym. Zobacz Kopie zapasowe i odzyskiwanie.

Przejście z laptopa na serwer

Nie publikuj linków laptopowych klientom. Gdy będziesz gotowy na współdzielone lub publiczne wdrożenie, wybierz jedną ze ścieżek:

Last reviewed: Recently