Files
infra/docs/SECURITY.md
T
kacperor 6ed7a7f4d2 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
2026-08-20 15:53:51 +00:00

150 lines
5.9 KiB
Markdown

# SECURITY.md — bezpieczeństwo serwera
Zasada porządkująca: **serwer jest tak bezpieczny, jak jego najsłabsza wystawiona usługa.**
Utwardzony SSH nie ma znaczenia, jeśli obok stoi panel administracyjny bez hasła.
---
## 1. Warstwy
| Warstwa | Czym chronimy | Gdzie skonfigurowane |
|---|---|---|
| Dostęp do maszyny | SSH tylko na klucz, root wyłączony | `/etc/ssh/sshd_config.d/99-hardening.conf` |
| Sieć | ufw: deny incoming, allow 22/80/443 | `ufw status verbose` |
| Automatyczne ataki | fail2ban na sshd | `/etc/fail2ban/jail.local` |
| Aktualizacje | unattended-upgrades (security) | `/etc/apt/apt.conf.d/50unattended-upgrades` |
| Izolacja aplikacji | osobne sieci Dockera, brak publikowanych portów | compose każdego stacka |
| Transport | TLS z Let's Encrypt na wszystkim | Traefik |
| Sekrety | pliki `.env`, `chmod 600`, poza repo | obok każdego stacka |
---
## 2. SSH
Docelowa konfiguracja:
```
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
AllowUsers ubuntu
X11Forwarding no
MaxAuthTries 3
```
**Reguła bezwzględna przy każdej zmianie w sshd:** otwierasz drugą sesję SSH i sprawdzasz,
że logowanie działa, **zanim** zamkniesz pierwszą. Błąd w `sshd_config` przy zamkniętej
sesji oznacza odzyskiwanie dostępu przez konsolę KVM w panelu OVH.
Port zostawiamy na 22. Przenoszenie na 2222 to kosmetyka — odsiewa hałas w logach,
ale nie zatrzymuje nikogo, kto celuje w konkretną maszynę. fail2ban robi tu realną robotę.
### Klucze
- osobny klucz na każde urządzenie, `ed25519`, z komentarzem identyfikującym sprzęt
- klucz prywatny **nigdy** nie trafia na serwer ani do repo
- rejestr kluczy: `SERVER.md`, sekcja 4
- przy zgubieniu urządzenia: usuwasz jego linię z `~/.ssh/authorized_keys`, koniec
iOS: Termius lub Blink. Wchodzisz przez `tmux attach -t claude` do tej samej sesji,
którą zostawiłeś na Macu.
---
## 3. Sekrety
| Zasada | Dlaczego |
|---|---|
| `.env` obok stacka, `chmod 600`, właściciel `ubuntu` | inni użytkownicy systemu nie odczytają |
| `.env` w `.gitignore`, w repo tylko `.env.example` | sekret w historii gita zostaje tam na zawsze |
| Hasła generowane, nie wymyślane — `openssl rand -base64 32` | brak ponownego użycia |
| Osobny sekret na usługę | wyciek jednego nie kompromituje reszty |
Jeśli sekret **przypadkiem** trafi do repo: nie wystarczy commit usuwający go.
Trzeba go **unieważnić i wygenerować nowy** — historia gita pamięta, a jeśli poszła na mirror
GitHuba, to jest już poza Twoją kontrolą.
---
## 4. Usługi administracyjne
Panel Traefika, bazy danych, narzędzia debugowe — **nie wystawiamy publicznie**.
Dostęp przez tunel SSH:
```bash
ssh -L 8080:127.0.0.1:8080 ubuntu@dfkk.cloud
# potem localhost:8080 w przeglądarce
```
Jeśli coś musi być publiczne (np. `status.dfkk.cloud`, żeby działało z telefonu),
to za basic auth w Traefiku, z hasłem z generatora.
**Gitea: rejestracja nowych użytkowników wyłączona natychmiast po instalacji.**
Otwarta rejestracja na publicznej instancji to zaproszenie dla botów, które
w kilka dni zamienią ją w hosting spamu.
---
## 5. Aktualizacje
| Co | Jak | Kiedy |
|---|---|---|
| Poprawki bezpieczeństwa Ubuntu | `unattended-upgrades`, automatycznie | codziennie |
| Reszta pakietów systemu | ręcznie, `apt upgrade` | miesięczny przegląd |
| Obrazy Dockera | ręcznie, podniesienie tagu wersji w compose | miesięczny przegląd |
| Restart po aktualizacji kernela | ręcznie, po snapshocie | gdy `/var/run/reboot-required` |
Automatyczny restart po aktualizacji jest **wyłączony**. Nie chcemy, żeby maszyna
sama się przeładowała w środku pracy albo w trakcie działania czegoś produkcyjnego.
Obrazy pinujemy do konkretnych wersji. `latest` oznacza, że najbliższy `docker compose pull`
może podmienić działającą aplikację na wersję z breaking changes — bez ostrzeżenia.
---
## 6. Co monitorujemy
| Sygnał | Próg | Reakcja |
|---|---|---|
| Zajętość dysku | 75% | sprzątanie wg `40-utrzymanie.md` |
| Usługa nie odpowiada | 2 nieudane sprawdzenia | alert mailem |
| Certyfikat wygasa | < 14 dni | sprawdzić DNS-01 i klucze OVH |
| Nietypowe wpisy w logach SSH | — | przegląd przy miesięcznym audycie |
Alerty idą na `k.kruszka@hotmail.com` przez zewnętrzny SMTP.
Serwera pocztowego tu nie stawiamy — OVH blokuje port 25.
---
## 7. Podejrzenie włamania
Kolejność ma znaczenie. **Nie restartuj i nie „posprzątaj" najpierw** — zniszczysz ślady
i stracisz możliwość ustalenia, czym weszli.
1. Odetnij ruch: `ufw default deny incoming` i zatrzymaj wystawione kontenery
2. **Zrób snapshot OVH** — to Twój materiał dowodowy
3. Zbierz: `last`, `journalctl -u ssh`, `docker ps -a`, `crontab -l` dla wszystkich użytkowników,
`ls -la /tmp /var/tmp`, nietypowe procesy i połączenia (`ss -tulpn`)
4. Unieważnij **wszystko**: klucze SSH, tokeny API OVH, token GitHub, hasła w `.env`
5. Oceń zakres — jeśli atakujący miał roota, maszyna jest spalona.
Postawienie od zera z repo `infra` + backup danych jest szybsze i pewniejsze
niż czyszczenie. Dlatego repo `infra` musi być kompletne.
6. Dopiero potem: odbudowa, i wpis do `SERVER.md` co się stało
---
## 8. Braki, które trzeba domknąć
Uczciwa lista rzeczy, których jeszcze **nie ma**. Przeglądać przy miesięcznym audycie.
- [ ] **Backup off-site (restic).** Snapshot OVH to rollback, nie backup — jeden slot,
ręczny, nadpisywany, w tej samej infrastrukturze. Do domknięcia **zanim**
na serwerze pojawią się pierwsze prawdziwe dane.
- [ ] **Test odtworzenia z backupu.** Backup, którego nie odtworzyłeś, nie istnieje.
- [ ] **Mirror repo `infra` na GitHub.** Bez tego awaria serwera zabiera kod, historię
i konfigurację potrzebną do odtworzenia serwera — naraz.
- [ ] **2FA na koncie OVH.** Panel OVH może zrobić z maszyną wszystko, łącznie
z reinstalacją. Jest w praktyce ważniejszy niż dostęp SSH.
- [ ] **2FA na koncie GitHub.**