Files
helm-charts/minecraft-server/templates/minecraft-server.configmap.yaml
T
jklein fc8f57e176 minecraft-server: null-safe hardening, probes and resources
The last open gap of #99. minecraft-server was the one chart of 21 where an
erased security context removed the hardening in silence: it never got the
defaultedDict helper, the StatefulSet rendered .Values.securityContext.pod
straight through toYaml, and the schema typed securityContext.pod as a strict
"object" without required. Measured against ci/minecraft-server/test-values.yaml
on 3.0.1:

  --set securityContext.pod=null --set securityContext.container=null
  -> helm exit 0, no schema error, "securityContext: null" for BOTH the pod and
     the container - no runAsNonRoot, no readOnlyRootFilesystem, no dropped
     capabilities, in a chart with a PVC.

Bitter place for it: the README lists this chart as the pilot for #68. It got
its schema early and was therefore never caught by the later null-safety wave.

Both halves are added, because they cover different cases. For a key WITH a
chart default Helm's coalescing deletes the null before validation ever sees
it, and only the defaultedDict fallback catches that; for a key WITHOUT one
(server.resources.limits) the null survives into validation, where the strict
"object" aborted the render. Now widened to ["object","null"].

The fallback table reproduces THIS chart's defaults, deviations included:
uid/gid pinned to 1000 (the image's minecraft user - starting as it directly
takes the entrypoint's non-root branch, which skips the recursive chown of
/data and the write to /etc/nsswitch.conf that a read-only root filesystem
would reject), fsGroupChangePolicy OnRootMismatch (a recursive chown of a 32Gi
world on every start costs minutes), the explicit empty capabilities.add list,
and all three probes as exec probes running the image's mc-health script - this
image has no HTTP endpoint, so a probe default rebuilt as httpGet would leave
the workload with no working probe at all. The startup budget stays 15s x 80.

server.resources goes through the same helper while keeping its memory request
deliberately unset, so it is still derived from the JVM heap.

Also, the same class one level down: init.sh chowned the migrated serverpack to
a hardcoded 1000:1000 while the uid it has to match was overridable. Both reads
now go through the same helper, so they cannot disagree. With the chart defaults
the rendered script is unchanged, so checksum/config does not move and no
existing pod rolls.

minecraft.resources.storage and .memory stay deliberately not null-safe: an
erased value yields an invalid PVC or an unparseable quantity, which is the loud
class #99 excludes.

Evidence, all against ci/minecraft-server/test-values.yaml unless noted:

  - the reported call now renders the defaults, byte-identical to the
    unmodified rendering. Fallback, not rejection.
  - rendering with securityContext, all three probes and server.resources set
    to null is byte-identical to rendering the chart defaults - which is what
    keeps the table and values.yaml in sync instead of leaving it to discipline.
  - no regression: rendering before and after the change is byte-identical, on
    the CI values, on the chart defaults, and with curseforgeServerpack enabled
    (the init-container path the CI values do not exercise). Confirmed
    structurally too, not only by raw diff.
  - partial nulling, 14 keys swept one at a time. On 3.0.1 twelve of them
    changed the rendering silently, including capabilities (the container kept
    every default capability instead of dropping ALL) and requests (cpu and
    ephemeral-storage disappeared entirely). On 4.0.0 all fourteen render
    identical to the defaults.
  - explicit false and 0 still win over the defaults; a scalar in a mapping slot
    is still rejected, now naming the values path.

Major bump: erasing one of these blocks used to change the rendered workload
and now does not, which is a runtime behaviour change. appVersion is untouched.

Refs #99
2026-08-24 16:53:25 +02:00

58 lines
2.3 KiB
YAML

{{/*
The chown at the end of init.sh used to be a hardcoded 1000:1000 while the uid
it has to match was overridable through securityContext.pod - so an override
made the two disagree in silence. Both now read the same null-safe helper, and
with the chart defaults the rendered script is unchanged (1000:1000), so this
does not move checksum/config and does not roll existing pods.
*/}}
{{- $podCtx := fromYaml (include "minecraft-server.podSecurityContext" .Values.securityContext) -}}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-{{ .Chart.Name }}-configmap
data:
init.sh: |
set -e
echo "downloading serverpack"
wget -O /modpacks/serverpack.zip {{ .Values.curseforgeServerpack.downloadUrl }}
SERVERPACK_DIR="{{ .Values.curseforgeServerpack.workingDirectory }}"
BACKUP_DIR="/data/serverpack-backup"
if [ -d "$SERVERPACK_DIR" ]; then
echo "found installed server. Migrating..."
if [ -d "$BACKUP_DIR" ]; then
echo "clearing old Backup"
rm -rf $BACKUP_DIR
fi
echo "backing up old server-files"
cp -r $SERVERPACK_DIR $BACKUP_DIR
rm -rf $SERVERPACK_DIR
mkdir $SERVERPACK_DIR
echo "extracting new server-files"
tar -xvf /modpacks/serverpack.zip -C $SERVERPACK_DIR
echo "copying old configuration-data"
cp -r $BACKUP_DIR/world $SERVERPACK_DIR/world
cp $BACKUP_DIR/banned-ips.json $SERVERPACK_DIR/banned-ips.json
cp $BACKUP_DIR/banned-players.json $SERVERPACK_DIR/banned-players.json
cp $BACKUP_DIR/ops.json $SERVERPACK_DIR/ops.json
cp $BACKUP_DIR/whitelist.json $SERVERPACK_DIR/whitelist.json
# The init container runs as the same uid as the server (see
# securityContext.pod) and cp creates the copies owned by that uid, so
# this is a no-op in the normal case. It is kept for volumes whose files
# still carry a foreign owner from an older chart version, and it must
# not be fatal: an unprivileged process cannot chown foreign files, and
# with "set -e" a failure here would keep the whole pod from starting.
echo "change owner of files"
chown -R {{ $podCtx.runAsUser }}:{{ $podCtx.runAsGroup }} $SERVERPACK_DIR || echo "chown skipped (not permitted); continuing"
echo "successfully migrated server"
# echo "deleting serverpack.zip"
# rm /modpacks/serverpack.zip
fi