Files
socktop-webterm/kubernetes
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
..

Kubernetes Deployment for Socktop WebTerm

This directory contains Kubernetes manifests for deploying Socktop WebTerm on your k3s cluster.

Overview

The deployment includes:

  • 3 replicas for high availability
  • Host networking to access Raspberry Pi nodes on port 8443
  • Session affinity to maintain terminal connections
  • Traefik Ingress for routing (default with k3s)
  • WebSocket support for terminal connections
  • External SSL termination via NGINX Proxy Manager
  • ConfigMaps for configuration files
  • Secrets for TLS certificates

Prerequisites

  1. k3s cluster running with at least 3 nodes
  2. Traefik Ingress Controller (comes default with k3s)
  3. External NGINX Proxy Manager for SSL termination
  4. DNS records pointing to your external IP:
    • socktop.io → your external IP
    • www.socktop.io → your external IP
    • origin.socktop.io → your external IP
  5. Docker registry access configured for 192.168.1.208:3002
  6. Proxy hosts configured in NGINX Proxy Manager to forward to k3s on port 8080

Installation

Step 1: Configure Docker Registry Access (if needed)

If your k3s nodes need authentication to pull from your Gitea registry:

# Create docker-registry secret
kubectl create secret docker-registry gitea-registry \
  --docker-server=192.168.1.208:3002 \
  --docker-username=YOUR_USERNAME \
  --docker-password=YOUR_PASSWORD \
  --docker-email=your-email@example.com

# Add to deployment (uncomment imagePullSecrets in 03-deployment.yaml)

Step 2: Configure Insecure Registry on k3s Nodes

Since your Gitea registry uses HTTP, configure k3s to allow insecure registries.

On each k3s node, create or edit /etc/rancher/k3s/registries.yaml:

mirrors:
  "192.168.1.208:3002":
    endpoint:
      - "http://192.168.1.208:3002"
configs:
  "192.168.1.208:3002":
    tls:
      insecure_skip_verify: true

Then restart k3s:

# On server node
sudo systemctl restart k3s

# On agent nodes
sudo systemctl restart k3s-agent

Step 3: Create TLS Certificates Secret

Replace the placeholder secret with your actual Raspberry Pi TLS certificates:

kubectl create secret generic socktop-webterm-certs \
  --from-file=rpi-master.pem=/path/to/rpi-master.pem \
  --from-file=rpi-worker-1.pem=/path/to/rpi-worker-1.pem \
  --from-file=rpi-worker-2.pem=/path/to/rpi-worker-2.pem \
  --from-file=rpi-worker-3.pem=/path/to/rpi-worker-3.pem \
  --namespace=default

Or if you don't have certificates yet, the deployment will work without them (secret is optional).

Step 4: Configure External NGINX Proxy Manager

In your NGINX Proxy Manager, create proxy hosts for:

For socktop.io:

  • Domain: socktop.io
  • Scheme: http
  • Forward Hostname/IP: <k3s-node-ip>
  • Forward Port: 8080
  • Enable WebSocket Support: ✓
  • SSL Certificate: Your SSL cert
  • Force SSL: ✓

Repeat for www.socktop.io and origin.socktop.io.

Step 5: Update Configuration (Optional)

Edit 01-configmap.yaml to customize:

  • profiles.json - Add/remove Raspberry Pi nodes
  • alacritty.toml - Adjust terminal appearance
  • catppuccin-frappe.toml - Change color scheme

Step 6: Deploy to Kubernetes

Apply all manifests in order:

# From the kubernetes directory
kubectl apply -f 01-configmap.yaml
kubectl apply -f 02-secret.yaml
kubectl apply -f 03-deployment.yaml
kubectl apply -f 04-service.yaml
kubectl apply -f 05-ingress.yaml

Or apply all at once:

kubectl apply -f .

Step 7: Verify Deployment

Check pod status:

kubectl get pods -l app=socktop-webterm

Expected output:

NAME                                READY   STATUS    RESTARTS   AGE
socktop-webterm-xxxxxxxxxx-xxxxx    1/1     Running   0          30s
socktop-webterm-xxxxxxxxxx-xxxxx    1/1     Running   0          30s
socktop-webterm-xxxxxxxxxx-xxxxx    1/1     Running   0          30s

Check service:

kubectl get svc socktop-webterm

Check ingress:

kubectl get ingress socktop-webterm

View logs:

kubectl logs -l app=socktop-webterm -f

Step 8: Access the Application

Once deployed and NGINX Proxy Manager is configured, access your terminal at:

Traffic flow: Internet → NGINX Proxy Manager (SSL) → k3s:8080 (HTTP) → Traefik → Service → Pods

Architecture

Host Networking

The deployment uses hostNetwork: true to allow containers to access your Raspberry Pi nodes on port 8443 directly. This means:

  • Each pod binds to the host's network interface
  • Pods can reach 192.168.1.101:8443, 192.168.1.102:8443, etc.
  • The containerized socktop-agent runs on port 3001 (not 3000)

Session Affinity

The Service uses sessionAffinity: ClientIP and the Ingress uses cookie-based affinity to ensure:

  • Terminal sessions stay connected to the same pod
  • WebSocket connections don't get routed to different pods
  • Session timeout is set to 3 hours (10800 seconds)

Replicas and Load Balancing

With 3 replicas and hostNetwork: true:

  • k3s will spread pods across available nodes (if you have 3+ nodes)
  • If you have fewer nodes, multiple pods may share nodes
  • Each pod has its own socktop-agent on port 3001
  • Traefik balances HTTP requests across all pods
  • NGINX Proxy Manager forwards external traffic to Traefik on port 8080

Configuration Updates

To update configuration without restarting pods:

# Edit the ConfigMap
kubectl edit configmap socktop-webterm-config

# Force pods to reload (rolling restart)
kubectl rollout restart deployment socktop-webterm

Troubleshooting

Pods in ImagePullBackOff

Check if nodes can access the Gitea registry:

# On any k3s node
docker pull 192.168.1.208:3002/jason/socktop-webterm:0.2.0

If it fails, verify /etc/rancher/k3s/registries.yaml is configured correctly.

Pods in CrashLoopBackOff

Check pod logs:

kubectl logs -l app=socktop-webterm --tail=100

Common issues:

  • Missing configuration files
  • Port conflicts (if hostNetwork is used)
  • Resource limits too low

Can't Connect to Raspberry Pi Nodes

Test from within a pod:

kubectl exec -it deployment/socktop-webterm -- curl -k https://192.168.1.101:8443/health

If this fails:

  • Verify hostNetwork: true is set in deployment
  • Check if your k3s nodes can reach the Raspberry Pi IPs
  • Verify TLS certificates are correct

Can't Access via HTTPS

SSL is terminated at your external NGINX Proxy Manager, not in the cluster.

Check external NGINX Proxy Manager:

  • Verify proxy host configuration
  • Check SSL certificate is valid
  • Ensure WebSocket support is enabled
  • Verify forwarding to correct k3s node IP on port 8080
  • Check DNS points to external IP, not cluster IP

Check Traefik ingress:

kubectl get ingress socktop-webterm
kubectl describe ingress socktop-webterm

Test internal access:

# From a k3s node
curl http://localhost:8080

WebSocket Connections Failing

WebSocket support must be enabled in two places:

  1. External NGINX Proxy Manager - Enable WebSocket support in proxy host settings
  2. Traefik - Should handle WebSockets by default

Check Traefik logs:

kubectl logs -n kube-system deployment/traefik -f

Test WebSocket upgrade:

# Check headers are being passed correctly
curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" http://<k3s-node>:8080/

Scaling

Scale up or down:

# Scale to 5 replicas
kubectl scale deployment socktop-webterm --replicas=5

# Scale down to 2 replicas
kubectl scale deployment socktop-webterm --replicas=2

Updating the Image

After publishing a new version to Gitea:

# Update to specific version
kubectl set image deployment/socktop-webterm webterm=192.168.1.208:3002/jason/socktop-webterm:0.3.0

# Or force pull latest
kubectl rollout restart deployment socktop-webterm

Uninstalling

Remove all resources:

kubectl delete -f .

Or individually:

kubectl delete ingress socktop-webterm
kubectl delete service socktop-webterm
kubectl delete deployment socktop-webterm
kubectl delete configmap socktop-webterm-config
kubectl delete secret socktop-webterm-certs

Resource Usage

Each pod uses:

  • CPU: 500m request, 2000m limit
  • Memory: 256Mi request, 1Gi limit

With 3 replicas:

  • Total CPU: 1500m request, 6000m limit
  • Total Memory: 768Mi request, 3Gi limit

Adjust in 03-deployment.yaml based on your cluster capacity and workload.

Security Considerations

  1. Host Network: Using hostNetwork: true reduces isolation. Ensure your cluster network is trusted.
  2. TLS Certificates: Store Pi certificates as Kubernetes secrets, not in ConfigMaps.
  3. External SSL: SSL is terminated at NGINX Proxy Manager before reaching the cluster.
  4. Authentication: Consider adding authentication layer in NGINX Proxy Manager or as a k8s middleware.
  5. Network Policies: Implement NetworkPolicies to restrict pod-to-pod communication.
  6. Port Exposure: Only port 8080 needs to be accessible from NGINX Proxy Manager, not from public internet.

Support

For issues specific to:

  • Kubernetes deployment: Check logs and events with kubectl describe
  • Container build: Refer to main repository documentation
  • k3s configuration: Consult k3s documentation at https://docs.k3s.io
  • Traefik ingress: Check Traefik logs in kube-system namespace
  • External proxy: Verify NGINX Proxy Manager configuration and SSL certificates