feat(kb-site): serwis nginx na PIHA + manifesty (wzorzec narty27)
services/kb-site/ — nginx:alpine serwujacy wolumen kb-site_content
(:ro, /usr/share/nginx/html), pelny layout z CLAUDE.md: docker-compose.yml,
service.yaml, README-wskaznik, env.example (swiadomie pusty — brak sekretow),
healthcheck.sh. Wpis w hosts/piha/services.yaml.
Port hosta 8250, NIE 8240 z opisu zadania: 8240 jest juz zajete przez narty27
(services/narty27/docker-compose.yml). Blok statyczny PIHA to 8210 paperless,
8220 nextcloud, 8230 kb-query, 8240 narty27 -> 8250 to nastepny wolny.
Uzgodnione z operatorem.
exposure: public — w odroznieniu od narty27 ta wystawka ma byc dostepna z
internetu przez vhost npm@PIHA kb.okit.pl; bind :8250 jest upstreamem proxy,
nie punktem wejscia.
Tresc jest czystym artefaktem repo (wyjscie scripts/kb/gen_pages.py), zyje
wylacznie w wolumenie kb-site_kb-site_content — bez binda pod /opt/homelab/data
i bez zadania backupu: odtworzeniem jest regeneracja z kb/.
Sprawdzone lokalnie: docker compose config -q, bash -n healthcheck.sh,
yaml.safe_load na obu manifestach.
2026-08-04 17:59:05 +02:00
|
|
|
service:
|
|
|
|
|
name: kb-site
|
|
|
|
|
owner_node: piha
|
|
|
|
|
role: static-html-host # public slice of the KB, rendered by scripts/kb/gen_pages.py
|
2026-08-05 12:34:13 +02:00
|
|
|
exposure: public # public via npm@PIHA (kb-e2a24af3.okit.pl). The container itself binds
|
feat(kb-site): serwis nginx na PIHA + manifesty (wzorzec narty27)
services/kb-site/ — nginx:alpine serwujacy wolumen kb-site_content
(:ro, /usr/share/nginx/html), pelny layout z CLAUDE.md: docker-compose.yml,
service.yaml, README-wskaznik, env.example (swiadomie pusty — brak sekretow),
healthcheck.sh. Wpis w hosts/piha/services.yaml.
Port hosta 8250, NIE 8240 z opisu zadania: 8240 jest juz zajete przez narty27
(services/narty27/docker-compose.yml). Blok statyczny PIHA to 8210 paperless,
8220 nextcloud, 8230 kb-query, 8240 narty27 -> 8250 to nastepny wolny.
Uzgodnione z operatorem.
exposure: public — w odroznieniu od narty27 ta wystawka ma byc dostepna z
internetu przez vhost npm@PIHA kb.okit.pl; bind :8250 jest upstreamem proxy,
nie punktem wejscia.
Tresc jest czystym artefaktem repo (wyjscie scripts/kb/gen_pages.py), zyje
wylacznie w wolumenie kb-site_kb-site_content — bez binda pod /opt/homelab/data
i bez zadania backupu: odtworzeniem jest regeneracja z kb/.
Sprawdzone lokalnie: docker compose config -q, bash -n healthcheck.sh,
yaml.safe_load na obu manifestach.
2026-08-04 17:59:05 +02:00
|
|
|
# 8250 on the LAN; npm is the sole public entry point.
|
|
|
|
|
dependencies: [] # nginx serving a local volume — nothing else required at runtime
|
|
|
|
|
ports:
|
|
|
|
|
- container: 80
|
|
|
|
|
host: 8250
|
|
|
|
|
protocol: tcp
|
|
|
|
|
healthcheck:
|
|
|
|
|
type: http
|
|
|
|
|
endpoint: http://127.0.0.1:8250/index.html # content must be loaded first (see runbook)
|
|
|
|
|
interval: 30s
|
|
|
|
|
timeout: 10s
|
|
|
|
|
retries: 5
|
|
|
|
|
restart_policy: unless-stopped
|
|
|
|
|
persistence:
|
|
|
|
|
# Docker named volume kb-site_kb-site_content (compose project prefix), NOT a
|
|
|
|
|
# bind under /opt/homelab/data. The content is a pure artifact: regenerate it
|
|
|
|
|
# from the repo with scripts/kb/gen_pages.py, no backup job needed.
|
|
|
|
|
paths:
|
|
|
|
|
- kb-site_kb-site_content
|
|
|
|
|
runtime:
|
docs(kb-site): przekaz ACCESS_TOKEN generatorowi w procedurze publikacji
Poprzedni commit nauczyl gen_pages.py dopisywac token do linkow, ale nic
go nie podawalo — publikacja poszlaby stara sciezka i dalaby build
z golymi linkami, czyli stan sprzed fiksa.
kb-site nie ma skryptu deployu: generator wolany jest wylacznie recznie
z runbooka (kroki 2 i 7), wiec to tam token musi wejsc.
Zrodlo tokenu: /opt/homelab/config/kb-site/.env na wezle GENERUJACYM
(SATURN/SOLARIA), nie na PIHA. To swiadome odstepstwo od konwencji
config/<serwis>/ z CLAUDE.md — plik trzyma zwykle sekrety wezla, ktory
serwis uruchamia, a ten token jest potrzebny tam, gdzie serwis sie
generuje. Kontener nginx dalej nie ma zadnej konfiguracji ani sekretow;
odnotowane w service.yaml i env.example, zeby nikt nie szukal .env na PIHA.
Token idzie zmienna srodowiskowa (set -a; . plik; set +a), nie flaga
--access-token: argument z linii polecen laduje w historii shella i jest
widoczny w ps dla kazdego uzytkownika wezla.
Lancuch publikacji z kroku 7 dostal dwa nowe ogniwa przed scp: test -n
"$ACCESS_TOKEN" (pusty token = build nieklikalny) oraz grep -q 'key='
w index.html (token byl, ale nie dojechal do generatora). Oba zatrzymuja
publikacje tak samo jak --check.
Krok 6 weryfikuje teraz wlasciwa rzecz: wyciaga href ze spisu i pobiera
GO, zamiast recznie sklejac URL — czyli testuje to, co faktycznie bylo
zepsute. Doszedl tez negatywny test bramki (bez tokenu ma NIE byc 200).
Tabela problemow: "index sie otwiera, ale klikniecie daje 403" (build bez
tokenu) i "403 takze z tokenem" (rotacja tokenu w NPM rozjechana z plikiem
— stary build zostaje z martwym tokenem w kazdym linku).
kb/services/kb-site.md (public) — sekcja Access: token siedzi teraz
w tresci kazdej serwowanej strony, wiec jedna zapisana strona wydaje go
w calosci. Model zagrozen bez zmian (URL wejsciowy zawsze go niosl), ale
warto, zeby dokument mowil to wprost obok zdania "to obscurity, not
access control".
Test: sekwencje z krokow 2 i 7 przepuszczone na symulowanym pliku tokenu
(prod /opt/homelab nietkniety) — token obecny: Token: TAK, 4x key=
w index.html, lancuch dochodzi do tar; token pusty: staje na pierwszym
ogniwie, brak tgz; build bez tokenu przy ustawionej zmiennej: staje na
grep, brak tgz. check_okf.py exit 0, gen_pages --check exit 0,
service.yaml parsuje sie.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 22:26:48 +02:00
|
|
|
# The CONTAINER has no .env and no secrets — the port bind is static. The
|
|
|
|
|
# access token below is not a container env var: it is consumed by the
|
|
|
|
|
# generator on the node that builds the site, never by nginx on PIHA.
|
|
|
|
|
config_files: []
|
feat(kb-site): serwis nginx na PIHA + manifesty (wzorzec narty27)
services/kb-site/ — nginx:alpine serwujacy wolumen kb-site_content
(:ro, /usr/share/nginx/html), pelny layout z CLAUDE.md: docker-compose.yml,
service.yaml, README-wskaznik, env.example (swiadomie pusty — brak sekretow),
healthcheck.sh. Wpis w hosts/piha/services.yaml.
Port hosta 8250, NIE 8240 z opisu zadania: 8240 jest juz zajete przez narty27
(services/narty27/docker-compose.yml). Blok statyczny PIHA to 8210 paperless,
8220 nextcloud, 8230 kb-query, 8240 narty27 -> 8250 to nastepny wolny.
Uzgodnione z operatorem.
exposure: public — w odroznieniu od narty27 ta wystawka ma byc dostepna z
internetu przez vhost npm@PIHA kb.okit.pl; bind :8250 jest upstreamem proxy,
nie punktem wejscia.
Tresc jest czystym artefaktem repo (wyjscie scripts/kb/gen_pages.py), zyje
wylacznie w wolumenie kb-site_kb-site_content — bez binda pod /opt/homelab/data
i bez zadania backupu: odtworzeniem jest regeneracja z kb/.
Sprawdzone lokalnie: docker compose config -q, bash -n healthcheck.sh,
yaml.safe_load na obu manifestach.
2026-08-04 17:59:05 +02:00
|
|
|
env_vars: []
|
|
|
|
|
content:
|
|
|
|
|
# Only kb/ documents with `visibility: public` are published; the generator
|
|
|
|
|
# is fail-closed (no frontmatter / no visibility field = private).
|
|
|
|
|
generator: scripts/kb/gen_pages.py
|
|
|
|
|
leak_check: scripts/kb/gen_pages.py --check # must pass before publishing
|
|
|
|
|
source: kb/**/*.md
|
docs(kb-site): przekaz ACCESS_TOKEN generatorowi w procedurze publikacji
Poprzedni commit nauczyl gen_pages.py dopisywac token do linkow, ale nic
go nie podawalo — publikacja poszlaby stara sciezka i dalaby build
z golymi linkami, czyli stan sprzed fiksa.
kb-site nie ma skryptu deployu: generator wolany jest wylacznie recznie
z runbooka (kroki 2 i 7), wiec to tam token musi wejsc.
Zrodlo tokenu: /opt/homelab/config/kb-site/.env na wezle GENERUJACYM
(SATURN/SOLARIA), nie na PIHA. To swiadome odstepstwo od konwencji
config/<serwis>/ z CLAUDE.md — plik trzyma zwykle sekrety wezla, ktory
serwis uruchamia, a ten token jest potrzebny tam, gdzie serwis sie
generuje. Kontener nginx dalej nie ma zadnej konfiguracji ani sekretow;
odnotowane w service.yaml i env.example, zeby nikt nie szukal .env na PIHA.
Token idzie zmienna srodowiskowa (set -a; . plik; set +a), nie flaga
--access-token: argument z linii polecen laduje w historii shella i jest
widoczny w ps dla kazdego uzytkownika wezla.
Lancuch publikacji z kroku 7 dostal dwa nowe ogniwa przed scp: test -n
"$ACCESS_TOKEN" (pusty token = build nieklikalny) oraz grep -q 'key='
w index.html (token byl, ale nie dojechal do generatora). Oba zatrzymuja
publikacje tak samo jak --check.
Krok 6 weryfikuje teraz wlasciwa rzecz: wyciaga href ze spisu i pobiera
GO, zamiast recznie sklejac URL — czyli testuje to, co faktycznie bylo
zepsute. Doszedl tez negatywny test bramki (bez tokenu ma NIE byc 200).
Tabela problemow: "index sie otwiera, ale klikniecie daje 403" (build bez
tokenu) i "403 takze z tokenem" (rotacja tokenu w NPM rozjechana z plikiem
— stary build zostaje z martwym tokenem w kazdym linku).
kb/services/kb-site.md (public) — sekcja Access: token siedzi teraz
w tresci kazdej serwowanej strony, wiec jedna zapisana strona wydaje go
w calosci. Model zagrozen bez zmian (URL wejsciowy zawsze go niosl), ale
warto, zeby dokument mowil to wprost obok zdania "to obscurity, not
access control".
Test: sekwencje z krokow 2 i 7 przepuszczone na symulowanym pliku tokenu
(prod /opt/homelab nietkniety) — token obecny: Token: TAK, 4x key=
w index.html, lancuch dochodzi do tar; token pusty: staje na pierwszym
ogniwie, brak tgz; build bez tokenu przy ustawionej zmiennej: staje na
grep, brak tgz. check_okf.py exit 0, gen_pages --check exit 0,
service.yaml parsuje sie.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 22:26:48 +02:00
|
|
|
# NPM enforces a ?key=<token> gate in front of this site, so every internal
|
|
|
|
|
# href must carry that token or a click lands on 403. The generator reads it
|
|
|
|
|
# from ACCESS_TOKEN; the value lives in the NPM database and in
|
|
|
|
|
# /opt/homelab/config/kb-site/.env ON THE GENERATING NODE (saturn/solaria) —
|
|
|
|
|
# never in this repository. Omitting it yields a valid preview build that
|
|
|
|
|
# must not be published. See kb/runbooks/kb-site-deploy.md.
|
|
|
|
|
access_token_env: ACCESS_TOKEN
|
|
|
|
|
access_token_file: /opt/homelab/config/kb-site/.env # generating node, not piha
|