75 lines
2.8 KiB
Markdown
75 lines
2.8 KiB
Markdown
|
|
---
|
||
|
|
okf: "0.1"
|
||
|
|
type: service
|
||
|
|
visibility: public
|
||
|
|
status: active
|
||
|
|
updated: 2026-08-04
|
||
|
|
links:
|
||
|
|
- ../runbooks/kb-site-deploy.md
|
||
|
|
---
|
||
|
|
|
||
|
|
# kb-site
|
||
|
|
|
||
|
|
Public slice of this knowledge base, served as static HTML at `kb.okit.pl`.
|
||
|
|
Plain `nginx:alpine` on the PIHA node reading one Docker named volume — no
|
||
|
|
build step at runtime, no database, no dependencies.
|
||
|
|
|
||
|
|
The site is a rendering, not a source. Every page is generated from the
|
||
|
|
Markdown documents of the knowledge base by `scripts/kb/gen_pages.py` and
|
||
|
|
copied into the volume; the HTML is never edited by hand and never committed.
|
||
|
|
|
||
|
|
## What gets published
|
||
|
|
|
||
|
|
Only documents that carry an explicit `visibility: public` field in their
|
||
|
|
frontmatter. The generator is **fail-closed**: a document with no frontmatter,
|
||
|
|
with unparseable frontmatter, with no `visibility` field, or with any other
|
||
|
|
value is treated as private and stays out of the build.
|
||
|
|
|
||
|
|
The same rule applies to cross-references. A link pointing at a document that
|
||
|
|
was not published is not rendered as a link — only the label survives, marked
|
||
|
|
`[private]`. A public page therefore never exposes the location of an internal
|
||
|
|
document and never produces a dead link.
|
||
|
|
|
||
|
|
Frontmatter shown on a page is deliberately partial: type, status and the last
|
||
|
|
update date. The `links` field is omitted, because a path to a private document
|
||
|
|
is already a leak of its name.
|
||
|
|
|
||
|
|
## Structure of the build
|
||
|
|
|
||
|
|
```
|
||
|
|
build/kb-site/
|
||
|
|
index.html list of all published documents, grouped by type
|
||
|
|
<directory>/<name>.html one page per document, mirroring the source tree
|
||
|
|
```
|
||
|
|
|
||
|
|
Each page carries a footer with the generation timestamp and the short commit
|
||
|
|
hash of the repository state it was rendered from, so any page can be traced
|
||
|
|
back to an exact revision.
|
||
|
|
|
||
|
|
## Leak gate
|
||
|
|
|
||
|
|
`gen_pages.py --check` re-reads the generated HTML — not the sources — and
|
||
|
|
fails on anything that looks like infrastructure detail leaking into a public
|
||
|
|
page: private, carrier-grade and public IP addresses (v4 and v6), high service
|
||
|
|
port numbers, absolute host paths, and long hex or base64 strings that look
|
||
|
|
like credentials. Deliberate exceptions live in a whitelist file that starts
|
||
|
|
out empty, so every exception is a recorded decision.
|
||
|
|
|
||
|
|
The check is a release gate: content is copied to the host only after it
|
||
|
|
passes.
|
||
|
|
|
||
|
|
## Operations
|
||
|
|
|
||
|
|
Deployment, content refresh, reverse-proxy and DNS setup are described in the
|
||
|
|
[kb-site deployment runbook](../runbooks/kb-site-deploy.md), which is internal —
|
||
|
|
on this site the reference above is plain text, exactly as described in the
|
||
|
|
previous section.
|
||
|
|
|
||
|
|
## Content lifetime
|
||
|
|
|
||
|
|
The volume holds an artifact, not data. There is no backup job — recovery is a
|
||
|
|
regeneration from the repository. Because the generator writes a fresh tree on
|
||
|
|
every run and the publish step replaces the volume contents wholesale, a
|
||
|
|
document that flips from public to private disappears from the site on the next
|
||
|
|
publish.
|