Harden Stalwart ConfigMap mount to eliminate CrashLoop risk

Issue: During stability testing (DEV-426), pod restart hit a ConfigMap
subPath mounting race, leaving config.json empty/unparseable and causing
CrashLoopBackOff. This undermines the HA work.

Root cause: Kubernetes subPath ConfigMap mounts can race during pod
restart, resulting in empty or incomplete files before the container starts.

Changes:
- Add copy-config init-container that copies ConfigMap files to emptyDir
- Replace subPath mount with directory mount from emptyDir
- Config files are now guaranteed to be complete before Stalwart starts
- Eliminates the ConfigMap subPath mounting race entirely

This is a critical hardening fix for production mail server stability.

Resolves DEV-431.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
CTO Agent 2026-08-01 09:47:22 +00:00
parent a1b723ac62
commit 291feb96a3

View file

@ -91,6 +91,22 @@ spec:
app: stalwart app: stalwart
spec: spec:
initContainers: initContainers:
# Copy ConfigMap files to emptyDir to avoid subPath mounting race
- name: copy-config
image: busybox:latest
command:
- sh
- -c
- |
cp /tmp/bootstrap-config/* /etc/stalwart/ && \
echo "Config files copied successfully:" && \
ls -la /etc/stalwart/
volumeMounts:
- name: bootstrap-config-source
mountPath: /tmp/bootstrap-config
readOnly: true
- name: config
mountPath: /etc/stalwart
- name: fix-permissions - name: fix-permissions
image: busybox:latest image: busybox:latest
command: ["sh", "-c", "chown -R 2000:2000 /var/lib/stalwart && chmod -R 755 /var/lib/stalwart"] command: ["sh", "-c", "chown -R 2000:2000 /var/lib/stalwart && chmod -R 755 /var/lib/stalwart"]
@ -125,9 +141,8 @@ spec:
volumeMounts: volumeMounts:
- name: data - name: data
mountPath: /var/lib/stalwart mountPath: /var/lib/stalwart
- name: bootstrap-config - name: config
mountPath: /etc/stalwart/config.json mountPath: /etc/stalwart
subPath: config.json
- name: tls-certs - name: tls-certs
mountPath: /etc/stalwart/certs mountPath: /etc/stalwart/certs
readOnly: true readOnly: true
@ -178,7 +193,11 @@ spec:
- name: data - name: data
persistentVolumeClaim: persistentVolumeClaim:
claimName: stalwart-data claimName: stalwart-data
- name: bootstrap-config # emptyDir for config files (populated by copy-config init-container)
- name: config
emptyDir: {}
# ConfigMap source for init-container (no longer mounted directly via subPath)
- name: bootstrap-config-source
configMap: configMap:
name: stalwart-bootstrap-config name: stalwart-bootstrap-config
- name: tls-certs - name: tls-certs