Fix K8s deployment with init container and proper security context
Some checks failed
Build and Deploy to K3s / test (push) Successful in 2m5s
Build and Deploy to K3s / lint (push) Successful in 1m33s
Build and Deploy to K3s / build-and-push (push) Successful in 48s
Build and Deploy to K3s / deploy (push) Failing after 5m42s

- Add init container to set up config files with correct ownership
- Run main container as socktop user (UID 100, GID 101) from the start
- Use fsGroup to ensure proper volume permissions
- Add emptyDir volume for /var/lib/socktop to avoid permission issues
- Create docker-entrypoint.sh wrapper to detect root vs non-root execution
  - Root mode: uses init-config.sh for Docker/docker-compose
  - Non-root mode: directly runs entrypoint.sh for K8s
- Update deployment command format to work with new entrypoint

This resolves 'Operation not permitted' errors when running in K8s
with security contexts that restrict user switching and ownership changes.
This commit is contained in:
jasonwitty 2025-11-30 04:22:43 -08:00
parent e870e2e4ec
commit 6915079e5c
2 changed files with 96 additions and 4 deletions

View File

@ -122,8 +122,18 @@ EXPOSE 8082 3001
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8082/ || exit 1 CMD curl -f http://localhost:8082/ || exit 1
# Set entrypoint (init-config.sh runs as root, copies configs, then switches to socktop user) # Create a wrapper script that detects if running as root or socktop user
ENTRYPOINT ["/init-config.sh"] RUN echo '#!/bin/bash\n\
if [ "$(id -u)" -eq 0 ]; then\n\
# Running as root - use init-config.sh to set up and switch to socktop\n\
exec /init-config.sh "$@"\n\
else\n\
# Running as socktop user - directly execute entrypoint\n\
exec /entrypoint.sh "$@"\n\
fi' > /docker-entrypoint.sh && chmod +x /docker-entrypoint.sh
# Set entrypoint to the wrapper
ENTRYPOINT ["/docker-entrypoint.sh"]
# Default command - use restricted shell that only allows socktop commands # Default command - use restricted shell that only allows socktop commands
CMD ["/entrypoint.sh", "webterm-server", "--host", "0.0.0.0", "--port", "8082", "--command", "/usr/local/bin/restricted-shell.sh"] CMD ["webterm-server", "--host", "0.0.0.0", "--port", "8082", "--command", "/usr/local/bin/restricted-shell.sh"]

View File

@ -18,11 +18,88 @@ spec:
hostNetwork: false hostNetwork: false
dnsPolicy: ClusterFirst dnsPolicy: ClusterFirst
# Security context for the pod
securityContext:
runAsUser: 100
runAsGroup: 101
fsGroup: 101
# Init container to set up configuration
initContainers:
- name: init-config
image: gt.wittyoneoff.com/jason/socktop-webterm:0.2.2
imagePullPolicy: Always
command: ["/bin/bash", "-c"]
args:
- |
set -e
echo "Setting up configuration directories..."
mkdir -p /var/lib/socktop/.config/socktop/certs
mkdir -p /var/lib/socktop/.config/alacritty
if [ -f "/home/socktop/.config/socktop/profiles.json" ]; then
cp /home/socktop/.config/socktop/profiles.json /var/lib/socktop/.config/socktop/profiles.json
echo "Copied profiles.json"
fi
if [ -f "/home/socktop/.config/alacritty/alacritty.toml" ]; then
cp /home/socktop/.config/alacritty/alacritty.toml /var/lib/socktop/.config/alacritty/alacritty.toml
echo "Copied alacritty.toml"
fi
if [ -f "/home/socktop/.config/alacritty/catppuccin-frappe.toml" ]; then
cp /home/socktop/.config/alacritty/catppuccin-frappe.toml /var/lib/socktop/.config/alacritty/catppuccin-frappe.toml
echo "Copied catppuccin-frappe.toml"
fi
if [ -d "/home/socktop/.config/socktop/certs" ]; then
cp /home/socktop/.config/socktop/certs/*.pem /var/lib/socktop/.config/socktop/certs/ 2>/dev/null || true
echo "Copied certificates"
fi
# Fix paths in profiles.json
if [ -f "/var/lib/socktop/.config/socktop/profiles.json" ]; then
sed -i 's|/home/socktop/.config/socktop/rpi-|/var/lib/socktop/.config/socktop/certs/rpi-|g' /var/lib/socktop/.config/socktop/profiles.json
echo "Updated certificate paths"
fi
echo "Configuration setup complete"
volumeMounts:
- name: config
mountPath: /home/socktop/.config/socktop/profiles.json
subPath: profiles.json
- name: config
mountPath: /home/socktop/.config/alacritty/alacritty.toml
subPath: alacritty.toml
- name: config
mountPath: /home/socktop/.config/alacritty/catppuccin-frappe.toml
subPath: catppuccin-frappe.toml
- name: certs
mountPath: /home/socktop/.config/socktop/certs
readOnly: true
- name: socktop-home
mountPath: /var/lib/socktop
securityContext:
runAsUser: 100
runAsGroup: 101
containers: containers:
- name: webterm - name: webterm
image: gt.wittyoneoff.com/jason/socktop-webterm:0.2.2 image: gt.wittyoneoff.com/jason/socktop-webterm:0.2.2
imagePullPolicy: Always imagePullPolicy: Always
command: ["/docker-entrypoint.sh"]
args:
[
"webterm-server",
"--host",
"0.0.0.0",
"--port",
"8082",
"--command",
"/usr/local/bin/restricted-shell.sh",
]
ports: ports:
- name: http - name: http
containerPort: 8082 containerPort: 8082
@ -78,6 +155,8 @@ spec:
- name: certs - name: certs
mountPath: /home/socktop/.config/socktop/certs mountPath: /home/socktop/.config/socktop/certs
readOnly: true readOnly: true
- name: socktop-home
mountPath: /var/lib/socktop
securityContext: securityContext:
allowPrivilegeEscalation: false allowPrivilegeEscalation: false
@ -85,7 +164,8 @@ spec:
drop: drop:
- ALL - ALL
readOnlyRootFilesystem: false readOnlyRootFilesystem: false
runAsNonRoot: false runAsUser: 100
runAsGroup: 101
volumes: volumes:
- name: config - name: config
@ -95,5 +175,7 @@ spec:
secret: secret:
secretName: socktop-webterm-certs secretName: socktop-webterm-certs
optional: true optional: true
- name: socktop-home
emptyDir: {}
restartPolicy: Always restartPolicy: Always