Files
helm-charts/apache-tika/templates/NOTES.txt
T
jklein ee9ae8a724
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
feat!: NetworkPolicy in six more charts, on by default
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

115 lines
6.3 KiB
Plaintext

{{- $replicas := include "apache-tika.replicas" (dict "scaleDown" .Values.scaleDown "replicas" .Values.tika.replicas) -}}
{{- /* effectiveResources, not resources: an erased "resources:" block falls back
to the chart defaults in the Deployment (#99), so the notes must report the
limits the release actually gets — and the heap figure below is derived from
that same effective limit, not from the raw value. */ -}}
{{- $limits := (include "apache-tika.effectiveResources" .Values.tika.resources | fromYaml).limits | default dict -}}
{{- $memLimit := index $limits "memory" -}}
{{- $svc := printf "%s-%s-service" .Release.Name .Chart.Name -}}
Apache Tika {{ .Chart.AppVersion }} — release {{ .Release.Name }} in namespace {{ .Release.Namespace }}.
ACCESS
This chart creates no Ingress. The server is cluster-internal:
http://{{ $svc }}.{{ .Release.Namespace }}.svc.cluster.local
Mind the port. The Service listens on 80 and forwards to the container's
9998, so consumers are configured without a port — e.g. paperless-ngx:
PAPERLESS_TIKA_ENDPOINT: http://{{ $svc }}.{{ .Release.Namespace }}.svc.cluster.local
To reach it from your machine:
kubectl -n {{ .Release.Namespace }} port-forward svc/{{ $svc }} 9998:80
curl http://localhost:9998/version
curl http://localhost:9998/parsers
/parsers lists every parser the running server actually has — the honest
answer to "why did this file come back empty". This chart has no secrets
and no volumes.
{{ if eq $replicas "0" }}
SCALED TO ZERO
{{ if .Values.scaleDown }}scaleDown: true{{ else }}tika.replicas: 0{{ end }} — the deployment runs with replicas: 0. The Service
keeps its ClusterIP but has no endpoints, so callers fail with "connection
refused" rather than a timeout. Set it back and upgrade to return.
{{ end }}
NO AUTHENTICATION — AND IT PARSES WHATEVER IT IS SENT
Tika has no authentication, and this chart adds none. It is a parser for
untrusted input by nature, and its parsers have a long history of being the
soft spot. Anything that can reach the Service can make this pod open a
file. Keep it cluster-internal; do not put an Ingress in front of it.
THE IMAGE TAG HAS TO KEEP ITS -full SUFFIX
appVersion is pinned to {{ .Chart.AppVersion }}. The "-full" variant is the one that
ships Tesseract OCR (5.5.0, with the languages deu, eng, fra, ita, jpn, osd
and spa) plus the extra parsers; the plain apache/tika:<version> image has
no tesseract binary at all. Overriding the tag without "-full" does not fail
loudly — OCR simply stops happening and scanned documents come back with
empty text.
{{- if $memLimit }}
THE JVM ONLY GETS A QUARTER OF THE MEMORY LIMIT
The server starts without -Xmx, so the JVM derives its maximum heap from the
container limit at MaxRAMPercentage=25. With this release's limit of
{{ $memLimit }} that is roughly {{ include "apache-tika.multiplyQuantity" (dict "quantity" $memLimit "factor" 0.25) }} of usable heap — the number to reason about when
sizing, not the limit itself. Raising tika.resources.requests.memory raises
the limit (limitFactor x request) and the heap along with it.
Text extraction streams rather than buffering, so ordinary documents stay
cheap regardless; the heap is what matters for parsers that have to build a
whole document in memory, and for OCR.
{{- end }}
{{- if .Values.networkPolicy.enabled }}
NETWORKPOLICY IS ACTIVE — WHAT IT CAPS, AND WHAT IT DOES NOT
{{ .Release.Name }}-{{ .Chart.Name }}-networkpolicy selects this workload's pods.
Inbound: TCP 9998 only. Outbound: DNS{{ with .Values.networkPolicy.egress }}{{ with .extraPorts }} plus TCP {{ join ", " . }}{{ end }}{{ end }} — Tika is handed documents and
fetches nothing.
THIS CHART HAS NO INGRESS AND ITS CONSUMERS ARE OTHER PODS. While
networkPolicy.probeSources is empty the 9998 rule has no source selector, so
any pod in the cluster — including a paperless-ngx release in another
namespace — reaches it. Narrowing probeSources restricts that rule, and the
consumers' namespaces must then be listed in networkPolicy.allowedNamespaces
in the same change, or document extraction stops with a connection error on
the paperless side and nothing at all on this one.
Three limits belong in the same breath, because none of them is visible in
the object itself:
- EGRESS IS BY PORT, NEVER BY DESTINATION. A NetworkPolicy matches CIDRs and
selectors and cannot express a hostname, so every egress rule permits its
port to ANY address. That is a limit of the object, not a shortcut — this
cluster's CNI (Canal: Flannel plus Calico) has no FQDN rule either. An
outbound port the chart does not know about is BLOCKED: add it to
networkPolicy.egress.extraPorts, and expect to find out through an
application-level connection error rather than through this object.
{{- if .Values.networkPolicy.probeSources }}
- THE PROBE PATH IS RESTRICTED in this release, because
networkPolicy.probeSources is set to
{{ join ", " .Values.networkPolicy.probeSources }}
Probes come from the IP of the WORKER NODE running the pod. If none of those
CIDRs covers the node this pod lands on, the kubelet's probes are dropped
and THE POD NEVER BECOMES READY — the rollout then times out and the symptom
looks like a broken application. Compare
kubectl -n {{ .Release.Namespace }} describe pod -l app={{ .Release.Name }}-{{ .Chart.Name }}-deployment
against `kubectl get node -o wide`.
{{- else }}
- THE PROBED PORT IS OPEN INSIDE THE CLUSTER. networkPolicy.probeSources is
empty, so that rule carries no source selector at all and any pod the CNI
routes to can reach it. Not from the internet — but this is NOT pod-level
isolation. Narrowing it means listing the worker node IPs in
networkPolicy.probeSources, because the kubelet probes from the node's own
address and the chart cannot know it; a wrong guess there leaves the pod
permanently un-Ready.
{{- end }}
- IT IS ONLY A BOUNDARY WHERE THE CNI ENFORCES POLICIES. Where it does not,
this object is accepted and filters nothing, so everything reads as
configured while nothing is filtered. `kubectl -n {{ .Release.Namespace }} get networkpolicy`
shows the object exists; only a connection attempt from an unrelated
namespace shows that it bites.
Switch it off with networkPolicy.enabled: false.
{{- end }}