# Runbook 10 — nowa usługa Od pustego katalogu do działającej aplikacji na własnej subdomenie z HTTPS. --- ## 1. Ustalenia przed startem | Pytanie | Po co | |---|---| | Nazwa projektu (małe litery, myślnik) | katalog, kontenery, sieć, subdomena | | Publiczna czy wewnętrzna? | czy w ogóle wchodzi do sieci `edge` | | Baza danych? Jaka? | osobny kontener w sieci wewnętrznej + wpis do backupu | | Dane trwałe? Gdzie? | bind-mount w `/srv/data/` | | Wysyłka maili? | zewnętrzny SMTP, nigdy lokalny | | Szacowane zużycie dysku | 100 GB to nasz limit | --- ## 2. Struktura ```bash mkdir -p /srv/apps/ mkdir -p /srv/data/ cd /srv/apps/ git init ``` Minimum plików: `compose.yaml`, `.env.example`, `.gitignore` (z `.env`), `README.md`. --- ## 3. Wzorzec compose ```yaml services: web: image: : # nigdy :latest container_name: -web restart: unless-stopped env_file: .env networks: - edge - internal volumes: - /srv/data//web:/app/data labels: - "traefik.enable=true" - "traefik.http.routers..rule=Host(`.dfkk.cloud`)" - "traefik.http.routers..entrypoints=websecure" - "traefik.http.routers..tls.certresolver=ovh" - "traefik.http.services..loadbalancer.server.port=" db: image: postgres:16.4 container_name: -db restart: unless-stopped env_file: .env networks: - internal # BEZ edge — baza nie widzi świata volumes: - /srv/data//db:/var/lib/postgresql/data networks: edge: external: true internal: name: -internal ``` **Trzy rzeczy, na które patrzysz w tym pliku:** 1. Brak sekcji `ports:` — ruch wchodzi wyłącznie przez Traefika. Opublikowany port omija ufw i jest widoczny z internetu. 2. `db` jest tylko w `internal`. Kontener w sieci `edge` jest osiągalny dla każdej innej usługi w `edge` — baza nie ma tam czego szukać. 3. Wersja obrazu przypięta. `:latest` oznacza, że przyszły `pull` może podmienić działającą aplikację na wersję z breaking changes. --- ## 4. Sekrety ```bash cp .env.example .env chmod 600 .env openssl rand -base64 32 # tak generujemy hasła, nie wymyślamy ich ``` Sprawdź, że `.env` jest w `.gitignore`, **zanim** zrobisz pierwszy commit. Sekret raz wypchnięty do repo trzeba unieważnić, nie usunąć. --- ## 5. DNS Rekord A dla `.dfkk.cloud` na IP serwera — panel OVH. Certyfikat leci z wildcardu `*.dfkk.cloud`, więc **nic dodatkowo nie robisz**. Szczegóły: `20-domena.md`. --- ## 6. Uruchomienie ```bash docker compose config # walidacja składni i podstawionych zmiennych docker compose up -d docker compose ps docker compose logs -f --tail=50 ``` --- ## 7. Weryfikacja — sprawdzasz, nie zakładasz ```bash curl -I https://.dfkk.cloud # 200 lub 3xx, certyfikat ważny docker compose ps # wszystko "Up", nic w restart loop docker stats --no-stream # zużycie w granicach rozsądku ``` Test negatywny — potwierdzenie, że baza **nie** jest wystawiona: ```bash # z lokalnej maszyny, nie z serwera: nc -zv 5432 # ma odmówić połączenia ``` --- ## 8. Domknięcie - [ ] Commit w repo projektu, push do Gitei - [ ] Wpis w `SERVER.md`: projekt, katalog, repo, domena, wolumeny, baza - [ ] Wpis w `SERVER.md`, sekcja 2: zajęta subdomena - [ ] Jeśli są dane trwałe — dopisanie ścieżki do listy backupu - [ ] Monitor w Uptime Kuma - [ ] `df -h` — kontrola, ile dysku ubyło