Files
socktop-webterm/kubernetes/03-deployment.yaml
T
jasonwitty 6711ac030f
Build and Deploy to K3s / test (push) Successful in 1m33s
Build and Deploy to K3s / lint (push) Successful in 1m0s
Build and Deploy to K3s / build-and-push (push) Successful in 5m17s
Build and Deploy to K3s / deploy (push) Successful in 1m9s
Pin socktop apt version (1.60.2-1); bump to 0.3.10
Image 0.3.9 baked socktop 1.60.1 because CI's registry layer cache reused
the apt-install layer from before the 1.60.2 release. 1.60.1 has no
--no-kill flag, so the restricted shell's invocation parsed it as the
positional websocket URL, breaking (and on overwrite, corrupting) the
local profile. Pinning the package version busts the cache and ties the
installed binary to the flags the restricted shell uses.

Also point the manifest's webterm container at the current tag so a
manual kubectl apply cannot roll the image back to 0.2.2.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 09:16:29 -07:00

199 lines
6.5 KiB
YAML

apiVersion: apps/v1
kind: Deployment
metadata:
name: socktop-webterm
labels:
app: socktop-webterm
spec:
replicas: 3
selector:
matchLabels:
app: socktop-webterm
template:
metadata:
labels:
app: socktop-webterm
spec:
# Use standard pod networking
hostNetwork: false
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:
- name: webterm
image: gt.wittyoneoff.com/jason/socktop-webterm:0.3.10
imagePullPolicy: Always
command: ["/docker-entrypoint.sh"]
args:
[
"webterm-server",
"--host",
"0.0.0.0",
"--port",
"8082",
"--command",
"/usr/local/bin/session-shell.sh",
]
ports:
- name: http
containerPort: 8082
protocol: TCP
- name: agent
containerPort: 3001
protocol: TCP
env:
- name: TERM
value: "xterm-256color"
- name: TZ
value: "America/New_York"
- name: RUST_LOG
value: "info"
# Disable socktop's local process-kill feature for every socktop
# launched anywhere under this pod, regardless of command line.
# The restricted shell also passes --no-kill, but this is the layer
# a visitor cannot route around (no way to unset env from the
# restricted shell).
- name: SOCKTOP_NO_KILL
value: "1"
resources:
limits:
cpu: "2000m"
memory: "1Gi"
requests:
cpu: "500m"
memory: "256Mi"
livenessProbe:
httpGet:
path: /
port: 8082
initialDelaySeconds: 10
periodSeconds: 30
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /
port: 8082
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
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
# webterm-server runs as in-container root holding ONLY
# CAP_SETUID/CAP_SETGID (everything else dropped, no privilege
# escalation), so it can drop each websocket session to the
# unprivileged `demo` user via session-shell.sh. The kernel then
# refuses any signal a session aims at the server, the agent
# (running as `socktop`), or another session's UID — the kill
# feature's UI gating stops being the only line of defense.
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
add:
- SETUID
- SETGID
readOnlyRootFilesystem: false
runAsUser: 0
runAsGroup: 0
volumes:
- name: config
configMap:
name: socktop-webterm-config
- name: certs
secret:
secretName: socktop-webterm-certs
optional: true
- name: socktop-home
emptyDir: {}
restartPolicy: Always