Init repo infra + poprawki runbooka bootstrap i HANDOFF
- Krok 9 (tmux): tee -> tee -a (nie nadpisuj configu), dodano focus-events on, poprawiono nazwę sesji na "bootstrap" - Krok 10: struktura katalogów odzwierciedla stan faktyczny (/srv i /srv/infra już istnieją, brakuje apps i data) - Krok 12: Claude Code oznaczony jako wykonany 20-08-2026, instalator natywny bez Node.js - Nowy Krok 14: audyt po bootstrapie (SSH, ufw, fail2ban, unattended-upgrades, swap, Docker, porty, klucze) - HANDOFF.md: poprawiona numeracja sekcji 6
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
# 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/<projekt>` |
|
||||
| Wysyłka maili? | zewnętrzny SMTP, nigdy lokalny |
|
||||
| Szacowane zużycie dysku | 100 GB to nasz limit |
|
||||
|
||||
---
|
||||
|
||||
## 2. Struktura
|
||||
|
||||
```bash
|
||||
mkdir -p /srv/apps/<projekt>
|
||||
mkdir -p /srv/data/<projekt>
|
||||
cd /srv/apps/<projekt>
|
||||
git init
|
||||
```
|
||||
|
||||
Minimum plików: `compose.yaml`, `.env.example`, `.gitignore` (z `.env`), `README.md`.
|
||||
|
||||
---
|
||||
|
||||
## 3. Wzorzec compose
|
||||
|
||||
```yaml
|
||||
services:
|
||||
web:
|
||||
image: <obraz>:<KONKRETNA-WERSJA> # nigdy :latest
|
||||
container_name: <projekt>-web
|
||||
restart: unless-stopped
|
||||
env_file: .env
|
||||
networks:
|
||||
- edge
|
||||
- internal
|
||||
volumes:
|
||||
- /srv/data/<projekt>/web:/app/data
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.<projekt>.rule=Host(`<projekt>.dfkk.cloud`)"
|
||||
- "traefik.http.routers.<projekt>.entrypoints=websecure"
|
||||
- "traefik.http.routers.<projekt>.tls.certresolver=ovh"
|
||||
- "traefik.http.services.<projekt>.loadbalancer.server.port=<PORT-WEWNĘTRZNY>"
|
||||
|
||||
db:
|
||||
image: postgres:16.4
|
||||
container_name: <projekt>-db
|
||||
restart: unless-stopped
|
||||
env_file: .env
|
||||
networks:
|
||||
- internal # BEZ edge — baza nie widzi świata
|
||||
volumes:
|
||||
- /srv/data/<projekt>/db:/var/lib/postgresql/data
|
||||
|
||||
networks:
|
||||
edge:
|
||||
external: true
|
||||
internal:
|
||||
name: <projekt>-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 `<projekt>.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://<projekt>.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 <IP-serwera> 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
|
||||
Reference in New Issue
Block a user