# Plan wdrożenia na Contabo Cloud VPS 10

**To jest PLAN -- nic z tego nie zostało jeszcze wykonane.** Ten dokument
opisuje krok po kroku, jak w przyszłości postawimy SameBeat na docelowym
serwerze produkcyjnym. Gdy przyjdzie czas wdrożenia, przejdziemy przez ten
plan punkt po punkcie i odhaczymy, co zrobione.

## Serwer docelowy

- **Dostawca:** Contabo Cloud VPS 10
- **System:** Ubuntu 22.04.5 LTS
- **Procesor:** 4 rdzenie AMD EPYC
- **Pamięć RAM:** 7,75 GiB
- **Dysk:** ok. 72 GB NVMe (szybki dysk SSD)
- **Sieć:** 200 Mbit/s gwarantowane, burst (chwilowe przyspieszenie) do
  1 Gbit/s, transfer bez sztywnego limitu GB, ale z polityką fair-use
  (dostawca może ograniczyć, jeśli zużycie będzie skrajnie nietypowe)

Te 7,75 GB RAM to jest zasób, o który trzeba dbać -- LiveKit, PostgreSQL,
backend i Nginx muszą się na nim razem zmieścić. Warto to mieć z tyłu głowy
przy planowaniu, ile osób jednocześnie impreza ma obsłużyć.

## Kolejność prac (plan krok po kroku)

### 1. Podstawowa konfiguracja Ubuntu

- Aktualizacja systemu (`apt update && apt upgrade`).
- Utworzenie osobnego użytkownika do pracy (nie działać stale jako `root`,
  czyli konto administratora o pełnych uprawnieniach).
- Podstawowy firewall (`ufw`) -- otwarte tylko porty, które faktycznie są
  potrzebne (SSH, HTTP/HTTPS, porty LiveKit).
- Fail2ban lub podobne zabezpieczenie przed automatycznym zgadywaniem haseł
  do SSH (zdalny dostęp do serwera).

### 2. Instalacja .NET 8 Runtime

- Instalacja środowiska uruchomieniowego .NET 8 (runtime -- nie pełne SDK,
  bo na serwerze nie kompilujemy kodu, tylko go uruchamiamy; kompilacja
  dzieje się wcześniej, na komputerze deweloperskim albo w osobnym procesie
  budowania).
- Sprawdzenie wersji po instalacji (`dotnet --info`).

### 3. Instalacja PostgreSQL

- Instalacja PostgreSQL z oficjalnych repozytoriów Ubuntu (lub nowszej
  wersji z repozytorium PostgreSQL, jeśli potrzebna).
- Utworzenie bazy danych produkcyjnej i osobnego użytkownika bazy (nie
  używać domyślnego superużytkownika `postgres` do codziennej pracy
  aplikacji).
- Ograniczenie dostępu do bazy tylko z `localhost` (baza nie powinna być
  widoczna z internetu -- tylko backend na tym samym serwerze się z nią
  łączy).
- Ustawienie mocnego hasła, zapisanego docelowo w
  `/etc/samebeat/appsettings.Production.json` (patrz punkt 7).

### 4. Instalacja Docker (pod LiveKit)

- Instalacja Docker Engine wg oficjalnej instrukcji Dockera dla Ubuntu
  22.04.
- LiveKit uruchamiamy jako kontener Docker -- to najprostszy, sprawdzony
  sposób na self-hosted LiveKit, z gotowym obrazem od twórców LiveKit.
- Konfiguracja LiveKit (plik `livekit.yaml`) z kluczami API i ustawieniami
  sieciowymi (porty UDP do transmisji audio/wideo, port TCP do
  sygnalizacji).
- Warto od razu zaplanować, że kontener LiveKit ma się sam podnosić po
  restarcie serwera (`restart: always` w konfiguracji Dockera).

### 5. Instalacja i konfiguracja Coturn (serwer TURN)

- Coturn pomaga łączyć się przeglądarkom, które siedzą za trudnym NAT-em
  (typowe domowe/firmowe łącza) -- bez tego część uczestników mogłaby mieć
  problem z połączeniem audio/wideo.
- Instalacja z repozytorium Ubuntu (`apt install coturn`).
- Konfiguracja z własną domeną/certyfikatem, mocnym hasłem/kluczem
  współdzielonym (shared secret).
- Otwarcie odpowiednich portów w firewallu (Coturn typowo używa portu 3478
  oraz zakresu portów dla przekazywanego ruchu).

### 6. Instalacja i konfiguracja Nginx

- Nginx jako "portier" na wejściu -- przyjmuje ruch z internetu na
  portach 80/443 i kieruje go dalej:
  - żądania do frontendu -> pliki statyczne (zbudowana wersja React),
  - żądania do API i SignalR -> backend ASP.NET Core,
  - żądania do LiveKit (sygnalizacja) -> kontener LiveKit.
- Certyfikat HTTPS -- np. przez Let's Encrypt (certbot), automatyczne
  odnawianie.
- **HTTPS jest obowiązkowe** -- przeglądarki blokują dostęp do mikrofonu i
  kamery na stronach bez szyfrowanego połączenia (poza `localhost`), więc
  bez HTTPS impreza w ogóle by nie zadziałała.
- **Nagłówki bezpieczeństwa dla plików frontendu -- ważne, łatwe do przeoczenia.**
  Backend (ETAP 7) dokleja `Content-Security-Policy` i pokrewne nagłówki
  (`X-Content-Type-Options`, `X-Frame-Options`, `Referrer-Policy`) do swoich
  własnych odpowiedzi (API, SignalR) -- ale **nigdy nie widzi** żądania o plik
  `index.html`/`.js`/`.css` frontendu, bo te serwuje bezpośrednio Nginx jako
  pliki statyczne. Backend fizycznie nie może doklejić nagłówka do czegoś,
  czego nie obsługuje. Dlatego **Nginx musi dostać ten sam zestaw nagłówków
  osobno**, w bloku `location /` (albo w `server`) obsługującym pliki
  frontendu, np.:
  ```nginx
  add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self' https://TWOJA-DOMENA-API wss://TWOJ-LIVEKIT; frame-ancestors 'none'; base-uri 'self'; form-action 'self'" always;
  add_header X-Content-Type-Options "nosniff" always;
  add_header X-Frame-Options "DENY" always;
  add_header Referrer-Policy "strict-origin-when-cross-origin" always;
  ```
  Podmień `TWOJA-DOMENA-API` i `TWOJ-LIVEKIT` na rzeczywiste adresy produkcyjne
  (te same wartości co `Cors:DozwoloneOrigin`/`LiveKit:Url` w
  `appsettings.Production.json`). Do czasu skonfigurowania tego w Nginx,
  jedyną ochroną CSP dla samej strony jest słabszy znacznik
  `<meta http-equiv="Content-Security-Policy">` wpisany w `frontend/index.html`
  -- wystarczający na start, ale docelowo nagłówek z Nginx jest ważniejszy
  (obsługuje też `frame-ancestors`, którego znacznik `<meta>` nie wspiera).

### 7. Katalogi na serwerze

Plan struktury katalogów -- każda rzecz ma jedno, stałe miejsce:

| Katalog | Do czego |
|---|---|
| `/opt/samebeat/backend` | Zbudowany, gotowy do uruchomienia backend (pliki wynikowe z `dotnet publish`) |
| `/opt/samebeat/frontend` | Zbudowany frontend (pliki statyczne z `npm run build`), serwowane przez Nginx |
| `/etc/samebeat/appsettings.Production.json` | Konfiguracja produkcyjna z prawdziwymi hasłami i kluczami -- **poza katalogiem publicznym**, backend czyta go wskazując pełną ścieżkę |
| `/var/lib/samebeat/music` | Pliki muzyczne używane w trakcie imprez |
| `/var/lib/samebeat/uploads` | Pliki wgrywane przez użytkowników (np. avatary, zdjęcia) |

Uzasadnienie takiego układu: `/opt` to standardowe miejsce na
oprogramowanie zainstalowane ręcznie (nie przez menedżer pakietów Ubuntu),
`/etc` to standardowe miejsce na konfigurację, `/var/lib` to standardowe
miejsce na dane, które aplikacja tworzy i którymi zarządza w trakcie
działania. Trzymanie się tego podziału ułatwia potem kopie zapasowe (samo
`/var/lib/samebeat` + baza danych wystarczą, żeby odtworzyć zawartość) i
aktualizacje (podmiana `/opt/samebeat/backend` nie rusza danych ani
konfiguracji).

### 8. systemd unit dla backendu

- Backend uruchamiany jako usługa systemd (system zarządzania usługami w
  Linuksie) -- żeby:
  - startował automatycznie po restarcie serwera,
  - sam się podnosił po awarii (`Restart=always`),
  - miał logi dostępne przez `journalctl`.
- Plik usługi np. `/etc/systemd/system/samebeat-backend.service`, w nim
  m.in. wskazanie na `/opt/samebeat/backend` i na plik konfiguracji
  `/etc/samebeat/appsettings.Production.json`.
- Analogicznie warto rozważyć osobną usługę/monitoring dla kontenera
  LiveKit i dla Coturn (choć Coturn zwykle sam ma już swoją usługę
  systemd po instalacji z `apt`).

### 9. Publikacja aktualizacji (na przyszłość)

- Ustalimy prosty proces: budowa lokalnie/CI -> przesłanie na serwer ->
  podmiana plików w `/opt/samebeat/...` -> restart usługi systemd.
- Zgodnie z zasadą "jedna aktualna wersja" -- publikujemy zawsze w to samo
  miejsce, nie tworzymy nowych katalogów przy każdym wdrożeniu.

### 10. Kopie zapasowe

- Regularny zrzut bazy PostgreSQL (`pg_dump`) do osobnego miejsca (najlepiej
  poza samym serwerem VPS, żeby awaria dysku nie zabrała też kopii).
- Kopia `/var/lib/samebeat` (muzyka, uploady).
- Kopia `/etc/samebeat/appsettings.Production.json` (ale przechowywana
  bezpiecznie -- to plik z sekretami, patrz `BEZPIECZENSTWO.md`).

## Co zostaje do ustalenia przed wykonaniem

- Domena, pod którą będzie działać SameBeat (potrzebna do certyfikatu
  HTTPS i konfiguracji Coturn).
- Docelowa liczba jednoczesnych uczestników na imprezę -- wpływa na to, ile
  RAM/CPU zostanie LiveKitowi, a ile reszcie systemu.
- Sposób automatycznego budowania i wysyłania aktualizacji (ręcznie przez
  FTP/SSH, czy jakiś prosty skrypt) -- do ustalenia bliżej etapu wdrożenia.

## Powiązane dokumenty

- `ARCHITEKTURA.md` -- jak działa system, żeby rozumieć, po co każdy z
  powyższych elementów.
- `INSTALACJA.md` -- uruchomienie lokalne do testów (etap przed VPS).
- `BEZPIECZENSTWO.md` -- zasady bezpieczeństwa, które ten plan już
  uwzględnia (m.in. konfiguracja poza katalogiem publicznym, HTTPS).
