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 #157: multiplyQuantity turned a bare integer resource value into
exponential notation and aborted the render. The null-safe helpers pass
values through fromYaml, which makes every number a float64, and Go's "%v"
switches float64 to exponential form from about 1e6 upwards - so
"1048576" arrived as "1.048576e+06" and the suffix check failed. A new
outline.formatNumber helper renders such a value as a plain decimal
string; it is applied to the input and to the non-integer product. This is
the canonical fix agreed for the issue, taken over unchanged so the copies
of the helper in all charts stay identical.
Part of #43: the chart gets a NOTES.txt. It renders the access URL (or the
port-forward command when the Ingress is off), lists the fields each of the
three 1Password items has to carry plus the OIDC redirect URI, and states
the traps that are otherwise found the hard way: editing a value inside a
1Password item restarts nothing, Postgres and Redis are external and
unencrypted by default, migrations run inside the startup probe's budget,
uploads sit on a single RWO volume that helm uninstall takes with it, the
Ingress body-size limit is ten times smaller than the app's, and the chart
configures no mail at all.
Minor bump: the fix changes no rendered output for any value the schema
accepted before, and a NOTES.txt renders no object.
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
No ingress gate: this chart already gates its Ingress correctly. Two
changes plus one guard the existing gate turned out to need.
1. values.schema.json (#68): additionalProperties: false on every
chart-owned object level.
2. Null-safety for hardening, probes and resources (#99). All three
probes keep /_health when rebuilt: it is Outline's only health
endpoint, and "/" returns 500 as well when the database is down, so
there is no dependency-free path to fall back to.
3. ingress.domain is required() where the StatefulSet reads it. It feeds
the URL env var - Outline's public URL for generated links and the
OIDC redirect URI - and did so without a guard. With the existing gate
and no domain it rendered "https://", breaking logins silently. That
hole predates this change; it now fails loudly.
outline.storage stays deliberately not null-safe: an erased block yields
an invalid PVC, which is the loud class #99 excludes.
Apart from an added comment, the rendered manifest is unchanged.
- apache-tika, gotenberg, cyberchef, homeassistant, patchmon: additive env
value blocks rendered through tpl (value, secretKeyRef and configMapKeyRef
forms), following the template-chart/outline pattern; patchmon gets separate
blocks for the server container and the guacd sidecar.
- homeassistant: ingress.className now defaults to nginx; an empty className
omits ingressClassName from the rendered Ingress, so the flexible upstream
ingress style stays intact.
- outline, paperless-ngx: remove the ingress.clusterIssuer defaults
(letsencrypt / letsencrypt-issuer) - the value is now strictly required,
consistent with the repo-wide ingress standard; CI test-values set it
explicitly.
Chart bumps: apache-tika 7.2.0, gotenberg 4.2.0, cyberchef 5.2.0,
patchmon 5.2.0, homeassistant 4.2.0 (minor); outline 5.0.0,
paperless-ngx 10.0.0 (major).
- Pod and container securityContext are now values-configurable
(outline.securityContext.pod/container) with hardened defaults:
runAsNonRoot (uid/gid 1001, the upstream image's nodejs user),
readOnlyRootFilesystem, allowPrivilegeEscalation false, all
capabilities dropped. /tmp is mounted as an emptyDir for Outline's
import/export scratch files.
- Probes moved to values (outline.livenessProbe/readinessProbe/
startupProbe); defaults are exactly the previously hardcoded ones.
- Ingress raised to the repo standard: ingress.className (default
nginx), ingress.annotations merged with the always-set annotations,
ingress.enabled flag; domain/clusterIssuer stay required and the
TLS secret name was already conform.
- Additive outline.env block rendered through tpl with value/
secretKeyRef/configMapKeyRef forms; chart-managed env stays in the
template.
Major bump 3.1.1+up1.9.2 -> 4.0.0+up1.9.2 (runtime behavior changes
through hardening).
Part of #32
- 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
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.
Every chart was installed twice in a throwaway k3d cluster (origin/main
vs this branch) with real Postgres/Redis/dex instances and observed for
readiness ordering, stability and dependency-outage behavior. Findings:
- voucher-vault: Django only accepts Hosts 127.0.0.1 and the configured
DOMAIN; the default probe Host (pod IP) always got 400. Probes now
send 'Host: 127.0.0.1'.
- zipline: /api/healthcheck includes the database, so liveness now uses
'/' (readiness/startup keep /api/healthcheck). Verified live: on a
Postgres outage the pod turns NotReady within 30s and is never
restarted by the kubelet.
- outline: '/' also returns 500 when the database is down, so there is
no dependency-free endpoint; all three probes use /_health.
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