paperless ngx
Justin Klein edited this page 2026-10-15 17:51:52 +00:00
Clone

Wiki Page Revisions

7 Commits

Author SHA1 Message Date
jklein 42e5f416f0 paperless-ngx, CI/CD, style guide, lessons: an egress rule names the pod port
Gitea #136. The paperless-ngx page said an egress rule names the port on the
destination as the client dials it, and that paperless dials the Tika and
Gotenberg Services on 80. The chart acted on it and the release cut Paperless
off from both services on 2026-10-15.

kube-proxy does a ClusterIP Service's destination NAT before the egress policy
is evaluated at the pod's interface, so the policy sees podIP:targetPort - the
rule names the pod port, 9998 and 3000 here. The old sentence is quoted as
refuted rather than removed, together with the symptom that identifies it: a
timeout, not connection refused.

- paperless-ngx: the rule's ports and the quick repair for 14.0.0, the new
  networkPolicy.egress.mailImport (993, off), extraPorts as pod ports inside the
  cluster, and the install-test's Tika gate being off, so a green install-test is
  not cover for the corrected path.
- CI-CD: the cross-chart assertion as a fifth row, why it needs two charts, the
  gate-on/gate-off pair, and 210 assertions over 30 charts.
- Chart-Style-Guide: pod ports also in egress, and the bar for a named egress
  switch - no second switch for a port another value already decides.
- Lessons-Learned: the lesson, plus how the wrong sentence passed every check
  while the correct mechanism stood two days older in the style guide.
2026-10-15 17:51:52 +00:00
jklein 81980279c4 NetworkPolicies in every chart (Gitea #5): the convention, the gate, and what it does not do
29 chart pages plus Chart-Style-Guide, CI-CD, Charts and Lessons-Learned.

Chart-Style-Guide gains section 15, and its core is the FOUR PORT CLASSES -
the part that is actually hard to get right. A port a network probe addresses
stays open until probeSources is set, because the kubelet probes from the
worker node's IP and no chart can know it. A NodePort-published port stays open
because the source is already masqueraded. Everything else can be and is
restricted by source, which is why the charts with a real inbound restriction
are exactly those whose probes use a different port. A replica-to-replica bus
gets a bare podSelector - and, since policyTypes lists Egress, its outbound
side needs a rule of its own or the cluster never forms while every node looks
healthy.

The exec-probe distinction is written down as load-bearing rather than
pedantic: it is the whole reason valkey and minecraft-server are the tightest
policies in the repository and every HTTP-probed web app is looser.

CI-CD gains the networkpolicy job as section 8 (the later two renumbered), and
it ends with the measurement rather than a claim. Two experiments ran on the PR
and were reverted: cyberchef's probe port restricted to an address no probe can
come from stayed GREEN at 1m9s, and outline with its DNS egress rule removed
went RED at 5m59s. Together those say k3s exempts the kubelet's probe traffic
while enforcing everything else - so the install-test's net is an EGRESS net,
and a wrong ingress port is caught by the render assertion or not at all.

Every chart page gets a networkPolicy values table and an operating note naming
that chart's own trap, not a boilerplate one:

- keycloak carries the blast radius: it is the cluster's identity provider, its
  http rule is the only source-restricted inbound rule in the repo, and nothing
  in CI can catch a wrong controller - so the page asks for a real login and a
  look at consumers' issuer URLs after the first upgrade.
- garage asks the reader to check their S3 consumers, because anything in
  another namespace is blocked until it is in allowedNamespaces.
- bulwark names the quietest failure in the sweep: its probes test its own port,
  so a jmapServerUrl on a blocked port yields a Ready pod serving an empty
  webmail.
- gotenberg explains what its DNS-only cap COSTS - HTML conversion silently
  loses remote assets - rather than only what it buys.
- satisfactory and homeassistant each argue their own Ingress-only policy;
  satisfactory's deciding half is that it is the one chart with no install-test
  at all, so an egress cap there would be the only one with no empirical check
  behind it.
- paperless-ngx names the two pods of its release that the object does NOT
  cover, including the consume CronJob whose pod template carries no labels.
- freesailarr explains why ten containers behind a VPN need only three egress
  rules, and that extraPorts cannot help with an alternative WireGuard port
  because it is TCP-only.

valkey and stalwart are corrected rather than extended. valkey's page now says
why having no probeSources is what makes it the tightest policy here and not an
incomplete one. stalwart's carries a dated correction: this page and the chart
both advised putting the ingress controller's namespace into allowedNamespaces
with ["ingress-nginx"] as the example, and both halves are wrong - ingress-nginx
is gone from the cluster entirely, and allowedNamespaces would have opened http
to every pod in that namespace anyway.

Charts drops the claim that valkey is "the first chart with a NetworkPolicy on
by default" and says instead that every chart has one, with the two shapes a
reader needs before opening any chart page.

Lessons-Learned gains four, all transferable:

- the net that existed for a different failure than the one it was built for,
  and why both experiments were needed before either could be read;
- a comment that could not describe its own syntax (a template comment must not
  spell out its own closing delimiter; the render then fails pointing at the
  template, not at the sentence);
- three values that reached no rule and would have read as controls - a
  convention about value NAMES is not a convention about which values exist;
- the subchart whose comments the parent could not fix, and the rule it
  produced: before making a check a gate, ask which failures the author of this
  diff can actually fix.
2026-10-14 14:57:00 +00:00
jklein 1caabc1a37 paperless-ngx 13.0.0: quoted scalars, the pinned mover, and oidcSecretRef gone (Gitea #11/#101/#112)
paperless-ngx: the removed secrets.oidcSecretRef and why it is not coming back
(one json env var, no _FILE variant; Keycloak marks a client public per
client), tokenAuthMethod restricted to "none" and why client_secret_basic
could never work beside a chart that configures no secret, the new
smbConnection.cron keys, and the env block's quoting with
PAPERLESS_LOGGING_DIR as the worked example - cross-referenced to
jk-cluster-config #360, which it does NOT close.

Two notes were wrong rather than incomplete and are replaced, not appended:
"A schedule may not start with *" documented the bug as a workaround ("use an
equivalent that starts with a digit"), and the probes-exception section said
paperless.replicas: 0 keeps moving PDFs off the share - with the required
podAffinity it no longer can, and what the operator gets instead is a failing
job per schedule.

CI-CD: the new yaml-scalar job as 7 (trivy-config 7->8, install-test 8->9,
following the renumbering the #128 round started), required podAffinity added
to the selector-match job's scope, and the two render-only overlay kinds in the
fixtures table.

Chart-Style-Guide: the | quote half of the env convention, which was never
written down here although template-chart has carried it all along - together
with the six charts that do not follow it, because template-chart's own comment
claimed all of them did while seven did not.

Lessons-Learned: the genus. A value the operator quotes correctly that still
lands bare in the manifest; its quiet half, where the render succeeds and the
API server rejects the object; the defect that survived because no fixture
rendered the object carrying it; and the issue that was wrong about the defect
while being right about the pain.
2026-10-13 19:17:12 +00:00
jklein 353fb7d6de Gateway-API mode for group 2 of #114: the five annotation charts
PR #117. calibre-web-automated, outline, paperless-ngx, zipline (proxy-body-size)
and freesailarr (rewrite-target) each gain an httpRoute block, off by default.

Per chart page: a Routing row instead of the Ingress row, a Gateway-mode install
snippet, an httpRoute values table, and a "Routing: Ingress or Gateway API"
operating note. The upload-limit disclosure is written in each chart's own terms
rather than copied: an e-book library (calibre), an upload service (zipline), the
web-UI half while the consume directory keeps no limit (paperless), and the open
#12 pair (outline). freesailarr sets no body-size annotation and needs none, but
ingress.annotations is its operator's only lever for one.

outline: #12 now says what Gateway mode does to it. The ingress half of the pair
disappears, so the effective ceiling is the Gateway's and neither documented
number necessarily decides. That moves the defect; it does not fix it.

paperless-ngx: it was the last chart rendering its Ingress unconditionally and
now has ingress.enabled, default true. Recorded with the reason, because the
page previously stated the absence of that switch as a property.

freesailarr: the page gains the finding and the improvement. Its shared-host app
list was gated on ingress.enabled and also feeds the <APP>__SERVER__URLBASE
variables, so Gateway mode would have served radarr/sonarr/prowlarr under their
prefixes with no base path set - broken UI, Ready pod. And its rewrite-target
crutch is gone: a URLRewrite filter is per rule, so qBittorrent needs no second
routing object, no repeated TLS secret, no conditional cert-manager annotation
and no regex path.

Chart-Style-Guide §4: the "needs one, not sets one" screen, the rewrite-target
asymmetry as the one place this mode is less machinery, the ingress.enabled-first
rule for a chart without that switch, the freesailarr hostnames exception, and
the group status. §12.1 gains the two addenda the sweep produced.

CI-CD: the HTTPRoute test figure (4 over 2 at the pilot, 20 over 10 after group 1,
36 over 15 now), the multi-app overlay rule, and the honest note that the Gateway
branch of NOTES.txt is executed by that test but printed by no stage.

Lessons-Learned: the freesailarr case in full, next to sure's. Same helper shape,
different symptom - which is the point: ingress.enabled is almost never asked
"does an Ingress exist", and the property it stands in for does not flip with the
object.
2026-10-12 18:28:32 +00:00
jklein 43aef80b2e paperless-ngx: the optional valkey subchart, and two findings it produced
paperless-ngx (Gitea #78) takes our own valkey chart as an optional subchart,
off by default. Its page gets the two new value blocks, the five Redis
consumers that argue the queue-vs-cache choice, the three operator traps and
the CI section, which now describes the first real installation of the
valkey-subchart path anywhere here.

Two findings are general enough to leave the chart page:

- A rule about the relationship between a parent's and a subchart's values
  cannot live in a template. Helm renders a subchart's templates first, so the
  subchart's own required() always wins and reports the path as the subchart
  sees it. Schema validation runs before any rendering, so that is where such a
  rule goes. The first draft was a fail() in the parent that could never fire.
- Erasing a dependency switch turns the subchart ON: a null override deletes
  the key, an unresolvable condition counts as enabled. The one block in a
  chart that must not be null-safe, and the opposite of the rule for every
  other block.

Both in Chart-Style-Guide section 14 and Lessons-Learned; valkey's page names
its second consumer and the queue/cache pair of worked examples; Charts gets
the row.
2026-10-02 21:29:18 +00:00
jklein 311293e164 chart pages carry no version numbers any more
Both version rows leave every chart page's at-a-glance table; the image
repository stays, because it does not rot. A plain app-version bump obliges
no wiki edit — that rule is deliberate and stays — so any number written
here is stale within a Renovate round, as urlaubsverwaltung's already was.
Chart.yaml is where the pair is read, exactly as the chart index has said
from the start.

Home and Workflow no longer promise version snapshots. Forge and tooling
described remotes named github and JLab-Git; the checkout has exactly one,
origin, pointing at Gitea. Workflow gains the rule the wiki never had:
fetch and rebase before every push, never force-push.
2026-09-26 21:42:15 +00:00
jklein f62f2e5871 Fill the wiki as the repository's knowledge base
One page per chart - prerequisites, installation walkthrough, the required
1Password fields, the complete values reference and the chart's operating
traps - plus the long form of the workflow, the forge and its measured
differences, the pipelines, versioning, Renovate, the chart style guide, the
procedure for a new chart, local development, and the incidents each rule was
bought with.

Chart pages quote versions as snapshots; Chart.yaml stays authoritative,
because Renovate moves app versions continuously and never edits the wiki.
2026-09-18 08:48:01 +00:00