Pod presentation nie wstawał: CreateContainerConfigError, „failed to create
subPath directory for volumeMount state".
MÓJ BŁĄD, NIE ZAGADKA. Udział z bazami jest wyeksportowany `ro: true`
z `root_squash` — ustawiłem to runbookiem DAN-25 i sam tam napisałem ostrzeżenie,
że po tej zmianie nikt nic nie wgra. Dokładając wolumen na konta zmieniłem
`readOnly` przy MONTOWANIU w podzie i uznałem sprawę za załatwioną, nie sprawdzając
eksportu po stronie serwera.
Przyczyna była zresztą podwójna i za każdym razem ta sama:
1. kubelet nie mógł utworzyć podkatalogu, bo udział jest tylko do odczytu,
2. a gdyby nawet mógł — kontenery działają jako root, a root_squash mapuje
roota na nobody, więc aplikacja i tak nie zapisałaby tam pliku kont.
ROZWIĄZANIE BEZ RUSZANIA DAN-25: osobny, mały udział /mnt/Tank1/astrololo-state,
zapisywalny, zawężony do tych samych trzech węzłów, z mapall_user na
nieuprzywilejowanego użytkownika (bezpieczniejsze niż no_root_squash, bo nie
oddaje roota). Udział z bazami ZOSTAJE tylko do odczytu.
Przy okazji znika subPath, czyli znika potrzeba, żeby kubelet cokolwiek zakładał —
katalog istnieje, bo jest korzeniem udziału.
Runbook README-stan-prezentacji.md zawiera test zapisu Z WĘZŁA do wykonania PRZED
wdrożeniem — dokładnie ten, którego zabrakło za pierwszym razem.
UWAGA: DAN-27 (zarządzanie plikami baz) uderzy w tę samą ścianę, bo wymaga zapisu
do udziału z BAZAMI. Ten commit tego nie rozwiązuje i celowo nie rusza DAN-25 —
to osobna decyzja, opisana na końcu runbooka.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ekran „Konta" zapisuje konta do pliku, więc prezentacja potrzebuje trwałego
miejsca — inaczej wszystkie konta znikałyby przy restarcie poda.
subPath, NIE cały udział: prezentacja dostaje wyłącznie własny podkatalog
`presentation-state` i nie widzi baz interpretacyjnych. Zamontowanie tu całego
/mnt/Tank1/astrololo dałoby jej wgląd w bazy i obeszłoby bokiem zamknięcie
dostępu z DAN-25.
Konto administracyjne zostaje w APP_USER/APP_PASSWORD z sekretu — celowo poza
plikiem, żeby nie dało się go skasować ani ograniczyć z aplikacji.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Wszystkie cztery usługi biegły na koncie `default` z AUTOMATYCZNIE montowanym
tokenem API Kubernetesa. Żadna z nich nie rozmawia z API klastra — sekrety dostają
przez `secretKeyRef`, który wstrzykuje kubelet, nie pod. Token był więc zbędny,
a leżał w każdym kontenerze jako gotowy punkt wyjścia do klastra dla kogoś, kto
przejmie proces (np. przez lukę w zależności).
`automountServiceAccountToken: false` w szablonie poda data/logic/presentation/
render. Zweryfikowane `kubectl kustomize` — pole trafia do `.spec.template.spec`,
nie do specu Deploymentu (tam byłoby ciche i bez efektu).
Zero wpływu na działanie: nic w kodzie nie woła API Kubernetesa.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Nowy komponent skladajacy raport PDF. Osobny obraz, bo dzwiga TeX Live (setki MB)
— ta sama zasada co przy izolacji swissepha (LOG-27): obraz produktu zostaje maly,
TeX aktualizuje sie niezaleznie, a awaria renderu nie kladzie aplikacji, tylko
przycisk „Pobierz PDF".
- render.yaml — Deployment + Service. ClusterIP, BEZ NodePortu i Ingressu: nie ma
powodu, zeby ktokolwiek siegal do tej uslugi z zewnatrz. Rozmawia wylacznie
z prezentacja.
- Szyfrowanie: wlasny, TRZECI klucz LINK_KEY_PRESENTATION_RENDER z sekretu
astrololo-link. Osobny, bo tym laczem plynie CALY raport (dane urodzeniowe
i opisy z baz) — przejecie go nie moze otwierac lacza do logiki ani danych.
LINK_ENCRYPTION_REQUIRED=true, wiec bez klucza pod NIE wstaje.
- readOnlyRootFilesystem + emptyDir na /tmp: kompilacja pisze tylko do katalogu
tymczasowego, raport nie zostawia sladu w kontenerze.
- Limity rozjechane celowo (100m/256Mi -> 1500m/1Gi): XeLaTeX na obszernym
raporcie bierze duzo, ale na krotko.
- presentation: RENDER_URL + trzeci klucz lacza.
Sekret astrololo-link trzeba UZUPELNIC o trzeci klucz PRZED wdrozeniem,
zachowujac dwa dotychczasowe — komenda w instrukcji.
Sprawdzone: kubectl kustomize + apply --dry-run=server na zywym klastrze
(service/render i deployment.apps/render created).
Pelna instrukcja: docs/wdrozenie-render-pdf.md w repo astrololo.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Domyka PRE-16 po stronie manifestow. Kod (astrololo#21) potrafi juz szyfrowac
ruch miedzy warstwami AES-256-GCM; tu dokladamy klucze i wymuszenie.
- astrololo-link: nowy sekret z dwoma kluczami (LINK_KEY_PRESENTATION_LOGIC,
LINK_KEY_LOGIC_DATA), tworzony POZA repo jak pozostale. Osobny klucz na pare
rozmowcow: przejecie klucza prezentacji nie otwiera warstwy danych. Logika
bierze oba, prezentacja i dane wylacznie swoj (secretKeyRef).
- LINK_ENCRYPTION_REQUIRED=true we wszystkich trzech: bez klucza pod NIE wstaje,
a klient nie wysyla niczego. Fail-closed w obie strony jest celowy — usluga,
ktora wstala i po cichu nie szyfruje, jest gorsza niz CrashLoop, bo awarii
nie widac.
README: sekcja o sekrecie astrololo-link (tworzenie, wymiana, restart calej
trojki naraz) oraz uczciwa nota, ze szyfrowane sa ciala, nie naglowki — sciezka
i token jada czytelnie, ale sam token bez klucza nic nie daje.
Sprawdzone: kubectl kustomize + apply --dry-run=server przechodza dla obu
profili. Pelna instrukcja wdrozenia: docs/wdrozenie-pre16.md w repo astrololo.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Do tej pory aplikacja chodzila po zwyklym http, a logowanie szlo przez HTTP
Basic — czyli haslo leciało siecia w postaci trywialnej do podsluchania.
Poza bezpieczenstwem TLS naprawia DWIE funkcje zepsute dzis z tego samego
powodu: geolokalizacja przegladarki („Tu i teraz") i kopiowanie promptu do
schowka dzialaja wylacznie w secure context, wiec po http po prostu odmawialy.
Wlasne CA, nie Let's Encrypt — klaster stoi w LAN (traefik trzyma LoadBalancera
na 192.168.1.x), wiec walidacja HTTP-01 nie ma jak dojsc z internetu, a DNS-01
wymagalby trzymania w klastrze tokena API do domeny.
Co dochodzi:
- tls.yaml — Issuer selfSigned -> korzen CA (10 lat, importowany raz do
przegladarki) -> Issuer CA -> certyfikat serwera (90 dni, odnawiany sam).
Krotki termin certyfikatu serwera jest CELOWY: odnawianie sprawdza sie wtedy
co kwartal, a nie dopiero za dekade.
- ingress.yaml — wejscie po https + naglowki (HSTS rok, nosniff, frameDeny)
oraz osobny Ingress na porcie 80 robiacy przekierowanie. Rozdzielone
swiadomie: gdyby redirect wisial na tym samym routerze co wejscie po https,
odsylalby sam do siebie w kolko.
- presentation: Service NodePort -> ClusterIP. NodePort byl druga,
nieszyfrowana droga do aplikacji, czyli obejsciem calego PRE-16.
Zmiana wymagajaca uwagi: TRUST_PROXY=true. Za Ingressem bezposrednim rozmowca
jest zawsze pod Traefika, wiec bez tego limit zadan liczylby WSZYSTKICH do
jednego wiadra i pierwsza osoba, ktora go wyklika, odcielaby pozostalych.
Sprawdzone: Ingress i Middleware przechodza `kubectl apply --dry-run=server`
na zywym klastrze (CRD traefik.io/v1alpha1 sa, entrypointy web/websecure sa).
Obiekty cert-managera zwalidowane offline wobec oficjalnego schematu z CRD
v1.21.0 z additionalProperties=false — literowka w nazwie pola zostalaby
zlapana. `kubectl kustomize` przechodzi dla obu profili (bazowego i swisseph).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Domyka od strony wdrozenia ochrone dodana w aplikacji (PR #10 w repo astrololo).
Bez tych zmiennych aplikacja startuje OTWARTA, a wystawia tresc oryginalnych
baz interpretacyjnych.
- presentation: APP_PASSWORD + INTERNAL_TOKEN z sekretu, APP_USER i
RATE_LIMIT_PER_MIN jawnie (nie sa tajne).
- logic, data: INTERNAL_TOKEN z sekretu — bez niego da sie ominac logowanie,
uderzajac wprost w warstwe nizej. Warstwa danych oddaje SUROWE wiersze,
wiec to najwrazliwszy punkt.
WARTOSCI SEKRETOW CELOWO NIE TRAFIAJA DO REPO — to GitOps, wiec zostalyby
w historii gita na zawsze i przekreslily caly sens tej zmiany. Manifesty
tylko odwoluja sie do sekretu `astrololo-auth`, tworzonego poza repo — ta sama
konwencja co istniejacy `gitea-registry`.
UWAGA: sekret jest WYMAGANY (bez `optional: true`), wiec pody nie wstana,
dopoki go nie utworzysz. To swiadome: lepsza widoczna awaria niz cichy start
bez ochrony. Instrukcja tworzenia i zmiany hasla w astrololo/README.md.
Przy okazji: poprawiony mylacy komentarz przy EXCEL_DIR — pliki baz ida
z NFS, nie z obrazu (montaz je nadpisuje).
Zwalidowane `kubectl kustomize` dla bazy i profilu swisseph: sekrety trafiaja
do wlasciwych uslug, a w wyniku nie ma zadnego `kind: Secret`.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>