One file, kubernetes/apps/monitoring-rules/probes-blackbox.yaml, in the monitoring namespace. No manifest in the paperless namespace is touched.
Why
The repo already documents this exact blind spot, at apps/gatus/configmap.yaml:176-185:
Paperless sits entirely behind the Authentik gate — every path, including /api/, answers 302 to unauthenticated callers, so there is no endpoint that proves the app rather than the gate. This check is therefore reachability only [...] It stays green if paperless itself is dead behind a live gate.
That external signal is still wanted — REN-2 adds it from UptimeRobot. This is the other half of the pair monitoring-vantage-point-rule asks for: the in-cluster vantage, which goes red on the app dying regardless of the gate.
Why /accounts/login/ and not a health endpoint
paperless-ngx has no unauthenticated health endpoint. Rather than invent one, this uses the app's own established "the webserver answers" signal: the same path its startup, liveness and readiness probes already use (paperless.yaml:252-272). It renders a Django view rather than a static file, so it exercises the WSGI worker and the template layer.
Stated plainly in the comment, because it will matter to whoever reads an alert from it: this does not cover the consumer/celery workers. See process-liveness-vs-protocol-liveness. It is a narrower signal than /-/healthy on Prometheus — but it is strictly more than the zero app-health signal paperless has today.
The cluster-local Host header is accepted only because PAPERLESS_ALLOWED_HOSTS is "*" (paperless.yaml:27). If that is ever narrowed, Django answers 400 here and this probe goes permanently red. The comment says so, in that file, next to the target.
The CNP question — answered "no change needed", against the repo's own comment
The gatus comment continues:
Closing that blind spot needs an in-cluster probe of the paperless ClusterIP, which crosses a namespace boundary and so needs a CiliumNetworkPolicy first — the monitoring probes get away without one only because their targets share a namespace with the prober.
I believe that sentence is true for gatus and not for this prober, and the difference is the namespace:
gatus runs in apps. blackbox-exporter runs in monitoring.
infrastructure/network-policies/paperless-ns.yaml:24-26 already admits the entire monitoring namespace, on every port, with endpointSelector: {}.
The paperless pod is additionally selected by apps/paperless/network-policy.yaml (paperless-gate-ingress), which allows only the gate outpost — but Cilium unions the allow rules of every CNP selecting an endpoint. That file's own comment at :8-12 is what states and relies on this mechanism.
So monitoring → paperless is already permitted today, and this PR adds no grant. Please check this before merging — if I have it backwards, the symptom is one permanently-red probe and a firing BlackboxProbeFailing, not an outage.
One thing reviewers should know, separately from this change
That union means paperless-gate-ingress's stated intent — "Lock the ingress side to the gate outpost only" (network-policy.yaml:6) — is not what the cluster currently enforces: the baseline CNP independently admits all of database and all of monitoring to the paperless pod. Given the header-trust model that file describes, that is worth someone's attention. It is pre-existing, it is not caused by this PR, and I have deliberately not changed it here — narrowing it would alter production traffic and belongs in its own reviewed change.
No PrometheusRule change
prometheusrule-blackbox.yaml:18-33 states the exclusion list and the dedicated rules are one invariant. This target has no dedicated rule, so it is correctly absent from the exclusion list and is picked up by the BlackboxProbeFailing catch-all (warning, for: 10m).
How this was verified — read honestly
Repo-verified. Every file:line above re-read at d36ffc8. YAML parsed with js-yaml; blackbox-http goes 17 → 18 targets, the other two Probe documents unchanged.
NOT cluster-verified. I have no kubeconfig — the owner's standing answer on REN-4 is repo-only — so I have not seen this probe return 200, and I have not stopped paperless to watch it go red. That is the task's stated bar and this PR does not meet it.
The one genuine unknown, and it is specific.module: http_2xx takes the chart default: redirects followed, only a final 2xx passes. I am confident /accounts/login/ renders the login page with 200 to an unauthenticated in-cluster caller, but the repo can only prove 200–399 — a kubelet httpGet accepts any of that range, so the passing probe at paperless.yaml:252 does not by itself exclude a 302. If it is in fact a 302 that redirects back to a gated page, this probe is permanently red rather than wrong-but-quiet.
So on merge, check this first: probe_http_status_code{instance=~".*paperless.*accounts.*"} is 200. If it is not, revert (below) rather than widening the module's accepted codes — a probe that accepts a redirect to a login page is the green-while-broken shape this file exists to prevent.
Blast radius
Read-only observation added to a namespace the prober can already reach. Nothing restarts, no existing workload, ingress or policy is modified. Worst realistic case is a false alert (a warning, not a page).
Revert
git revert <sha>, or delete the one target line and its comment block. One file, additive only, no dependent resource. Reverting this PR does not affect the navidrome/lidarr PR (#976), which branches from the same master.
Merge order note:#976 and this PR both insert at the end of the same static: list and were both cut from master, so whichever merges second needs a trivial rebase. They are deliberately separate so each reverts alone.
## What changed
One target added to the existing `blackbox-http` Probe CR, nothing else:
```
http://paperless.paperless.svc.cluster.local:80/accounts/login/
```
One file, `kubernetes/apps/monitoring-rules/probes-blackbox.yaml`, in the `monitoring` namespace. **No manifest in the `paperless` namespace is touched.**
## Why
The repo already documents this exact blind spot, at `apps/gatus/configmap.yaml:176-185`:
> Paperless sits entirely behind the Authentik gate — every path, including `/api/`, answers 302 to unauthenticated callers, so there is no endpoint that proves the app rather than the gate. This check is therefore reachability only [...] It stays green if paperless itself is dead behind a live gate.
That external signal is still wanted — REN-2 adds it from UptimeRobot. This is the other half of the pair `monitoring-vantage-point-rule` asks for: the in-cluster vantage, which goes red on the app dying regardless of the gate.
## Why `/accounts/login/` and not a health endpoint
paperless-ngx has **no unauthenticated health endpoint**. Rather than invent one, this uses the app's own established "the webserver answers" signal: the same path its startup, liveness and readiness probes already use (`paperless.yaml:252-272`). It renders a Django view rather than a static file, so it exercises the WSGI worker and the template layer.
Stated plainly in the comment, because it will matter to whoever reads an alert from it: **this does not cover the consumer/celery workers.** See `process-liveness-vs-protocol-liveness`. It is a narrower signal than `/-/healthy` on Prometheus — but it is strictly more than the zero app-health signal paperless has today.
The cluster-local Host header is accepted only because `PAPERLESS_ALLOWED_HOSTS` is `"*"` (`paperless.yaml:27`). If that is ever narrowed, Django answers 400 here and this probe goes permanently red. The comment says so, in that file, next to the target.
## The CNP question — answered "no change needed", against the repo's own comment
The gatus comment continues:
> Closing that blind spot needs an in-cluster probe of the paperless ClusterIP, which crosses a namespace boundary and so needs a CiliumNetworkPolicy first — the monitoring probes get away without one only because their targets share a namespace with the prober.
**I believe that sentence is true for gatus and not for this prober**, and the difference is the namespace:
- gatus runs in `apps`. blackbox-exporter runs in `monitoring`.
- `infrastructure/network-policies/paperless-ns.yaml:24-26` already admits the entire `monitoring` namespace, on every port, with `endpointSelector: {}`.
- The paperless pod is additionally selected by `apps/paperless/network-policy.yaml` (`paperless-gate-ingress`), which allows only the gate outpost — but Cilium **unions** the allow rules of every CNP selecting an endpoint. That file's own comment at `:8-12` is what states and relies on this mechanism.
So `monitoring` → paperless is already permitted today, and this PR adds no grant. **Please check this before merging** — if I have it backwards, the symptom is one permanently-red probe and a firing `BlackboxProbeFailing`, not an outage.
### One thing reviewers should know, separately from this change
That union means `paperless-gate-ingress`'s stated intent — *"Lock the ingress side to the gate outpost only"* (`network-policy.yaml:6`) — is **not** what the cluster currently enforces: the baseline CNP independently admits all of `database` and all of `monitoring` to the paperless pod. Given the header-trust model that file describes, that is worth someone's attention. It is pre-existing, it is not caused by this PR, and I have deliberately **not** changed it here — narrowing it would alter production traffic and belongs in its own reviewed change.
## No PrometheusRule change
`prometheusrule-blackbox.yaml:18-33` states the exclusion list and the dedicated rules are one invariant. This target has no dedicated rule, so it is correctly **absent** from the exclusion list and is picked up by the `BlackboxProbeFailing` catch-all (warning, `for: 10m`).
## How this was verified — read honestly
- **Repo-verified.** Every `file:line` above re-read at `d36ffc8`. YAML parsed with js-yaml; `blackbox-http` goes 17 → 18 targets, the other two Probe documents unchanged.
- **NOT cluster-verified.** I have no kubeconfig — the owner's standing answer on REN-4 is repo-only — so I have not seen this probe return 200, and I have not stopped paperless to watch it go red. That is the task's stated bar and this PR does not meet it.
**The one genuine unknown, and it is specific.** `module: http_2xx` takes the chart default: redirects followed, only a final **2xx** passes. I am confident `/accounts/login/` renders the login page with 200 to an unauthenticated in-cluster caller, but the repo can only prove 200–399 — a kubelet `httpGet` accepts any of that range, so the passing probe at `paperless.yaml:252` does not by itself exclude a 302. If it is in fact a 302 that redirects back to a gated page, this probe is permanently red rather than wrong-but-quiet.
So on merge, check this first: `probe_http_status_code{instance=~".*paperless.*accounts.*"}` is `200`. If it is not, revert (below) rather than widening the module's accepted codes — a probe that accepts a redirect to a login page is the green-while-broken shape this file exists to prevent.
## Blast radius
Read-only observation added to a namespace the prober can already reach. Nothing restarts, no existing workload, ingress or policy is modified. Worst realistic case is a false alert (a warning, not a page).
## Revert
`git revert <sha>`, or delete the one target line and its comment block. One file, additive only, no dependent resource. Reverting this PR does not affect the navidrome/lidarr PR (#976), which branches from the same `master`.
**Merge order note:** #976 and this PR both insert at the end of the same `static:` list and were both cut from `master`, so whichever merges second needs a trivial rebase. They are deliberately separate so each reverts alone.
paperless.renner.uno is served entirely through the paperless-gate
Authentik outpost. gatus already records the consequence at
apps/gatus/configmap.yaml:176-185: every path including /api/ answers
302 to an unauthenticated caller, so its check of that hostname — and
the UptimeRobot monitor REN-2 adds — is reachability only and stays
green while paperless is dead behind a live gate. This adds the app
health half of the pair, from the in-cluster vantage.
The target is /accounts/login/ because paperless-ngx has no
unauthenticated health endpoint. It is the app's own established
"the webserver answers" signal — the path its startup, liveness and
readiness probes already use — and it renders a Django view rather
than a static file. It does not cover the consumer/celery workers,
and the comment says so.
No CiliumNetworkPolicy change, and no edit to the paperless namespace.
The gatus comment above asserts an in-cluster probe needs one first;
that was written for gatus, which runs in `apps`. paperless-ns.yaml:24-26
already admits the whole monitoring namespace, where blackbox-exporter
runs, and Cilium unions the allow rules of every CNP selecting an
endpoint — the same mechanism apps/paperless/network-policy.yaml:8-12
relies on.
No PrometheusRule change: the target is covered by the existing
BlackboxProbeFailing catch-all and is correctly absent from its
exclusion list, which per prometheusrule-blackbox.yaml:18-33 holds only
instances that have a dedicated rule elsewhere.
Refs REN-21.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
🤖Automated review — model CLI default (complexity: unknown), commit bdf55c5b49b38a7a0d96cb5be09cb78fdc989fd3.
Advisory review by the review-bot pipeline. It never approves; a human merges. Push new commits to get a fresh review.
Summary
Adds one target — http://paperless.paperless.svc.cluster.local:80/accounts/login/ — to the existing blackbox-http Probe in kubernetes/apps/monitoring-rules/probes-blackbox.yaml, giving paperless an in-cluster app-health signal to complement the gate-only external check documented in apps/gatus/configmap.yaml:176-185. Single file, additive only, no other manifest touched. I independently verified the PR body's technical claims against the checkout and they hold up (details below); no blocking issues found.
🟡 Suggestions
Redirect risk on the module is real, and worth resolving promptly after merge rather than being left to whoever notices the alert.probes-blackbox.yaml:37 uses module: http_2xx (helmrelease-blackbox-exporter.yaml confirms it's the unmodified chart default, which follows redirects and passes on any final 2xx). The k8s startupProbe/livenessProbe/readinessProbe at paperless.yaml:252-272 hit the identical path and succeed, but httpGet treats the whole 200-399 range as success, so their passing does not prove /accounts/login/ returns a bare 200 rather than a 30x — the PR body's own "one genuine unknown" section says as much. Blast radius is limited (the BlackboxProbeFailing catch-all in prometheusrule-blackbox.yaml:35 is severity: warning, for: 10m), so this doesn't block, but the post-merge check the author commits to (probe_http_status_code{instance=~".*paperless.*accounts.*"} == 200) should actually happen.
The CNP reasoning checks out: monitoring namespace is already admitted to the paperless pod via default-deny-ingress's endpointSelector: {} at infrastructure/network-policies/paperless-ns.yaml:24-26, unioned with paperless-gate-ingress's narrower authentik-only rule per Cilium's allow-rule-union semantics (apps/paperless/network-policy.yaml:8-12). No CiliumNetworkPolicy change is needed for this probe to reach the pod, confirming the PR's central "no change needed" claim.
Tests
Infra-as-code repo with no test suite for this file; the existing convention is inline documentation plus the BlackboxProbeFailing/exclusion-list invariant in prometheusrule-blackbox.yaml, which this PR correctly respects (the new target has no dedicated rule, so it's correctly not added to the exclusion regex at prometheusrule-blackbox.yaml:35, and will be picked up by the catch-all). No CI mechanically validates that invariant — it's manually maintained, consistent with the rest of the file.
Recommendation
Looks reasonable — no blocking issues; comments above are optional.
🤖 **Automated review** — model `CLI default` (complexity: unknown), commit `bdf55c5b49b38a7a0d96cb5be09cb78fdc989fd3`.
> Advisory review by the `review-bot` pipeline. It never approves; a human merges. Push new commits to get a fresh review.
---
## Summary
Adds one target — `http://paperless.paperless.svc.cluster.local:80/accounts/login/` — to the existing `blackbox-http` Probe in `kubernetes/apps/monitoring-rules/probes-blackbox.yaml`, giving paperless an in-cluster app-health signal to complement the gate-only external check documented in `apps/gatus/configmap.yaml:176-185`. Single file, additive only, no other manifest touched. I independently verified the PR body's technical claims against the checkout and they hold up (details below); no blocking issues found.
## 🟡 Suggestions
- **Redirect risk on the module is real, and worth resolving promptly after merge rather than being left to whoever notices the alert.** `probes-blackbox.yaml:37` uses `module: http_2xx` (`helmrelease-blackbox-exporter.yaml` confirms it's the unmodified chart default, which follows redirects and passes on any final 2xx). The k8s `startupProbe`/`livenessProbe`/`readinessProbe` at `paperless.yaml:252-272` hit the identical path and succeed, but `httpGet` treats the whole 200-399 range as success, so their passing does **not** prove `/accounts/login/` returns a bare 200 rather than a 30x — the PR body's own "one genuine unknown" section says as much. Blast radius is limited (the `BlackboxProbeFailing` catch-all in `prometheusrule-blackbox.yaml:35` is `severity: warning`, `for: 10m`), so this doesn't block, but the post-merge check the author commits to (`probe_http_status_code{instance=~".*paperless.*accounts.*"} == 200`) should actually happen.
- The CNP reasoning checks out: `monitoring` namespace is already admitted to the paperless pod via `default-deny-ingress`'s `endpointSelector: {}` at `infrastructure/network-policies/paperless-ns.yaml:24-26`, unioned with `paperless-gate-ingress`'s narrower authentik-only rule per Cilium's allow-rule-union semantics (`apps/paperless/network-policy.yaml:8-12`). No CiliumNetworkPolicy change is needed for this probe to reach the pod, confirming the PR's central "no change needed" claim.
## Tests
Infra-as-code repo with no test suite for this file; the existing convention is inline documentation plus the `BlackboxProbeFailing`/exclusion-list invariant in `prometheusrule-blackbox.yaml`, which this PR correctly respects (the new target has no dedicated rule, so it's correctly *not* added to the exclusion regex at `prometheusrule-blackbox.yaml:35`, and will be picked up by the catch-all). No CI mechanically validates that invariant — it's manually maintained, consistent with the rest of the file.
## Recommendation
Looks reasonable — no blocking issues; comments above are optional.
<!-- pr-review:sha=bdf55c5b49b38a7a0d96cb5be09cb78fdc989fd3 -->
Approve. Reviewed at head bdf55c5b, base d36ffc8, rebased onto master after #976. Full review with evidence: REN-22.
Checked, not skimmed:
Diff is exactly one file, kubernetes/apps/monitoring-rules/probes-blackbox.yaml, namespace monitoring. Pure append. Zero production-namespace manifests.
Target counts parsed with js-yaml: blackbox-http 17 → 18 standalone, 19 → 20 after rebase onto #976. blackbox-edge-wan (3) and blackbox-tcp-relays (2) byte-identical.
:80 matches the paperless Service (port: 80 → targetPort: http).
Falls to the BlackboxProbeFailing catch-all — severity: warning, for: 10m, correctly absent from the prometheusrule-blackbox.yaml:35 exclusion list, consistent with the invariant stated at :18-33. No 03:00 page.
No secret, RBAC grant, or public-status-page surface touched.
Citations spot-checked and accurate: PAPERLESS_ALLOWED_HOSTS: "*" (paperless.yaml:27), probe path (paperless.yaml:252-272), CNP union mechanism (apps/paperless/network-policy.yaml:8-12), and both house-policy notes (monitoring-vantage-point-rule, process-liveness-vs-protocol-liveness). The latter is the right citation — /accounts/login/ proves the WSGI worker, not the celery/consumer workers, and the comment says so.
On the CNP claim — conclusion right.paperless-ns.yaml:24-26 admits the whole monitoring namespace under endpointSelector: {} with no toPorts; paperless-gate-ingress is additional and Cilium unions allow rules across every CNP selecting an endpoint. Same egress caveat as #976: no CNP in monitoring declares an egress: block, which is the undocumented load-bearing fact.
One correction to this PR's reasoning. It describes gatus/configmap.yaml:182-185 as written for gatus. Reading it, the sentence is "the monitoring probes get away without one only because their targets share a namespace with the prober" — that is a claim about the blackbox prober, not gatus. The simpler and true diagnosis is that the comment is wrong/stale: paperless-ns.yaml:24-26 already admits all of monitoring and its author did not check. That matters, because this PR's entire justification is "that comment is wrong" and it leaves the comment in place — the next person re-derives the phantom CNP requirement. One-line fix, tracked on REN-21.
The 302 risk is real and unresolved.module: http_2xx is the chart default (not declared in helmrelease-blackbox-exporter.yaml), so redirects are followed and only a final 2xx passes. The kubelet httpGet evidence proves only 200–399. I could not check the live status code — no Prometheus read path. If /accounts/login/ returns 302, revert this PR rather than widening valid_status_codes; a probe that accepts a redirect to a login page is the exact green-while-broken shape this file exists to prevent.
Revert path: this PR's git revert -m 1 <merge sha> is clean — I tested it (20 → 19, navidrome+lidarr intact). Merged second deliberately, so the higher-uncertainty target gets the conflict-free revert.
Not verified: no Prometheus read path. probe_success and probe_http_status_code unseen; recorded as owed on REN-22.
Rebase disclosure. I performed the rebase onto master after #976 (commit cb9e73bd, previously bdf55c5b). I am the merger, so I am stating exactly what I did to a PR I did not author: the conflict was the two blocks appending at the same insertion point, and I resolved it by deleting the three conflict-marker lines only. I changed no other character. Verified: the 29 added lines are byte-identical to the original commit (diff against git diff d36ffc80 bdf55c5b output — identical), svc-atlas is preserved as author, and js-yaml reparse gives blackbox-http 19 -> 20 with paperless the only addition, nothing removed, no duplicates, blackbox-edge-wan (3) and blackbox-tcp-relays (2) unchanged.
**Approve.** Reviewed at head `bdf55c5b`, base `d36ffc8`, rebased onto master after #976. Full review with evidence: REN-22.
**Checked, not skimmed:**
- Diff is exactly one file, `kubernetes/apps/monitoring-rules/probes-blackbox.yaml`, namespace `monitoring`. Pure append. Zero production-namespace manifests.
- Target counts parsed with js-yaml: `blackbox-http` 17 → 18 standalone, 19 → 20 after rebase onto #976. `blackbox-edge-wan` (3) and `blackbox-tcp-relays` (2) byte-identical.
- `:80` matches the paperless Service (`port: 80 → targetPort: http`).
- Falls to the `BlackboxProbeFailing` catch-all — `severity: warning`, `for: 10m`, correctly absent from the `prometheusrule-blackbox.yaml:35` exclusion list, consistent with the invariant stated at `:18-33`. No 03:00 page.
- No secret, RBAC grant, or public-status-page surface touched.
- Citations spot-checked and accurate: `PAPERLESS_ALLOWED_HOSTS: "*"` (`paperless.yaml:27`), probe path (`paperless.yaml:252-272`), CNP union mechanism (`apps/paperless/network-policy.yaml:8-12`), and both house-policy notes (`monitoring-vantage-point-rule`, `process-liveness-vs-protocol-liveness`). The latter is the right citation — `/accounts/login/` proves the WSGI worker, not the celery/consumer workers, and the comment says so.
**On the CNP claim — conclusion right.** `paperless-ns.yaml:24-26` admits the whole `monitoring` namespace under `endpointSelector: {}` with no `toPorts`; `paperless-gate-ingress` is additional and Cilium unions allow rules across every CNP selecting an endpoint. Same egress caveat as #976: no CNP in `monitoring` declares an `egress:` block, which is the undocumented load-bearing fact.
**One correction to this PR's reasoning.** It describes `gatus/configmap.yaml:182-185` as written for gatus. Reading it, the sentence is *"the monitoring probes get away without one only because their targets share a namespace with the prober"* — that is a claim about **the blackbox prober**, not gatus. The simpler and true diagnosis is that the comment is **wrong/stale**: `paperless-ns.yaml:24-26` already admits all of `monitoring` and its author did not check. That matters, because this PR's entire justification is "that comment is wrong" and it leaves the comment in place — the next person re-derives the phantom CNP requirement. One-line fix, tracked on REN-21.
**The 302 risk is real and unresolved.** `module: http_2xx` is the chart default (not declared in `helmrelease-blackbox-exporter.yaml`), so redirects are followed and only a final 2xx passes. The kubelet `httpGet` evidence proves only 200–399. I could not check the live status code — no Prometheus read path. If `/accounts/login/` returns 302, **revert this PR rather than widening `valid_status_codes`**; a probe that accepts a redirect to a login page is the exact green-while-broken shape this file exists to prevent.
**Revert path:** this PR's `git revert -m 1 <merge sha>` is clean — I tested it (20 → 19, navidrome+lidarr intact). Merged second deliberately, so the higher-uncertainty target gets the conflict-free revert.
**Not verified:** no Prometheus read path. `probe_success` and `probe_http_status_code` unseen; recorded as owed on REN-22.
---
**Rebase disclosure.** I performed the rebase onto master after #976 (commit `cb9e73bd`, previously `bdf55c5b`). I am the merger, so I am stating exactly what I did to a PR I did not author: the conflict was the two blocks appending at the same insertion point, and I resolved it by **deleting the three conflict-marker lines only**. I changed no other character. Verified: the 29 added lines are byte-identical to the original commit (`diff` against `git diff d36ffc80 bdf55c5b` output — identical), `svc-atlas` is preserved as author, and js-yaml reparse gives `blackbox-http` 19 -> 20 with paperless the only addition, nothing removed, no duplicates, `blackbox-edge-wan` (3) and `blackbox-tcp-relays` (2) unchanged.
Ghost
merged commit 0a82d61ff8 into master2026-09-25 18:52:17 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What changed
One target added to the existing
blackbox-httpProbe CR, nothing else:One file,
kubernetes/apps/monitoring-rules/probes-blackbox.yaml, in themonitoringnamespace. No manifest in thepaperlessnamespace is touched.Why
The repo already documents this exact blind spot, at
apps/gatus/configmap.yaml:176-185:That external signal is still wanted — REN-2 adds it from UptimeRobot. This is the other half of the pair
monitoring-vantage-point-ruleasks for: the in-cluster vantage, which goes red on the app dying regardless of the gate.Why
/accounts/login/and not a health endpointpaperless-ngx has no unauthenticated health endpoint. Rather than invent one, this uses the app's own established "the webserver answers" signal: the same path its startup, liveness and readiness probes already use (
paperless.yaml:252-272). It renders a Django view rather than a static file, so it exercises the WSGI worker and the template layer.Stated plainly in the comment, because it will matter to whoever reads an alert from it: this does not cover the consumer/celery workers. See
process-liveness-vs-protocol-liveness. It is a narrower signal than/-/healthyon Prometheus — but it is strictly more than the zero app-health signal paperless has today.The cluster-local Host header is accepted only because
PAPERLESS_ALLOWED_HOSTSis"*"(paperless.yaml:27). If that is ever narrowed, Django answers 400 here and this probe goes permanently red. The comment says so, in that file, next to the target.The CNP question — answered "no change needed", against the repo's own comment
The gatus comment continues:
I believe that sentence is true for gatus and not for this prober, and the difference is the namespace:
apps. blackbox-exporter runs inmonitoring.infrastructure/network-policies/paperless-ns.yaml:24-26already admits the entiremonitoringnamespace, on every port, withendpointSelector: {}.apps/paperless/network-policy.yaml(paperless-gate-ingress), which allows only the gate outpost — but Cilium unions the allow rules of every CNP selecting an endpoint. That file's own comment at:8-12is what states and relies on this mechanism.So
monitoring→ paperless is already permitted today, and this PR adds no grant. Please check this before merging — if I have it backwards, the symptom is one permanently-red probe and a firingBlackboxProbeFailing, not an outage.One thing reviewers should know, separately from this change
That union means
paperless-gate-ingress's stated intent — "Lock the ingress side to the gate outpost only" (network-policy.yaml:6) — is not what the cluster currently enforces: the baseline CNP independently admits all ofdatabaseand all ofmonitoringto the paperless pod. Given the header-trust model that file describes, that is worth someone's attention. It is pre-existing, it is not caused by this PR, and I have deliberately not changed it here — narrowing it would alter production traffic and belongs in its own reviewed change.No PrometheusRule change
prometheusrule-blackbox.yaml:18-33states the exclusion list and the dedicated rules are one invariant. This target has no dedicated rule, so it is correctly absent from the exclusion list and is picked up by theBlackboxProbeFailingcatch-all (warning,for: 10m).How this was verified — read honestly
file:lineabove re-read atd36ffc8. YAML parsed with js-yaml;blackbox-httpgoes 17 → 18 targets, the other two Probe documents unchanged.The one genuine unknown, and it is specific.
module: http_2xxtakes the chart default: redirects followed, only a final 2xx passes. I am confident/accounts/login/renders the login page with 200 to an unauthenticated in-cluster caller, but the repo can only prove 200–399 — a kubelethttpGetaccepts any of that range, so the passing probe atpaperless.yaml:252does not by itself exclude a 302. If it is in fact a 302 that redirects back to a gated page, this probe is permanently red rather than wrong-but-quiet.So on merge, check this first:
probe_http_status_code{instance=~".*paperless.*accounts.*"}is200. If it is not, revert (below) rather than widening the module's accepted codes — a probe that accepts a redirect to a login page is the green-while-broken shape this file exists to prevent.Blast radius
Read-only observation added to a namespace the prober can already reach. Nothing restarts, no existing workload, ingress or policy is modified. Worst realistic case is a false alert (a warning, not a page).
Revert
git revert <sha>, or delete the one target line and its comment block. One file, additive only, no dependent resource. Reverting this PR does not affect the navidrome/lidarr PR (#976), which branches from the samemaster.Merge order note: #976 and this PR both insert at the end of the same
static:list and were both cut frommaster, so whichever merges second needs a trivial rebase. They are deliberately separate so each reverts alone.🤖 Automated review — model
CLI default(complexity: unknown), commitbdf55c5b49b38a7a0d96cb5be09cb78fdc989fd3.Summary
Adds one target —
http://paperless.paperless.svc.cluster.local:80/accounts/login/— to the existingblackbox-httpProbe inkubernetes/apps/monitoring-rules/probes-blackbox.yaml, giving paperless an in-cluster app-health signal to complement the gate-only external check documented inapps/gatus/configmap.yaml:176-185. Single file, additive only, no other manifest touched. I independently verified the PR body's technical claims against the checkout and they hold up (details below); no blocking issues found.🟡 Suggestions
probes-blackbox.yaml:37usesmodule: http_2xx(helmrelease-blackbox-exporter.yamlconfirms it's the unmodified chart default, which follows redirects and passes on any final 2xx). The k8sstartupProbe/livenessProbe/readinessProbeatpaperless.yaml:252-272hit the identical path and succeed, buthttpGettreats the whole 200-399 range as success, so their passing does not prove/accounts/login/returns a bare 200 rather than a 30x — the PR body's own "one genuine unknown" section says as much. Blast radius is limited (theBlackboxProbeFailingcatch-all inprometheusrule-blackbox.yaml:35isseverity: warning,for: 10m), so this doesn't block, but the post-merge check the author commits to (probe_http_status_code{instance=~".*paperless.*accounts.*"} == 200) should actually happen.monitoringnamespace is already admitted to the paperless pod viadefault-deny-ingress'sendpointSelector: {}atinfrastructure/network-policies/paperless-ns.yaml:24-26, unioned withpaperless-gate-ingress's narrower authentik-only rule per Cilium's allow-rule-union semantics (apps/paperless/network-policy.yaml:8-12). No CiliumNetworkPolicy change is needed for this probe to reach the pod, confirming the PR's central "no change needed" claim.Tests
Infra-as-code repo with no test suite for this file; the existing convention is inline documentation plus the
BlackboxProbeFailing/exclusion-list invariant inprometheusrule-blackbox.yaml, which this PR correctly respects (the new target has no dedicated rule, so it's correctly not added to the exclusion regex atprometheusrule-blackbox.yaml:35, and will be picked up by the catch-all). No CI mechanically validates that invariant — it's manually maintained, consistent with the rest of the file.Recommendation
Looks reasonable — no blocking issues; comments above are optional.
bdf55c5b49tocb9e73bd94Approve. Reviewed at head
bdf55c5b, based36ffc8, rebased onto master after #976. Full review with evidence: REN-22.Checked, not skimmed:
kubernetes/apps/monitoring-rules/probes-blackbox.yaml, namespacemonitoring. Pure append. Zero production-namespace manifests.blackbox-http17 → 18 standalone, 19 → 20 after rebase onto #976.blackbox-edge-wan(3) andblackbox-tcp-relays(2) byte-identical.:80matches the paperless Service (port: 80 → targetPort: http).BlackboxProbeFailingcatch-all —severity: warning,for: 10m, correctly absent from theprometheusrule-blackbox.yaml:35exclusion list, consistent with the invariant stated at:18-33. No 03:00 page.PAPERLESS_ALLOWED_HOSTS: "*"(paperless.yaml:27), probe path (paperless.yaml:252-272), CNP union mechanism (apps/paperless/network-policy.yaml:8-12), and both house-policy notes (monitoring-vantage-point-rule,process-liveness-vs-protocol-liveness). The latter is the right citation —/accounts/login/proves the WSGI worker, not the celery/consumer workers, and the comment says so.On the CNP claim — conclusion right.
paperless-ns.yaml:24-26admits the wholemonitoringnamespace underendpointSelector: {}with notoPorts;paperless-gate-ingressis additional and Cilium unions allow rules across every CNP selecting an endpoint. Same egress caveat as #976: no CNP inmonitoringdeclares anegress:block, which is the undocumented load-bearing fact.One correction to this PR's reasoning. It describes
gatus/configmap.yaml:182-185as written for gatus. Reading it, the sentence is "the monitoring probes get away without one only because their targets share a namespace with the prober" — that is a claim about the blackbox prober, not gatus. The simpler and true diagnosis is that the comment is wrong/stale:paperless-ns.yaml:24-26already admits all ofmonitoringand its author did not check. That matters, because this PR's entire justification is "that comment is wrong" and it leaves the comment in place — the next person re-derives the phantom CNP requirement. One-line fix, tracked on REN-21.The 302 risk is real and unresolved.
module: http_2xxis the chart default (not declared inhelmrelease-blackbox-exporter.yaml), so redirects are followed and only a final 2xx passes. The kubelethttpGetevidence proves only 200–399. I could not check the live status code — no Prometheus read path. If/accounts/login/returns 302, revert this PR rather than wideningvalid_status_codes; a probe that accepts a redirect to a login page is the exact green-while-broken shape this file exists to prevent.Revert path: this PR's
git revert -m 1 <merge sha>is clean — I tested it (20 → 19, navidrome+lidarr intact). Merged second deliberately, so the higher-uncertainty target gets the conflict-free revert.Not verified: no Prometheus read path.
probe_successandprobe_http_status_codeunseen; recorded as owed on REN-22.Rebase disclosure. I performed the rebase onto master after #976 (commit
cb9e73bd, previouslybdf55c5b). I am the merger, so I am stating exactly what I did to a PR I did not author: the conflict was the two blocks appending at the same insertion point, and I resolved it by deleting the three conflict-marker lines only. I changed no other character. Verified: the 29 added lines are byte-identical to the original commit (diffagainstgit diff d36ffc80 bdf55c5boutput — identical),svc-atlasis preserved as author, and js-yaml reparse givesblackbox-http19 -> 20 with paperless the only addition, nothing removed, no duplicates,blackbox-edge-wan(3) andblackbox-tcp-relays(2) unchanged.Ghost referenced this pull request2026-09-25 19:00:56 +00:00