samba.globalConfig has been part of values.yaml since the chart's first
commit but is read by no template. Setting it never had an effect.
Rather than implement it, the key is removed and the strict schema now
rejects it: additionalProperties is already false on the samba object, so
dropping the property turns a silently ignored key into a render-time
error.
Operationally inert: neither the cluster-smb fleet bundle nor the deployed
release's user-supplied values set the key -- it only ever appeared as the
chart's own null default.
Major, because a published value disappears and is now rejected.
Fixes#117
No ingress gate: this chart has no Ingress at all (clients reach it via a
NodePort), and ingress.domain appears neither in its templates nor in its
values.
1. values.schema.json (#68): additionalProperties: false on every
chart-owned object level, including the entries of the mappings list,
where domain and internalUrl are required.
2. Null-safety for hardening, probes and resources (#99). Two things a
rebuilt default probe must not lose, both verified:
- the API port is addressed by NAME ("api-port"), so the probe keeps
working when server.apiPort is overridden.
- mc-router still has no /health endpoint in 1.46.4, so GET /routes is
the health signal, and the "Accept: application/json" header belongs
to that request.
The pod context keeps pinning uid/gid 10000 even though the image
declares USER 65532 since 1.46.0, so the runtime identity does not
silently change with the base image.
mappings stays deliberately not null-safe: the chart fails loudly on a
missing or empty routing table, which is the loud class #99 excludes - a
router without routes is not operable and has no sensible default.
Rendering with normal values is byte-identical to 2.0.0.
No ingress gate change: this chart already honours ingress.enabled, and
its ingress block keeps the upstream-style host/tls lists that the README
documents as an exception. The schema models that shape as it is instead
of pushing the repo's domain/clusterIssuer pair onto it, and the list
entries stay open because they go verbatim into the Ingress spec.
The domain checkpoint ran over values.yaml and templates and came back
empty: ingress.domain does not exist in this chart at all.
1. values.schema.json (#68): additionalProperties: false on every
chart-owned object level. Pod-spec passthrough (volumes, volumeMounts,
nodeSelector, tolerations, affinity, ingress hosts/tls) stays open.
2. Null-safety for hardening, probes and resources (#99).
This chart's hardening is a documented deviation and the fallbacks
reproduce it exactly: the pod context is deliberately EMPTY, because
the official image must start as root (s6-overlay does its setup as
uid 0 and the image has no non-root user), and capabilities.add keeps
NET_RAW, without which device discovery (DHCP watcher, ping/arp
integrations) logs "Operation not permitted".
core.storage stays deliberately not null-safe: an erased block yields an
invalid PVC, which is the loud class #99 excludes.
The #82 limitation around the 1Password-backed config Secret is
untouched: Helm never sees the content, so it cannot be hashed, and the
values.yaml note about the manual rollout restart stays as it is.
Rendering with normal values is byte-identical to 5.0.0.
No ingress gate: this chart has no Ingress at all (SMB and NetBIOS are
exposed via NodePort), and ingress.domain appears neither in its
templates nor in its values.
1. values.schema.json (#68): additionalProperties: false on every
chart-owned object level, including the entries of the samba.shares
list.
2. Null-safety for hardening, probes and resources (#99).
This chart's hardening is a documented deviation forced by the
ghcr.io/dockur/samba image, and the fallbacks reproduce it exactly
instead of restoring the repo standard: no runAs* values (the
entrypoint creates Unix users and smbd impersonates the share user per
session, both requiring a root start), readOnlyRootFilesystem stays
false (the entrypoint writes /etc/passwd, /etc/group, the healthcheck
symlink and the Samba TDBs), and capabilities.add keeps the six
entries a multi-user root file server needs. Restoring the standard
here would stop the file server from working.
The probes target the SMB TCP port directly, because SMB is not HTTP.
The users.conf / checksum-config limitation from #82 is untouched: Helm
never sees the Secret content, so it cannot be hashed, and the comment in
values.yaml documenting the manual rollout restart stays as it is.
Rendering with normal values is byte-identical to 5.0.0.
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.
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.
The domain checkpoint from rallly ran over values.yaml and templates
and came back empty here: ingress.domain is read nowhere but in the
Ingress template. Unlike rallly, zipline, voucher-vault and outline,
this gate therefore frees both domain and clusterIssuer, and no extra
required() is needed.
3. Null-safety for hardening, probes and resources (#99).
This chart's hardening is a documented deviation from the repo
standard, and the fallbacks reproduce it exactly instead of restoring
the standard: no runAs* values (s6-overlay boots as root and drops to
PUID/PGID 1000), readOnlyRootFilesystem stays false (read-only mode
disables the PUID/PGID remapping, silently moving the runtime uid from
1000 to 911 and breaking existing volume data), and capabilities.add
keeps its six entries that the s6 init and supervision need. A
"cleaned up" standard default here would not be tidier, it would be an
outage.
cwa.storage stays deliberately not null-safe: an erased value yields an
invalid PVC, which is the loud class #99 excludes.
Rendering with normal values is byte-identical to 4.0.0.
No ingress gate: this chart has no Ingress at all (game and messaging
ports are exposed via NodePort), and ingress.domain appears neither in
its templates nor in its values.
1. values.schema.json (#68): additionalProperties: false on every
chart-owned object level. Like teamspeak-server, this chart keeps env,
probes and securityContext at the TOP level, and the schema mirrors
that shape.
2. Null-safety for hardening, probes and resources (#99). What a rebuilt
default must not lose here:
- liveness and startup run the image's own healthcheck script via
exec. It queries the server's HTTPS API on SERVERGAMEPORT, so it
survives a port override, which a tcpSocket default could not.
- readiness keeps the named "api" port.
- the resources default keeps limitFactor 2 rather than the repo-wide
3, which is what holds the memory limit at the published 8Gi.
- the pod context keeps fsGroupChangePolicy OnRootMismatch, which is
what avoids a recursive chown of multi-GB game files on every start.
server.storage stays deliberately not null-safe: an erased value yields
an invalid PVC, which is the loud class #99 excludes.
This chart is excluded from the CI install-test, so the local proof is
the only one. Rendering is byte-identical to 4.0.0 with default values
and with the production bundle values, and the rendered manifests were
additionally validated by the cluster's API server via a server-side
dry-run.
No ingress gate: this chart has no Ingress at all (voice/file-transfer
are exposed via NodePort), and ingress.domain appears neither in its
templates nor in its values.
1. values.schema.json (#68): additionalProperties: false on every
chart-owned object level. Note that this chart keeps replicas,
resources, probes and securityContext at the TOP level rather than
under a chart-named key, so the schema mirrors that shape.
2. Null-safety for hardening, probes and resources (#99). The rebuilt
probes keep the "file-transfer" port name: the voice service is UDP
and cannot be probed, so that TCP port is the only thing a probe can
target - a default probe without it would leave the workload with no
working probe at all.
The container defaults keep capabilities.add as an empty list, exactly
as values.yaml has it, so an erased block restores today's rendering
byte for byte rather than a cleaned-up variant.
storage stays deliberately not null-safe: an erased block yields an
invalid PVC, which is the loud class #99 excludes.
Rendering with normal values is byte-identical to 4.0.0.
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.
No ingress gate: this chart already gates its Ingress correctly. Two
changes plus one guard that the existing gate turned out to need.
1. values.schema.json (#68): additionalProperties: false on every
chart-owned object level. Lists that go verbatim into the pod spec
(ports, storage.volumes, storage.volumeMounts) stay open.
2. Null-safety for hardening, probes and resources (#99). Two specifics
of this chart:
- The probes were wrapped in "if" guards, so an erased probe block did
not render "livenessProbe: null" - it removed the probe entirely and
silently. The guards are gone; an empty block now means chart
defaults, so the workload keeps its probes.
- The rebuilt probes keep the Host: 127.0.0.1 header. Django's
ALLOWED_HOSTS only accepts 127.0.0.1 and the configured DOMAIN, so a
probe without it would get 400 and the pod would never be ready.
3. ingress.domain is required() where it is read. The dependency lives in
values.yaml, not in a template: the DOMAIN env entry is a tpl string
feeding Django's ALLOWED_HOSTS. With the existing gate and no domain
the app rendered DOMAIN: "" and answered 400 to every real request -
silently, and already before this change. It now fails loudly.
Apart from an added comment, the rendered manifest is unchanged.
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.
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.
ingress.domain is NOT a pure Ingress value here - it is also the app's
public base URL (NEXT_PUBLIC_BASE_URL). Gating alone would therefore
have introduced a new silent failure: with the Ingress switched off and
no domain, the deployment rendered value: "https://" and every
generated link would be broken. The deployment's read of the value is
now required(), so that case fails loudly. Only clusterIssuer actually
becomes unnecessary when the Ingress is off.
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. Restoring the pod context
matters especially here, because its fsGroup is what makes the Next.js
cache emptyDir group-writable for the container.
rallly.cache is deliberately NOT null-safe: cache.path is required(), so
an erased block fails loudly and belongs to the loud class #99 excludes.
Apart from an added comment, the rendered manifest is unchanged.
Records the reasoning inline, matching the comment the gotenberg chart
carries, so the next edit does not quietly switch back to the raw helper and
drop the paragraph whenever a resources: block has been erased.
Tika has no Ingress, so the notes lead with the cluster-internal URL, the
Service-port-80 to container-port-9998 mismatch a consumer has to get right,
and /parsers as the direct answer to "why did this file come back empty".
Two warnings come from measuring the running container rather than from
reading the values file:
- The image tag has to keep its "-full" suffix. That variant is where
Tesseract 5.5.0 and the extra parsers live; the plain image carries no
tesseract binary at all, so dropping the suffix does not fail loudly, it
just stops OCR and returns empty text for scans.
- The JVM never sees the container limit. It starts without -Xmx and derives
its heap from the limit at MaxRAMPercentage=25, so the number worth sizing
against is a quarter of it.
The heap figure is computed from the effective limit through the chart's own
null-safe effectiveResources helper, so an erased resources: block still
prints the defaults the container actually receives instead of dropping the
paragraph. Refs #43.
Retrofit of #99 for a chart that already carries a values.schema.json,
plus the schema type change that goes with it.
An override written without children is YAML null. Where the chart
defines a default, Helm's coalescing deletes the default before schema
validation runs, so the schema never sees the null and cannot reject it:
the container rendered "securityContext: null" - unhardened, healthy,
silent. Where the chart defines no default (resources.limits), the null
survives into validation and a strict "object" type aborted the render.
The defaultedDict helper from #96 handles the first case; widening the
types of exactly these blocks to ["object", "null"] handles the second.
All other keys stay strict, additionalProperties: false is untouched.
The probes address the container port by name, so a rebuilt default probe
needs no further context.
Rendering with normal values is byte-identical to 5.0.0.
Retrofit of #99 for a chart that already carries a values.schema.json,
plus the schema type change that goes with it.
An override written without children is YAML null. Where the chart
defines a default, Helm's coalescing deletes the default before schema
validation runs, so the schema never sees the null and cannot reject it:
the container rendered "securityContext: null" - unhardened, healthy,
silent. Where the chart defines no default (resources.limits), the null
survives into validation and a strict "object" type aborted the render.
The defaultedDict helper from #96 handles the first case; widening the
types of exactly these blocks to ["object", "null"] handles the second.
All other keys stay strict, additionalProperties: false is untouched.
The probes address the container port by name, so a rebuilt default probe
needs no further context.
Rendering with normal values is byte-identical to 8.0.0.
Gotenberg has no Ingress, so the notes lead with the cluster-internal URL and
point out that the Service listens on 80 while the container listens on 3000
— the mismatch a consumer such as paperless-ngx has to get right — plus the
port-forward command for reaching it by hand.
Three findings from measuring the running chart went in as warnings:
- The chart passes no command-line flags, so Gotenberg's basic auth, OIDC,
SSRF guards and request timeout cannot be enabled through values at all.
- Memory, not disk, is the first limit to hit: at the default limit a large
document gets the container OOM-killed, the caller sees the connection
dropped rather than an HTTP error, and the notes give the exact kubectl
command that prints OOMKilled.
- Temp space is an emptyDir counted against ephemeral-storage, where running
out looks different — the pod is evicted and replaced, not restarted.
Both limits are read back through the chart's own resources helper, so the
printed figures follow limitFactor and any override instead of being
hardcoded. Refs #43.
Three changes, all about values that do not do what they promise:
1. Ingress gate (#93): the Ingress template is wrapped in
{{- if .Values.ingress.enabled }}. The key already existed in
values.yaml with default true but was never read, so switching it off
did nothing. Both required() calls for domain and clusterIssuer live
inside the Ingress file, so gating also removes the contradiction that
one had to supply a domain and issuer in order to turn off an Ingress
one does not want.
2. Null-safety for hardening, probes and resources (#99): an override
written without children is YAML null and erased the whole default
sub-tree, rendering "securityContext: null" - an unhardened container
that starts and reports healthy.
3. values.schema.json types (#68 + #99): the blocks covered by the
null-safety accept null. This is load-bearing only for keys that have
no chart default (e.g. resources.limits): there Helm has nothing to
delete, so the null survives into schema validation and a strict
"object" type rejected it outright.
Rendering with normal values is byte-identical to 7.0.0.
Prints what an operator would otherwise have to look up after installing:
the rendered Ingress URL, the cert-manager Certificate to watch while the
browser still warns, and the fact that the chart needs no secrets and no
volumes.
Adds three warnings that the values alone do not tell: CyberChef ships no
authentication, so everything that reaches the URL can use it; the app is
static and holds no server-side state, so upgrades and rollbacks need no
migration; and cyberchef.env reaches nginx but never the served bundle.
Scaled-down installations are called out conditionally, naming whichever of
scaleDown / cyberchef.replicas caused it, via the chart's own replicas
helper so the notice cannot drift from the rendered Deployment.
The URL is only ever rendered from .Values.ingress.domain, so no domain is
stored in the chart. Refs #43.
Third change of the same class (#99): an override written without
children is YAML null and replaced the whole default sub-tree, rendering
"securityContext: null" (unhardened container), a vanished probe or a
container without resource accounting - silently, while the workload
reports healthy.
The defaultedDict helper from #96 is adopted for both workloads, so an
empty block means "chart defaults apply" while an explicitly set value
still wins, including false and 0.
The server probes rebuild their Host header from ingress.domain via the
passed-in root context, because the 2.x server rejects requests whose
Host is neither loopback nor a CORS_ORIGIN host.
The schema types allow null for exactly these blocks, so schema and
helper agree instead of the schema rejecting what the helper absorbs.
Rendering with normal values is byte-identical to the previous version,
with and without the guacd sidecar.
Two changes, both 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. Null-safety for hardening, probes and resources (#99): an override
written without children is YAML null and replaced the whole default
sub-tree, rendering "securityContext: null" (unhardened container), a
vanished probe or a container without resource accounting - silently.
The defaultedDict helper from #96 is adopted so an empty block means
"chart defaults apply", while an explicitly set value still wins,
including false and 0.
The schema types allow null for exactly these blocks, so the two changes
agree instead of the schema rejecting what the helper is meant to absorb.
No ingress gate here: this chart already gates its Ingress correctly.
Rendering with normal values is byte-identical to the previous version.
Major bump: a schema can break existing deployments that carry dead keys.
Two changes of the same class - 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. Objects passed
verbatim into the pod spec (probes, securityContext, global) stay open.
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. Without the gate the
value did not exist at all and could not switch the Ingress off.
Major bump: a schema can break existing deployments that carry dead keys.
The chart mounted no volumes at all while running with
readOnlyRootFilesystem: true, so every Next.js write to
/app/apps/web/.next/cache failed. The image optimizer's failure even
surfaced as an unhandledRejection, so this was more than log noise.
The cache path is now a writable emptyDir; path and an optional
sizeLimit are configurable under rallly.cache. The hardening is
untouched — the pod's existing fsGroup (1000) is what makes the mounted
volume writable for uid 20000.
Verified in a throwaway k3d cluster which paths the app actually writes:
with a fully writable root filesystem and the cache mounted, the only
path the container touches is the cache directory itself. /tmp, $HOME
(=/app) and the rest of the root filesystem stay untouched, so no second
mount is needed.
Also drops the vestigial "capabilities.add: []": Trivy's AVD-KSV-0022 for
rallly (#84) comes from the older chart version deployed in the cluster,
which rendered a null list entry under add:. Reproduced with trivy config
against both renderings; the app needs no capabilities.
Major bump: runtime behavior changes, a volume is added.
Fixes#60
A "barcodes:" key left without children (e.g. after deleting the last
remaining sub-key, PAPERLESS_CONSUMER_BARCODE_SCANNER, which paperless-ngx
3.0 removed) is YAML null and replaced the whole default sub-tree on merge.
Rendering then failed on the nil pointer, so the release simply stopped
updating.
An empty or null block now means "the chart defaults apply". The merge runs
through a new paperless-ngx.defaultedDict helper: nulls never delete, nested
maps merge recursively, and explicitly set values win - including false and 0,
which "default" and "mergeOverwrite" would swallow. A scalar where the
defaults define a map is rejected with the values path in the message.
Major bump: the meaning of a values override changes.
Fixes#61
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. Objects passed verbatim into the pod spec (probes,
securityContext, global) stay open - Kubernetes owns their schema there.
Major bump: a schema can break existing deployments that carry dead keys.
Refs #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. Objects passed verbatim into the pod spec (probes,
securityContext, global) stay open - Kubernetes owns their schema there.
Major bump: a schema can break existing deployments that carry dead keys.
Refs #68