The doc comments on the resources and defaultedDict helpers justified the
copy-per-chart with "charts in this repo deliberately have no dependencies".
That rule fell with #214: a dependency is admissible now, just expensive, and
it sits in the README as guideline 14, not 13. The justification still holds,
but its reason is a different one - sharing the helper would mean a library
chart, a second artefact to publish, version and pull for something that
changes about once a year. searxng got that wording in PR #38; this carries it
to the remaining 22 charts, 41 occurrences in all.
Comments only: every touched chart renders byte-identical against its
ci/<chart>/test-values.yaml. Each published chart takes a patch bump,
appVersion and +up suffix untouched; template-chart is never published and
takes none, but is corrected because every new chart inherits from it.
Two repo files carried the same claim at no version cost:
validate-charts.yml explained the all-charts quantity render test with it, and
change-app-version.yml still counted nine images for freesailarr - MediathekArr
made it ten.
Part of #43 — templates/NOTES.txt.
The rule from the approved plan was that a NOTES.txt repeating the values is
worthless, so this one prints what an operator would otherwise look up in the
templates: the rendered URL (or the port-forward command when the Ingress is
off, plus the reason ingress.domain stays required — it is
CORE_DEFAULT_DOMAIN), the two op:// refs together with the exact field names
the 1Password items must carry ("connection-url" and "server-secret", because
the operator names the Secret keys after the item's fields), and the traps of
this chart: the setup page hands the super administrator to whoever reaches
the URL first, migrations run inside the startup probe's window (computed
from the effective probe values), a database outage leaves the pod running
and NotReady because liveness deliberately uses "/", the upload ceiling that
actually bites is the Ingress annotation and not the app's fixed 500mb, /tmp
is an emptyDir counted against the ephemeral-storage limit (computed) so an
oversized upload evicts the pod, and the uploads PVC is an ordinary release
resource that "helm uninstall" deletes. Conditional sections cover scaleDown
/ replicas: 0, more than one replica against the single ReadWriteOnce claim,
and a set zipline.env. No domain is baked into the chart; every host is
rendered from the values, examples use example.com.
Part of #157 — multiplyQuantity.
The null-safe fallbacks pass values through fromYaml, which parses every
number as float64, and Go's "%v" switches float64 to exponential notation
from about 1e6 upwards: a bare "1048576" arrived as "1.048576e+06" and the
render aborted on the suffix check. This is the canonical correction agreed
for all charts, taken over verbatim with this chart's prefix — the input and
the non-integer product now go through a formatNumber helper, and the
toYaml/fromYaml round trip is not touched, since it is not the cause.
Measured against ci/zipline/test-values.yaml on the chart's only resources
path, zipline.resources: before, both requests.memory=1048576 and
requests.ephemeralStorage=1048576 aborted with
unsupported resource quantity suffix "e+06" in "1.048576e+06"
after, they render with the limits "3145728", while the 65536 fallback probe
still yields 196608 unchanged. Rendered manifests are byte-identical to the
previous version for the default values.
Sets seccompProfile.type: RuntimeDefault in the pod security context of
minecraft-router, outline, urlaubsverwaltung, zipline, voucher-vault,
satisfactory, patchmon and calibre-web-automated, so the container
runtime's default syscall filter applies to every container in the pod.
The value lives in the pod context rather than the container context
because it covers init containers and any container added later without
being repeated; a container that needs a different filter can still
override it under securityContext.container, which wins over the pod
value.
Five of the eight also get the docker.io/ prefix on their previously
unqualified image references, so the pull no longer depends on the
runtime's default-registry setting: itzg/mc-router,
outlinewiki/outline, urlaubsverwaltung/urlaubsverwaltung,
l4rm4nd/vouchervault (twice, app and init container) and
guacamole/guacd:1.6.0. zipline, satisfactory and calibre-web-automated
were already qualified with ghcr.io.
Verified in a throwaway k3d cluster against real application work, not
just a Running pod, and with Seccomp: 2 (filter mode) read from
/proc/<pid>/status inside each container:
- minecraft-router: a Minecraft handshake for a mapped domain travels
through the router to a backend and the backend's status payload comes
back to the client.
- outline: all migrations apply (45 tables), OIDC discovery succeeds and
the server-rendered page answers 200 with <title>Outline</title>.
- urlaubsverwaltung: Liquibase applies 79 changesets (35 tables), the app
seeds its settings and vacation types, /login answers 200.
- zipline: 27 migrations applied, then a full round trip - first user
created, login, token, upload, and the file downloaded back byte-exact
from the PVC.
- voucher-vault: the init container's collectstatic output is served
(200, 22 KB), Django has its 22 tables and uWSGI answers 200 with
<title>VoucherVault</title>.
- satisfactory: application behavior is NOT proven - the image is
multiple GB and pulls 10 GB+ of game files on first start, which is why
the chart sits in ci/excluded-charts.txt. What is proven is that the
rendered pod securityContext is accepted server-side and yields
Seccomp: 2 with uid/gid 1000 on a substitute image.
- patchmon: both containers run under the pod profile and both report
Seccomp: 2. The server applies 47 migrations (44 tables), connects to
Postgres and Redis and serves its dashboard; guacd answers a real
Guacamole "select rdp" instruction with its full args list, over the
same 127.0.0.1:4822 path the chart wires up.
- calibre-web-automated: the readOnlyRootFilesystem: false deviation is
unaffected - id abc is still uid 1000 (not the 911 the image falls back
to in read-only mode), /config and the Calibre metadata.db are owned by
1000, and both the root s6 init and the uid-1000 application report
Seccomp: 2. calibredb 9.1 runs and adds a book. Its IPC worker prints a
traceback while doing so, but an unconfined control pod on the same
image prints the same class of traceback, so it is not the filter.
trivy config now reports "0 to act on" for all eight; the untouched
samba still shows KSV-0104 and KSV-0030, which confirms these charts are
what closed the findings.
No values.schema.json needed changing: in all eight schemas
securityContext.pod is type ["object", "null"] with no property
restrictions, so the new key validates as it stands. The #99 null paths
still hold - nulling securityContext or securityContext.pod falls back to
the defaults including the new one.
Renovate resolves the prefixed guacd reference: a local dry-run lookup
(renovate 44.40.1, --platform=local --dry-run=lookup) reports depName
docker.io/guacamole/guacd against registryUrl https://index.docker.io
with lookupName guacamole/guacd, currentVersion 1.6.0 and its real
release timestamp, with no warnings. The other four prefixed references
live in templates, which Renovate never reads - they are tracked by the
customManagers via appVersion in Chart.yaml with a depName hardcoded in
renovate.json5, so they are unaffected.
Major bump for all eight: runtime behavior changes.
Refs #84
Three changes, all about values that do not do what they promise:
1. values.schema.json (#68): additionalProperties: false on every
chart-owned object level, so a key the chart does not read is rejected
at render time instead of being silently ignored.
2. Ingress gate (#93): the Ingress template is wrapped in
{{- if .Values.ingress.enabled }} and the key is added to values.yaml
with default true, so behaviour is unchanged.
As in rallly, ingress.domain is not a pure Ingress value: the
StatefulSet also feeds it to CORE_DEFAULT_DOMAIN, the app's default
domain for generated share links, and did so without required(). The
guarantee only came from the ungated Ingress template, so the gate
would have handed out unusable links silently. That read is now
required() as well; only clusterIssuer becomes unnecessary.
3. Null-safety for hardening, probes and resources (#99): an erased block
fell back to "securityContext: null" (unhardened), a vanished probe or
a container without resource accounting. The rebuilt liveness probe
keeps "/" rather than /api/healthcheck, so a database outage still does
not restart the pod.
config stays deliberately not null-safe: storage and storageClass are
required(), which puts an erased block in the loud class #99 excludes.
Apart from an added comment, the rendered manifest is unchanged.
Repo-standard flexible ingress (required clusterIssuer instead of the
hardcoded letsencrypt-issuer, domain moved from config.domain to
ingress.domain, className value, annotations merge, standard TLS secret
name), secrets.<name>SecretRef structure, core secret renamed to the
standard -secret name, additive tpl-rendered env block, documented PVC
naming exception. Major bump 4.1.2+up4.7.0 -> 5.0.0+up4.7.0.
- Add icon: to all 17 Chart.yaml (official project icons); removes the
last helm lint --strict INFO finding across the repo
- Rename template files to the <app>.<kind>.yaml scheme (apache-tika,
gotenberg, teamspeak-server PVC, paperless-ngx configmap) - pure
git mv, no content changes
- template-chart: fix missing space in {{ .Chart.Name}} and rename the
ConfigMap resource -config-map -> -configmap (chart is never published)
- rallly: fix typos in required messages (rallySecret -> ralllySecret,
databseSecret -> databaseSecret)
- README: document the deliberate PVC-name exception from the naming
scheme (renames would provision new empty volumes)
- Patch-bump all 16 published charts
Rendered resources are byte-identical for all published charts (only
helm's '# Source:' comments change for the renamed files); the only
render change is the template-chart ConfigMap name.
Part of #32
Nine non-critical app-version bumps, each with a chart patch bump:
- apache-tika 3.2.3.0-full -> 3.3.1.0-full
- gotenberg 8.26.0 -> 8.36.0
- matrix-synapse v1.149.1 -> v1.159.0
- rallly 4.8.1 -> 4.12.3
- samba 4.23.5 -> 4.23.10
- urlaubsverwaltung 6.5.0 -> 6.7.0
- voucher-vault 1.27.4 -> 1.30.1
- zipline 4.6.4 -> 4.7.0
- teamspeak-server v6.0.0-beta8 -> 6.0.0-beta12.1 (new tag format has no v prefix)
Release notes of every chart were checked for environment-variable
changes; none of the charts needs an env adjustment.
The teamspeak-server install-test is reactivated: beta12.1 ships a
valid default license, so the exclusion is removed, CI fixtures are
added under ci/teamspeak-server/, and the install-test was verified
in a local k3d cluster. README list of excluded charts updated.
Every Deployment/StatefulSet now takes its replica count from a replicas
value (default 1, explicit 0 allowed) via a new per-chart <chart>.replicas
helper; the helper uses a kindIs "invalid" nil check so an explicit 0 is
not swallowed by Helm's default function. A chart-global scaleDown flag
(default false) takes precedence: it renders every workload with
replicas: 0 and suspends the paperless-ngx consume CronJob, stopping the
app without uninstalling it (PVCs, Secrets, Services and Ingress remain).
Defaults leave the rendered manifests byte-identical to main, so all
published charts get a minor version bump; the template-chart carries the
reference helper implementation and stays unversioned.
Fixes#25
Every chart now renders its container resources through a duplicated
_helpers.tpl helper (reference implementation in template-chart): requests
ship as chart defaults, missing memory and ephemeral-storage limits are
computed as resources.limitFactor x the request (default 3, satisfactory
keeps 2 to preserve its previously published 8Gi limit), an explicitly set
limit always wins, and a CPU limit is only rendered when set explicitly.
Fixed limit defaults are removed from all values.yaml files; teamspeak-server
gains a values-driven resources block instead of hardcoded template values.
Major version bump for all published charts.
Add securityContext hardening (runAsNonRoot, readOnlyRootFilesystem,
capabilities drop ALL, allowPrivilegeEscalation false) to the 10 workloads
that lacked it: apache-tika, cyberchef, gotenberg, homeassistant,
matrix-delegation-nginx, paperless-server, paperless-consume cronjob
(plus automountServiceAccountToken false), patchmon-frontend,
urlaubsverwaltung and zipline. All contexts are configurable via
securityContext.pod / securityContext.container in values.yaml; writable
paths are provided as emptyDirs. Image-forced deviations (Home Assistant
root start for s6-overlay + NET_RAW for discovery, paperless root init
container for /run ownership) are documented in the charts' values.yaml.
Major version bump for every changed published chart.
Every container in every Deployment/StatefulSet now defines all three
probes. The paperless-ngx consume CronJob intentionally has none (batch
workload).
- Add probes: apache-tika, calibre-web-automated, cyberchef, gotenberg,
homeassistant, patchmon-backend, samba (tcp/445), teamspeak-server
(tcp/30033), zipline (/api/healthcheck)
- Fix voucher-vault null probe values with real defaults
- Fix startup-probe semantics in template-chart and rallly (no
initialDelaySeconds, generous failureThreshold)
- Switch outline probes to its /_health endpoint
- Add readiness/startup probes to satisfactory
- Add startup probes to matrix-synapse, matrix-delegation-nginx,
paperless-server, patchmon-frontend, urlaubsverwaltung
- Major version bump for all published charts