Przejdź do treści
Q
QuoteNode

Instalacja

Instalacja na publicznym serwerze Ubuntu

Wdrożenie QuoteNode na publicznym serwerze Ubuntu z domeną, HTTPS, SMTP, kopiami zapasowymi i podstawami zapory sieciowej.

Instalacja na publicznym serwerze Ubuntu

Użyj tej ścieżki dla wdrożenia produkcyjnego dostępnego przez publiczną domenę dla klientów.

Kiedy warto zastosować

  • Zewnętrzni klienci muszą otwierać publiczne linki do ofert.
  • Wiadomości e-mail powinny zawierać działające linki.
  • Chcesz mieć bezpośrednią kontrolę nad serwerem zamiast korzystać z warstwy PaaS.

Co nie będzie działać bez odpowiedniej konfiguracji

  • Publiczne linki nie działają, jeśli DNS nie wskazuje na serwer.
  • Publiczne linki nie działają, jeśli adres URL przeglądarki różni się od konfiguracji CORS.
  • Wydanie certyfikatu HTTPS nie powiedzie się, jeśli porty 80/443 są zablokowane.
  • Linki e-mail nie działają, jeśli brakuje SMTP lub jeśli wiadomości są odrzucane przez dostawcę poczty odbiorcy.
  • Wdrożenia z dynamicznym domowym IP wymagają DDNS i przekierowania portów w routerze; VPS jest zazwyczaj prostszy.

Wymagania wstępne

  • Serwer Ubuntu LTS lub VPS.
  • Publiczny rekord DNS, na przykład crm.example.com, wskazujący na serwer.
  • Porty 80 i 443 otwarte z internetu.
  • Docker Engine 24.0+ i Docker Compose v2.
  • Konto SMTP do dostarczania poczty e-mail.
  • Co najmniej 4 GB RAM i 20 GB wolnego miejsca na dysku (zalecane dla produkcji).
  • Miejsce docelowe kopii zapasowych i procedura przywracania.

Sprawdź Docker:

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 o nazwie .env. Zastąp crm.example.com swoją prawdziwą domeną:

# 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

# Public domain — replace with your real domain
CORS_ALLOWED_ORIGINS=https://crm.example.com
DOMAIN=crm.example.com

# Email delivery
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USERNAME[email protected]
SMTP_PASSWORD=your-smtp-password
SMTP_AUTH=true
SMTP_STARTTLS=true

# Notification preference links (must match your public domain)
NOTIFICATIONS_PUBLIC_PREFERENCES_URL=https://crm.example.com/notifications/preferences

# 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

Wykonaj kopię zapasową pliku .env przed pierwszym użyciem produkcyjnym. Przechowaj go w menedżerze haseł lub fizycznym sejfie. DB_ENCRYPTION_KEY jest kluczowy — jego utrata oznacza trwałą utratę zaszyfrowanych danych.

Alternatywa dla SMTP: Możesz pominąć zmienne SMTP_* z .env i skonfigurować pocztę e-mail później w Ustawienia > Email SMTP w QuoteNode. Panel administratora przechowuje hasło SMTP zaszyfrowane za pomocą DB_ENCRYPTION_KEY, co eliminuje potrzebę umieszczania go w pliku .env.

Krok 3 — Utwórz plik Docker Compose

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

Krok 4 — Skonfiguruj zaporę sieciową

Otwórz tylko to, co jest potrzebne:

ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable

Nie eksponuj PostgreSQL publicznie. Powinien pozostać w sieci Docker.

Krok 5 — Uruchom QuoteNode

docker compose up -d

Obserwuj start:

docker compose logs -f backend

Poczekaj, aż zobaczysz Started QuoteNodeApplication. Kontener frontend (Caddy) automatycznie uzyska certyfikat Let’s Encrypt dla Twojej domeny.

Krok 6 — Otwórz QuoteNode

Przejdź do https://crm.example.com w przeglądarce.

Domyślne dane logowania:

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

Zmień domyślne hasło natychmiast po zalogowaniu.

Sprawdzenie po wdrożeniu

  1. Zaloguj się i zmień hasło administratora.
  2. Utwórz testową ofertę.
  3. Wygeneruj PDF.
  4. Utwórz i otwórz publiczny link z innego urządzenia.
  5. Jeśli SMTP jest skonfigurowany, wyślij testowe powiadomienie i sprawdź, czy linki w wiadomości e-mail działają.

Co działa w tle?

KontenerCo robiZużycie RAM
postgresPrzechowuje wszystkie dane~256 MB
backendSerwer API Java, logika biznesowa~512 MB – 1,5 GB
gotenbergKonwertuje HTML do PDF (oparty na Chromium)~200 MB
frontendSerwuje interfejs + reverse proxy (Caddy z auto-HTTPS)~20 MB

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

Przydatne polecenia

# 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

Lista kontrolna aktualizacji

Przed każdą aktualizacją:

  1. Potwierdź bieżącą wersję aplikacji w panelu administracyjnym.
  2. Wykonaj kopię zapasową .env.
  3. Uruchom lub zweryfikuj świeżą kopię zapasową bazy danych.
  4. Pobierz nowe obrazy i uruchom ponownie.
  5. Sprawdź stan backendu, logowanie, generowanie PDF i publiczny link do oferty.

Bezpieczeństwo sekretów

SekretCo chroniW przypadku utraty
DB_PASSWORDDostęp do bazy danychMożliwy do odzyskania — zresetuj przez narzędzia admin PostgreSQL
DB_ENCRYPTION_KEYKody MFA, hasło SMTP, klucz FX API, pola PIITrwale nieczytelne
TIMING_TOKEN_SECRETTokeny anty-timing-attackZregeneruj — użytkownicy ponownie się uwierzytelniają
PUBLIC_LINK_PASSWORD_SESSION_SECRETSesje publicznych linkówZregeneruj — aktywne sesje wygasają

Przechowuj .env w menedżerze haseł (1Password, Bitwarden). Dla maksymalnego bezpieczeństwa wydrukuj sekrety i przechowuj wydruk w fizycznym sejfie. Nigdy nie commituj .env do systemu kontroli wersji.

Odzyskiwanie po utracie .env

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

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

Last reviewed: Recently