Commit Graph
4 Commits
Author SHA1 Message Date
jklein ee9ae8a724 feat!: NetworkPolicy in six more charts, on by default
Install-test / Install-test apache-tika (pull_request) Successful in 1m21s
Install-test / Install-test bentopdf (pull_request) Successful in 1m16s
Install-test / Install-test cyberchef (pull_request) Successful in 1m6s
Install-test / Install-test gotenberg (pull_request) Successful in 1m32s
Install-test / Install-test outline (pull_request) Failing after 1m16s
Install-test / Install-test rss-bridge (pull_request) Successful in 1m1s
Install-test / Install-test searxng (pull_request) Successful in 1m13s
Validate Helm Charts / Install-test (pull_request) Failing after 9m57s
Install-test / Install-test ytdlp-web-player (pull_request) Successful in 1m11s
Validate Helm Charts / Detect changed charts (pull_request) Successful in 3s
Validate Helm Charts / Resource quantities (pull_request) Failing after 18s
Validate Helm Charts / HTTPRoute match (pull_request) Failing after 13s
Validate Helm Charts / Selector match (pull_request) Failing after 17s
Validate Helm Charts / Bump level (pull_request) Successful in 8s
Validate Helm Charts / YAML scalars (pull_request) Failing after 16s
Validate Helm Charts / NetworkPolicy (pull_request) Failing after 9s
Validate Helm Charts / Build apache-tika (pull_request) Successful in 5s
Validate Helm Charts / Trivy config apache-tika (pull_request) Successful in 13s
Validate Helm Charts / Build bentopdf (pull_request) Successful in 5s
Validate Helm Charts / Build cyberchef (pull_request) Successful in 6s
Validate Helm Charts / Build outline (pull_request) Successful in 5s
Validate Helm Charts / Build template-chart (pull_request) Successful in 5s
Validate Helm Charts / Trivy config outline (pull_request) Failing after 12s
Validate Helm Charts / Trivy config searxng (pull_request) Successful in 15s
Validate Helm Charts / Trivy config template-chart (pull_request) Successful in 14s
Validate Helm Charts / Build gotenberg (pull_request) Successful in 5s
Validate Helm Charts / Build rss-bridge (pull_request) Successful in 5s
Validate Helm Charts / Build searxng (pull_request) Successful in 5s
Validate Helm Charts / Build ytdlp-web-player (pull_request) Successful in 5s
Validate Helm Charts / Trivy config bentopdf (pull_request) Successful in 14s
Validate Helm Charts / Trivy config cyberchef (pull_request) Successful in 13s
Validate Helm Charts / Trivy config gotenberg (pull_request) Successful in 13s
Validate Helm Charts / Trivy config rss-bridge (pull_request) Successful in 14s
Validate Helm Charts / Trivy config ytdlp-web-player (pull_request) Successful in 15s
bentopdf, apache-tika, gotenberg, rss-bridge, searxng, ytdlp-web-player. One
major each, networkPolicy.enabled defaults to true.

Three of them differ from the simple case in ways worth naming:

GOTENBERG gets DNS-only egress as a deliberate, documented trade. It drives a
headless Chromium, and 3000 is its probe port - so it is reachable from the
whole cluster by default, and an egress rule for 80/443 would turn a service
anyone can POST to into a way of fetching arbitrary URLs. The price is the
remote-asset half of HTML conversion: inline content converts, images the page
would have fetched silently do not. That degrades a PDF instead of failing a
pod, so nothing alerts on it, which is why it is in the template header, in
values.yaml and in NOTES.txt, with extraPorts: [80, 443] named as the knowing
opt-in.

RSS-BRIDGE, SEARXNG and YTDLP-WEB-PLAYER get the open internet on their web
ports, because reaching other people's servers IS the application and this
object cannot name a host. Said plainly in each, so none of them reads
stricter than it is. What the cap still buys is real: no other outbound port,
so a compromised pod reaches no database, no mail server and no SSH anywhere.

APACHE-TIKA and GOTENBERG render no Ingress - their consumers are other pods,
in other namespaces here - so neither gets an ingressController value and both
say in NOTES.txt that narrowing probeSources means listing the consumers'
namespaces in allowedNamespaces in the same change, or extraction and
conversion stop.

YTDLP-WEB-PLAYER names the gap this convention has: its oauth2-proxy subchart
renders its own Deployment with its own labels and ships no policy, so with the
proxy enabled the pod that actually faces the Ingress is unrestricted in both
directions. Nothing in this chart can change that - an upstream chart is
consumed as it comes - so it is written down instead.

ci/outline/test-values.yaml gains egress.extraPorts: [5556]. The CI dex runs
there rather than on 443, and Outline fetches the discovery document at boot -
so this is the chart's documented escape hatch used for exactly the case it was
written for, and the one place in the repo where the cap's upgrade risk is
actually exercised.

Part of #5
2026-10-14 14:20:39 +00:00
jklein e4b41577ae feat(ytdlp-web-player): Gateway-API as an alternative to the Ingress
Group 3 of the #114 sweep, last chart - and the one that carried the group-2
pattern this sweep was told to look for. It reads ingress.enabled OUTSIDE its
Ingress template, in ytdlp-web-player.validate, and in Gateway mode
ingress.enabled is false by construction, so that guard would have gone
silent. Fixed with ytdlp-web-player.published = ingress.enabled OR
httpRoute.enabled - the freesailarr.published / sure.publishedOverTls shape,
identical to ingress.enabled while httpRoute.enabled is false, which is why it
changes no existing render.

AND THE GUARD IS NEEDED MORE IN GATEWAY MODE, NOT LESS. It refuses to publish
the application and the oauth2-proxy on the same host:

  - In INGRESS mode the consequence of ignoring it is loud: ingress-nginx's
    admission webhook rejects the second Ingress and the Fleet bundle goes to
    ErrApplied.
  - In GATEWAY mode THE WEBHOOK NEVER FIRES. It compares Ingress objects with
    Ingress objects, and an HTTPRoute is a different kind - so nothing rejects
    anything, both objects stay valid, and one hostname is served over two
    data paths that are NOT equivalent: the proxy's Ingress goes through
    AUTHENTICATION and this chart's HTTPRoute goes straight to the
    application. Which one a client reaches depends on what DNS resolves to.
    That is an authentication bypass that comes and goes with a DNS record and
    that no Kubernetes object reports.

So the Gateway-mode abort has its own message saying exactly that. Both
messages exercised, plus the collision reached through httpRoute.hostnames
rather than through the ingress.domain fallback, and the guard still firing
when only the Deployment is rendered.

THE SUBCHART HAS NO GATEWAY SUPPORT, and this chart cannot give it one -
upstream's chart is consumed as it comes (README, "Chart dependencies"). It
renders an Ingress or nothing. So in the RECOMMENDED configuration, where the
proxy sits in the data path and owns the host, the publishing object is the
SUBCHART'S INGRESS in both of this chart's modes, and turning httpRoute on
buys nothing. The route is for the proxy-disabled case, or for the application
on a host of its own - which is the documented unauthenticated bypass. Said in
the template header, in values.yaml, in the schema and in the proxy branch of
NOTES.txt, because someone migrating hosts will otherwise set the value and
wonder why nothing moved.

The 16k proxy-buffer-size this chart recommends is NOT lost by this switch,
and that needed stating rather than assuming: it belongs on the PROXY's
Ingress (oauth2-proxy.ingress.annotations) as the second half of the 4kB
session-cookie trap, and the subchart keeps rendering an Ingress. This chart's
own ingress.annotations default is {} and it sets nothing but the cert-manager
annotation, so there is no chart-side annotation loss to name.

CORRECTED CLAIM: values.yaml and the schema both said that everything the
Ingress needs is read only inside its template, so switching it off freed BOTH
ingress.domain and ingress.clusterIssuer. clusterIssuer is still freed; domain
is now read by the HTTPRoute, so it is freed only with both modes off. The
reason the claim was made still holds and is kept - the application has no
base-URL setting and builds no absolute links.

NOTHING WAS MEASURED ON A LIVE INGRESS OF THIS CHART, because there is none.
Measured 2026-10-12: the release runs in namespace jlab-player with both
Deployments Ready, and NOT ONE of the cluster's 23 Ingress objects is in that
namespace - neither this chart's nor the subchart's. What publishes it instead
could not be determined: this workspace's identity may not list httproutes or
secrets, so neither a hand-written HTTPRoute nor the release's Helm values are
readable. Recorded as the open question it is, in values.yaml and in the
overlay, rather than guessed at.

Minor: additive, defaults unchanged. Empty helm template diff against
origin/main with ci/ytdlp-web-player/test-values.yaml.

Part of #114
2026-10-13 08:59:09 +00:00
jlab-renovate-bot caea6e7353 Update Helm release oauth2-proxy to v10.7.1
renovate/stability-days Updates have met minimum release age requirement
Validate Helm Charts / Detect changed charts (pull_request) Successful in 7s
Validate Helm Charts / Resource quantities (pull_request) Successful in 25s
Validate Helm Charts / Build ytdlp-web-player (pull_request) Successful in 9s
Validate Helm Charts / Trivy config ytdlp-web-player (pull_request) Successful in 40s
Install-test / Install-test ytdlp-web-player (pull_request) Successful in 2m6s
Validate Helm Charts / Install-test (pull_request) Successful in 2m6s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 37s
Publish YTDLP Web Player Helm Chart / Publish YTDLP Web Player Helm Chart (push) Successful in 36s
SonarQube Analysis / SonarQube Analysis (push) Successful in 31s
2026-10-04 13:15:31 +00:00
jklein 6b0d8c9232 ytdlp-web-player: new chart with an optional oauth2-proxy subchart (1.0.0+upv1.2.0)
Deploys matszwe02/ytdlp_web_player, a Flask app that fetches videos with
yt-dlp, transcodes them with ffmpeg and serves them as HLS. It ships no
authentication of any kind, so the chart carries a preconfigured oauth2-proxy
as an optional subchart, in the data path in front of the app.

This is the first chart in the repo with a dependency, so the rule "charts
have no dependencies" falls here. It is replaced in CLAUDE.md and README.md by
a bar: a dependency has to be optional and off by default, upstream's chart is
consumed as it comes (documented where it falls short of our conventions,
never patched), and the price is written down - above all that a subchart is
invisible to everything downstream watching Helm release versions, so a new
proxy release only reaches a cluster when this chart is republished.

CI learns the dependency in five places, not the three the plan expected:
helm lint, package, template and install all exit 1 while charts/ is unfilled,
so ci/helm-dependencies.sh runs before lint and package in validate-charts.yml,
before package in publish-helm-chart.yml, and inside run-install-test.sh,
run-trivy-config.sh and run-quantity-render-test.sh - the last of which renders
every chart on every PR and would have gone red first.

Notable chart decisions, each measured rather than assumed:

- The image has no USER and runs as root by default, but not by necessity: it
  runs under an arbitrary uid with readOnlyRootFilesystem and the full
  hardening baseline. Only the pinned uid is a deviation, and it is documented.
- Two emptyDirs, each justified separately. /data holds the video cache
  (DATA_PATH). /tmp is NOT mounted - measured across metadata extraction, HLS
  transcoding, sprite generation and audio extraction, the image never writes
  there. What it does write is $HOME/.cache, so /cache is mounted with HOME and
  XDG_CACHE_HOME pointed at it; without it yt-dlp re-downloads its JavaScript
  challenge-solver from github.com on every extraction.
- The proxy is wired through config.configFile, the only value the subchart
  passes through tpl - config.upstreams is emitted with toJson and would carry
  a literal {{ .Release.Name }} into the manifest.
- Rendering aborts when this chart's Ingress and the proxy's claim the same
  host: ingress-nginx rejects the second one and a Fleet bundle then sits in
  ErrApplied until forceSyncGeneration is bumped.

Fixes #214
2026-08-30 17:34:49 +02:00