Przejdź do głównej zawartości

5. Zabezpieczenie VPS – Traefik

Dokumentacja konfiguracji Traefika jako reverse proxy dla backendów Palette i Tinting na VPS. Traefik obsługuje ruch na portach 80/443, wystawia certyfikaty Let's Encrypt i kieruje żądania do odpowiednich serwisów.


Środowisko

color-selector-backend (na VPS: color-selector-admin)

SerwisPortUwagi
Directus8055CMS Palette
n8n5678Basic Auth w zmiennych środowiskowych
PostgreSQLBrak portu na hosta
RedisBrak portu na hosta
BackupDo AWS

TRUST_PROXY i PUBLIC_URL muszą być ustawione w zmiennych środowiskowych.

color-tinting-backend

SerwisPortUwagi
Directus8056CMS Tinting (mapowanie host:8056→kontener:8055)
PostgreSQLPort zakomentowany na produkcji
RedisBrak portu na hosta
AdminerPort zakomentowany na produkcji

Architektura

Internet (80/443)


[ Traefik ]

├── color-selector.pl/ → directus (color-selector-admin) :8055
├── color-selector.pl/tinting/ → directus (color-tinting-backend) :8055
└── color-selector.pl/n8n/ → n8n :5678

Mapowanie katalogów

Na VPSW repozytorium
color-selector-admincolor-selector-backend
color-tinting-backendcolor-tinting-backend

Funkcje Traefika

  • Jeden punkt wejścia – porty 80/443; backends nie są wystawiane bezpośrednio na internet.
  • Automatyczne certyfikaty Let's Encrypt (HTTP-01).
  • Routing po domenie i ścieżce (host + PathPrefix).
  • Konfiguracja przez labels w docker-compose.
  • Redirect HTTP → HTTPS.

Konfiguracja

1. Sieć Docker

docker network create traefik-public

W każdym docker-compose (color-selector-backend, color-tinting-backend):

networks:
traefik-public:
external: true

2. Traefik

Katalog traefik/ zawiera:

  • traefik.yml – konfiguracja statyczna
  • docker-compose.yml – serwis Traefika
  • letsencrypt/ – katalog na certyfikaty (mkdir letsencrypt && chmod 700 letsencrypt)

traefik/traefik.yml

api:
dashboard: true

entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
websecure:
address: ":443"

certificatesResolvers:
letsencrypt:
acme:
email: twoj@email.pl
storage: /letsencrypt/acme.json
httpChallenge:
entryPoint: web

providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
network: traefik-public

Adres e-mail w acme.email musi być prawidłowy – Let's Encrypt używa go do powiadomień. Nie musi być w domenie serwisu.

traefik/docker-compose.yml

services:
traefik:
image: traefik:v3.2
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik.yml:/etc/traefik/traefik.yml:ro
- ./letsencrypt:/letsencrypt
networks:
- traefik-public
environment:
- TRAEFIK_API_INSECURE=true
- DOCKER_HOST=unix:///var/run/docker.sock

networks:
traefik-public:
external: true

3. Labels – color-selector-backend

Directus (Palette)

directus:
networks:
- directus-network
- traefik-public
labels:
- "traefik.enable=true"
- "traefik.http.routers.directus-palette.rule=Host(`color-selector.pl`) && !PathPrefix(`/tinting`) && !PathPrefix(`/n8n`)"
- "traefik.http.routers.directus-palette.entrypoints=websecure"
- "traefik.http.routers.directus-palette.tls=true"
- "traefik.http.routers.directus-palette.tls.certresolver=letsencrypt"
- "traefik.http.routers.directus-palette.priority=10"
- "traefik.http.services.directus-palette.loadbalancer.server.port=8055"

n8n

n8n:
networks:
- directus-network
- traefik-public
labels:
- "traefik.enable=true"
- "traefik.http.routers.n8n.rule=Host(`color-selector.pl`) && PathPrefix(`/n8n`)"
- "traefik.http.routers.n8n.entrypoints=websecure"
- "traefik.http.routers.n8n.tls=true"
- "traefik.http.routers.n8n.tls.certresolver=letsencrypt"
- "traefik.http.routers.n8n.priority=20"
- "traefik.http.services.n8n.loadbalancer.server.port=5678"
- "traefik.http.middlewares.n8n-strip.stripprefix.prefixes=/n8n"
- "traefik.http.routers.n8n.middlewares=n8n-strip"

Middleware Stripprefix dla n8n jest wymagany – bez niego n8n zwraca HTML zamiast plików CSS/JS, co powoduje błędy MIME type w przeglądarce.

4. Labels – color-tinting-backend

Directus (Tinting)

directus:
networks:
- directus-test-network
- traefik-public
labels:
- "traefik.enable=true"
- "traefik.http.routers.directus-tinting.rule=Host(`color-selector.pl`) && PathPrefix(`/tinting`)"
- "traefik.http.routers.directus-tinting.entrypoints=websecure"
- "traefik.http.routers.directus-tinting.tls=true"
- "traefik.http.routers.directus-tinting.tls.certresolver=letsencrypt"
- "traefik.http.routers.directus-tinting.priority=20"
- "traefik.http.services.directus-tinting.loadbalancer.server.port=8055"
- "traefik.http.middlewares.tinting-strip.stripprefix.prefixes=/tinting"
- "traefik.http.routers.directus-tinting.middlewares=tinting-strip"

PUBLIC_URL w Directus (Tinting): https://color-selector.pl/tinting/ (ze slash na końcu).


Wyłączenie portów na hostzie

Po potwierdzeniu działania przez Traefik można usunąć mapowanie portów (ports:) z serwisów directus i n8n w color-selector-backend oraz z directusa w color-tinting-backend. Dostęp będzie wyłącznie przez Traefik.


Rozwiązywanie problemów

ObjawDziałanie
Port 80 zajętysudo systemctl stop nginx && sudo systemctl disable nginx
„Error response from daemon”Dodać DOCKER_HOST=unix:///var/run/docker.sock w environment Traefika
„unable to parse email address”Ustawić prawidłowy adres e-mail w traefik.yml
n8n: MIME type text/html dla CSS/JSDodać middleware Stripprefix /n8n do routera n8n

Wdrożenie

Szczegółowy przewodnik wdrożenia: traefik/WDROZENIE-VPS.md.

Wymagania przed startem

  • Sieć traefik-public utworzona
  • PUBLIC_URL w color-tinting-backend: https://color-selector.pl/tinting/
  • Prawidłowy adres e-mail w traefik.yml (certyfikaty Let's Encrypt)
  • Nginx zatrzymany (jeśli wcześniej obsługiwał port 80)