Files
akademiawodociagowca/DEPLOYMENT_CHECKLIST.md
T
debian c53ad95104
Deploy PROD / deploy (push) Failing after 0s
LiveKit: jeden port UDP dla wszystkich (mux) zamiast zakresu
Zakres port_range 50000-50100 rezerwowal osobny port na kazde polaczenie.
Test z 200 botami wszedl dokladnie w 49, a log serwera pokazal kandydata
UDP tylko przy 52 polaczeniach i TCP przy wszystkich 204: kolejni
uczestnicy dostawali juz tylko TCP. Zmienna UDP_PORT z zakresem nie
wlaczala muxa, bo przegrywala z zakresem z pliku.

Teraz udp_port: 7882 (sprawdzone lokalnie: rtc.portUDP Start 7882, End 0),
nowa zmienna LIVEKIT_UDP_PORT, zeby stara LIVEKIT_UDP_RANGE w .env nie
mogla przywrocic zakresu.

Automatyczne wdrozenie nie dotyka profilu livekit: kontener trzeba
przeladowac recznie.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 09:16:01 +02:00

12 KiB

Test odbiorczy po wdrozeniu

Lista do wykonania w podanej kolejnosci po uruchomieniu instancji u klienta. Kazdy punkt ma oczekiwany wynik: jesli sie nie zgadza, nie przechodz dalej, bo kolejne punkty na nim polegaja.

Czas wykonania calosci: okolo 90 minut, plus czekanie na przypomnienia i na podsumowanie (do dwoch godzin, mozna w tle).

Wszystkie punkty wykonuje sie przy WLACZONYM trybie bezpiecznym wysylki, poza sekcja I, ktora ten tryb celowo wylacza na koniec. Dzieki temu zadna wiadomosc z testow nie trafi do prawdziwych ludzi.


A. Przed uruchomieniem

# Czynnosc Oczekiwany wynik
A1 cp .env.production.example .env.production i uzupelnic plik istnieje, chmod 600
A2 ./scripts/check-config.sh --skip-db Konfiguracja w porzadku, kod wyjscia 0
A3 Sprawdzic DNS domeny: dig +short webinary.klient.pl adres IP serwera
A4 Sprawdzic certyfikat SSL na reverse proxy klienta waznosc powyzej 14 dni
A5 Porty otwarte na firewallu: 80, 443 dostepne z internetu
A6 Przy VIDEO_PROVIDER=LIVEKIT: dodatkowo 7880, 7881 TCP oraz port UDP 7882 (tryb mux, jeden port dla wszystkich) dostepne z internetu

A6 jest najczestszym przeoczeniem. Bez otwartego zakresu UDP uczestnicy wchodza do pokoju i widza liste obecnych, ale sie nie slysza. Objaw wyglada jak awaria aplikacji, a jest regula firewalla.


B. Uruchomienie

# Czynnosc Oczekiwany wynik
B1 docker compose -f docker-compose.prod.yml --env-file .env.production up -d wszystkie kontenery Started
B2 docker compose -f docker-compose.prod.yml ps postgres i minio healthy, backend healthy (do 90 s)
B3 docker compose logs backend | grep "KONFIGURACJA INSTANCJI" -A 20 wypis stanu, Brak ostrzezen konfiguracyjnych
B4 curl -s https://webinary.klient.pl/api/health {"status":"UP",...}
B5 ./scripts/check-config.sh (juz bez --skip-db) kod wyjscia 0

Jesli B3 pokazuje ostrzezenia, przeczytaj je: kazde nazywa skutek, nie ustawienie. Ostrzezenie o wylaczonym trybie bezpiecznym na tym etapie oznacza, ze testy ponizej wysla prawdziwe wiadomosci.

# Czynnosc Oczekiwany wynik
B6 docker compose logs backend | grep -i "haslo administratora" jednorazowe haslo (gdy ADMIN_PASSWORD bylo puste)
B7 Zalogowac sie na /logowanie i od razu zmienic haslo wejscie do /panel, haslo zmienione

C. Konfiguracja przez panel

Poczta i bramka SMS nie sa w .env: ustawia sie je w panelu, bo zmiana nie moze wymagac dostepu do serwera.

# Czynnosc Oczekiwany wynik
C1 Ustawienia -> E-mail: host, port, login, haslo, nazwa nadawcy zapisane
C2 Sprawdzic, ze MAIL_SAFE_MODE jest wlaczony i ma adres zastepczy wlaczony, adres wlasny
C3 Ustawienia -> E-mail -> Test wysylki wiadomosc dociera na adres zastepczy
C4 Ustawienia -> Aplikacja: nazwa marki, adres publiczny, strefa czasowa zapisane
C5 Ustawienia -> Grafika: logo i ikona widoczne w panelu i na stronie glownej
C6 Ustawienia -> Zgody: tresc regulaminu i zgod marketingowych zapisane, CONSENT_VERSION ustawiona
C7 Przy uzyciu SMS: Ustawienia -> SMS, klucz bramki, tryb bezpieczny wlaczony test SMS dociera na numer zastepczy

D. Sciezka webinarowa

# Czynnosc Oczekiwany wynik
D1 Panel -> Webinary -> nowy: tytul, termin w przyszlosci, limit miejsc zapisany jako DRAFT
D2 Dodac tresc strony w edytorze, wgrac obrazek obrazek widoczny w podgladzie
D3 Opublikowac webinar status PUBLISHED
D4 Otworzyc /w/{slug} w oknie prywatnym strona z trescia i formularzem zapisu
D5 Zapisac sie z wlasnego adresu, zaznaczyc zgody ekran potwierdzenia
D6 Sprawdzic skrzynke mail potwierdzajacy z dzialajacym linkiem i zalacznikiem invite.ics
D7 Otworzyc invite.ics w kalendarzu wydarzenie z poprawna data i strefa
D8 Kliknac link z maila strona wlasnego zapisu, widoczny przycisk rezygnacji
D9 Panel -> lista zapisanych wpis widoczny, zgody z wersja i data
D10 Eksport CSV listy zapisanych plik otwiera sie w Excelu, polskie znaki poprawne
D11 Dodac regule przypomnienia na za 5 minut i odczekac przypomnienie dociera (na adres zastepczy)
D12 Wejsc na /spotkanie/{token} z linku przedpokoj z tytulem i imieniem do potwierdzenia
D13 Wejsc na sale, wyslac wiadomosc na czacie wiadomosc widoczna, autor jako imie i inicjal
D14 Zadac pytanie i zaglosowac na nie z drugiej przegladarki licznik glosow rosnie o 1, drugi glos tej samej osoby odrzucony
D15 Panel prowadzenia: zatwierdzic pytanie pytanie pojawia sie u uczestnika
D16 Zglosic sie do zabrania glosu, przyznac glos z panelu mikrofon uczestnika dziala
D17 Zakonczyc webinar, zmienic termin na przeszly, odczekac SUMMARY_DELAY_MINUTES podsumowanie dociera raz, nie dwa razy
D18 Wystawic certyfikat uczestnikowi z odnotowana obecnoscia PDF z polskimi znakami w nazwisku
D19 Otworzyc /certyfikat/{numer} w oknie prywatnym weryfikacja pokazuje numer, tytul, imie z inicjalem, bez adresu e-mail

D18 jest krytyczny. Certyfikat z polamanym nazwiskiem jest bezuzyteczny, a blad osadzania czcionki widac wylacznie na gotowym pliku.


E. Sciezka Akademii

# Czynnosc Oczekiwany wynik
E1 Otworzyc / w oknie prywatnym strona glowna Akademii, przycisk Zaloguj sie
E2 Panel -> Kursy -> nowy kurs z modulem i lekcja wideo zapisany jako DRAFT
E3 Wgrac nagranie lekcji, ustawic dlugosc plik widoczny
E4 Opublikowac kurs, ustawic cene widoczny na /kursy
E5 Zarejestrowac konto kursanta na /rejestracja mail z linkiem potwierdzajacym
E6 Potwierdzic adres z linku konto aktywne, wejscie na /moje-konto
E7 Zapisac sie na kurs darmowy dostep od reki, kurs na pulpicie
E8 Otworzyc odtwarzacz, obejrzec lekcje do konca lekcja oznaczona jako ukonczona, postep rosnie
E9 Przewinac nagranie w polowie przewijanie dziala (naglowek Range)
E10 Dodac quiz do lekcji, rozwiazac go jako kursant wynik policzony, poprawne odpowiedzi nie sa widoczne w zrodle strony przed koncem
E11 Ukonczyc wszystkie lekcje wymagane kurs COMPLETED, certyfikat wystawiony automatycznie
E12 Sprawdzic mail o ukonczeniu zalacznik PDF, dzialajacy link do pulpitu
E13 Panel -> Kursanci -> szczegoly postep, zgody z historia, ostatnia aktywnosc
E14 Zalogowac sie adresem majacym konto w obu swiatach ekran wyboru: Moje konto i Panel

F. Czego NIE DA SIE sprawdzic lokalnie

Te punkty musza zostac wykonane po wdrozeniu, bo lokalnie nie ma jak ich przejsc. Kazdy z nich to droga, ktora dotad nie zostala przebyta end-to-end.

F1. Notyfikacja ITN Autopay

Operator laczy sie z naszym serwerem, wiec wymaga publicznej domeny z waznym certyfikatem. Na localhost nie da sie tego wywolac.

Krok Oczekiwany wynik
Ustawic AUTOPAY_MODE=TEST, ServiceID i klucz ze srodowiska testowego operatora Autopay: konfiguracja kompletna w wypisie startowym
Zamowic kurs platny jako kursant przekierowanie na bramke testowa
Zaplacic karta testowa operatora powrot na /kurs/{slug}/platnosc
Odczekac na ITN (do kilkudziesieciu sekund) strona sama pokazuje nadany dostep
Panel -> Zamowienia status PAID, w dzienniku wpis notyfikacji
Powtorzyc notyfikacje z panelu operatora dostep nadany raz, drugi komunikat potwierdzony bez zmiany
Sprobowac zaplacic kwota inna niz w zamowieniu notyfikacja odrzucona, wpis w dzienniku

Dopiero po przejsciu wszystkich krokow przelaczyc AUTOPAY_MODE=PRODUCTION. Wypis startowy pokaze wtedy ostrzezenie o prawdziwych pieniadzach: to jest oczekiwane i ma zostac zauwazone.

F2. Nagrywanie przez Egress

Lokalnie proces zatrzymywal sie na tym, ze szablon nie subskrybowal zadnej sciezki: do domkniecia potrzebny jest publikujacy uczestnik w tej samej sieci co Egress, czego nie da sie zestawic na Docker Desktop przy jednym NODE_IP.

Krok Oczekiwany wynik
docker compose ... --profile livekit up -d cztery kontenery wideo dzialaja
docker compose logs livekit-egress | head -30 polaczenie z Redisem, brak bledow ICE
Zestawic spotkanie z dwoma uczestnikami, jeden publikuje obraz obraz i dzwiek plyna w obie strony
Uruchomic nagrywanie z panelu prowadzenia wpis w recordings ze statusem DOWNLOADING
Zakonczyc nagrywanie, odczekac status READY, plik w MinIO
Odtworzyc nagranie z panelu, przewinac odtwarza sie i przewija

Gdy nagrywanie nie ruszy: reczne wgranie pliku dziala i jest droga awaryjna. Nie blokuje to wdrozenia.

F3. Webhook dostawcy wideo

Krok Oczekiwany wynik
Ustawic VIDEO_WEBHOOK_SECRET w panelu i ten sam sekret u dostawcy zapisane
Wywolac zdarzenie u dostawcy (zakonczenie nagrania) wpis w logu backendu, odpowiedz 200
Wyslac zadanie z blednym sekretem: curl -X POST .../api/webhooks/video/livekit -d '{}' 404, nie 403

Odpowiedz 404 jest celowa: 403 pozwalalaby sprawdzic, ktore webinary istnieja.

F4. Zajawki w komunikatorach

Wymagaja publicznego adresu: robot musi pobrac strone z internetu.

Krok Oczekiwany wynik
Wkleic https://webinary.klient.pl/w/{slug} na Slacku albo Facebooku zajawka z tytulem webinaru i opisem
curl -A "facebookexternalhit/1.1" https://webinary.klient.pl/w/{slug} HTML z og:title zawierajacym tytul
To samo dla webinaru w stanie DRAFT 404, wersje robocze nie moga wyciekac

F5. Poczta wychodzaca do prawdziwych odbiorcow

Krok Oczekiwany wynik
Sprawdzic rekordy SPF i DKIM domeny nadawcy skonfigurowane
Wyslac test na adres w Gmailu i w Outlooku wiadomosc nie trafia do spamu
Sprawdzic naglowki dostarczonej wiadomosci SPF pass, DKIM pass

G. Kopia zapasowa

# Czynnosc Oczekiwany wynik
G1 ./scripts/backup.sh katalog w ./backups, pliki baza.dump i minio.tar.gz niepuste
G2 Sprawdzic INFO.txt w kopii data, nazwa bazy, wersja obrazu
G3 Dodac wpis do crontab (patrz README) crontab -l pokazuje wpis
G4 Odtworzyc kopie na maszynie testowej, nie na produkcji dane zgodne ze stanem z chwili kopii

G4 jest obowiazkowy. Kopia, ktorej nigdy nie odtworzono, nie jest kopia zapasowa, tylko plikiem o nieznanej zawartosci.


H. Bezpieczenstwo

# Czynnosc Oczekiwany wynik
H1 curl -s https://webinary.klient.pl/api/admin/webinars 401, nie lista
H2 nmap -p 5432,9000,9001 webinary.klient.pl porty zamkniete z internetu
H3 Otworzyc /swagger-ui.html 404 albo 403 (SWAGGER_ENABLED=false)
H4 Zalogowac sie 6 razy blednym haslem blokada po 5 probie, komunikat taki sam jak przy zlym hasle
H5 Sprobowac pobrac certyfikat cudzym tokenem zapisu 404
H6 Sprawdzic /api/public/config wylacznie nazwa marki, adres i strefa, zadnych sekretow

I. Przelaczenie na ruch produkcyjny

Dopiero po przejsciu wszystkich punktow powyzej.

# Czynnosc Oczekiwany wynik
I1 Skasowac dane testowe: webinary, kursy, zamowienia, kontakty testowe listy puste albo z prawdziwymi danymi
I2 Nie kasowac app_settings ani konta administratora konfiguracja zachowana
I3 Ustawienia -> E-mail: wylaczyc MAIL_SAFE_MODE zapisane
I4 Przy uzyciu SMS: wylaczyc SMS_SAFE_MODE zapisane
I5 Zrestartowac backend i przeczytac wypis startowy ostrzezenie o wylaczonym trybie bezpiecznym: oczekiwane
I6 Wyslac jedna prawdziwa wiadomosc testowa do siebie dociera na wlasciwy adres
I7 ./scripts/backup.sh na czysto kopia stanu wyjsciowego

Po I3 kazda wysylka idzie do prawdziwych odbiorcow. Od tego momentu dane testowe z terminem w przeszlosci moga uruchomic scheduler i wyslac wiadomosci do osob z bazy: dlatego I1 jest przed I3, a nie po.