Instalacja
Instalacja za pomocą Portainer, QNAP lub NAS
Wdrożenie QuoteNode na NAS lub hoście Docker zarządzanym przez Portainer z pełnymi instrukcjami konfiguracji.
Instalacja za pomocą Portainer, QNAP lub NAS
Użyj tej ścieżki, jeśli korzystasz z Docker przez Portainer, QNAP Container Station, Synology lub podobną platformę. Dokładny interfejs użytkownika różni się w zależności od dostawcy, ale podstawowy stos Docker Compose jest identyczny.
Kiedy to zastosować
- Już zarządzasz stosami Docker za pośrednictwem interfejsu do zarządzania kontenerami.
- Rozumiesz, jak platforma mapuje woluminy i porty.
- Potrafisz weryfikować kopie zapasowe poza interfejsem NAS.
Co może nie działać
- Publiczne linki nie działają poza siecią LAN, chyba że skonfigurowano NAT, DNS, proxy i HTTPS.
- Tryby uśpienia NAS mogą przerywać działanie usługi.
- Niektóre interfejsy Docker w NAS modyfikują pliki compose lub zmienne środowiskowe; zweryfikuj wyrenderowany stos przed poleganiem na nim.
- Kopie zapasowe przechowywane wyłącznie na tym samym NAS nie chronią przed awarią NAS.
Wymagania wstępne
- Obsługa Docker Compose v2 na Twojej platformie.
- Obsługa woluminów trwałych dla danych PostgreSQL, przesłanych plików, PDF-ów i kopii zapasowych.
- Co najmniej 2 GB RAM dostępnego i 10 GB wolnego miejsca na dysku.
- Stabilny adres URL: adres IP sieci LAN do użytku wewnętrznego lub publiczna domena za reverse proxy dla linków klientów.
Krok 1 — Utwórz plik konfiguracyjny
Utwórz plik .env (lub ustaw zmienne przez interfejs środowiskowy platformy). Zastąp adres URL rzeczywistym adresem NAS lub publiczną domeną:
W przypadku wdrożenia tylko wewnętrznego NAS:
# 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
# Internal NAS URL
CORS_ALLOWED_ORIGINS=http://nas.local
DOMAIN=nas.local
# 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
W przypadku publicznej domeny za reverse proxy:
CORS_ALLOWED_ORIGINS=https://crm.example.com
DOMAIN=crm.example.com
Zapisz plik
.envnatychmiast. Jeśli utraciszDB_ENCRYPTION_KEY, zaszyfrowane pola staną się trwale nieczytelne.
Krok 2 — Utwórz stos Docker Compose
Użyj edytora stosów w Portainer lub interfejsie Docker NAS, albo utwórz plik 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:
Konflikty portów: Jeśli Twój NAS już używa portu 80 lub 443, zmień lewą stronę mapowania
ports(np."8080:80") i odpowiednio zaktualizujCORS_ALLOWED_ORIGINS(np.http://nas.local:8080).
Krok 3 — Wdróż i zweryfikuj
Uruchom stos przez interfejs platformy lub przez SSH:
docker compose up -d
docker compose logs -f backend
Poczekaj, aż zobaczysz Started QuoteNodeApplication.
Krok 4 — Otwórz QuoteNode
Przejdź do adresu URL Twojego NAS (np. http://nas.local lub https://crm.example.com).
Domyślne dane logowania:
| Pole | Wartość |
|---|---|
[email protected] | |
| Hasło | Admin123! |
Zmień domyślne hasło natychmiast po zalogowaniu.
Lista kontrolna trwałości danych
Sprawdź, czy poniższe dane są mapowane na woluminy trwałe (nie na tymczasowy storage kontenera):
| Dane | Dlaczego to ważne |
|---|---|
| PostgreSQL data | Główna baza danych aplikacji |
| Uploads | Zdjęcia produktów, loga, załączniki |
| Generated PDFs | Pliki ofert i dokumentów |
| Backups | Lokalne archiwa kopii zapasowych (jeśli worker kopii zapasowych jest włączony) |
| GeoIP database | Opcjonalne dane kontroli dostępu |
Co działa w tle?
| Kontener | Co robi | Zużycie RAM |
|---|---|---|
postgres | Przechowuje wszystkie dane | ~256 MB |
backend | Serwer API Java, logika biznesowa | ~512 MB – 1,5 GB |
gotenberg | Konwertuje HTML do PDF (oparty na Chromium) | ~200 MB |
frontend | Serwuje interfejs + reverse proxy | ~20 MB |
Łącznie: około 1,5 – 2,5 GB RAM.
Bezpieczeństwo sekretów
| Sekret | Co chroni | W przypadku utraty |
|---|---|---|
DB_PASSWORD | Dostęp do bazy danych | Możliwy do odzyskania — zresetuj przez narzędzia admin PostgreSQL |
DB_ENCRYPTION_KEY | Kody MFA, hasło SMTP, klucz FX API, pola PII | Trwale nieczytelne |
TIMING_TOKEN_SECRET | Tokeny anty-timing-attack | Zregeneruj — użytkownicy ponownie się uwierzytelniają |
PUBLIC_LINK_PASSWORD_SESSION_SECRET | Sesje publicznych linków | Zregeneruj — aktywne sesje wygasają |
Przechowuj kopie zapasowe
.envpoza NAS. Awaria NAS niszcząca jedyną kopięDB_ENCRYPTION_KEYpowoduje trwałą utratę zaszyfrowanych danych.
Zalecane kolejne kroki
- Skonfiguruj kopie zapasowe w lokalizacji poza NAS.
- Przetestuj generowanie PDF po pierwszym wdrożeniu.
- Jeśli chcesz płynniejszą ścieżkę wdrożenia publicznego, rozważ Coolify na VPS.