CODEX-001: Decommissioning Socket-Mounted Web UIs & Enforcing Terminal-Native Ops
Classification: Ingress Hardening & Attack Surface Reduction
Status: Implemented & Verified
Executive Summary#
This report documents the architectural lifecycle of container management on Bastion: from initially deploying a web-based GUI (Portainer) to overcome early CLI friction, to identifying the inherent security risks of host-socket mounting, and finally decommissioning the interface in favor of key-authenticated, terminal-native tooling (lazydocker).
Phase 1: Initial Deployment & Context#
Why Portainer Was Introduced#
When initially transitioning to Docker and container orchestration, early CLI management presented significant friction. Debugging multi-container networks, diagnosing container start failures, and managing persistent volume paths purely through raw shell commands often led to silent errors and operational overhead.
Portainer was deployed as a visual bridge:
- Visual State Verification: Immediate confirmation of container states, health checks, and volume mounts.
- Rapid Log Inspection: Quick access to rolling logs across services without crafting continuous
docker logsshell strings. - Training Wheels: Allowed focusing on core service architectures (Nginx, databases, tunneling) before mastering lower-level CLI orchestration.
Initial Implementation Architecture#
- Ingress Route: Cloudflare Tunnel $\rightarrow$ Reverse Proxy (
nginx.confupstream block) $\rightarrow$ Portainer Container (bastion.ownchain.systems). - Privilege Hook: Mounted the host Docker daemon socket into the container (
-v /var/run/docker.sock:/var/run/docker.sock) to allow the web application to control container lifecycles.
Phase 2: Threat Modeling & The Problem With Web Sockets#
As operational fluency with Docker Compose and Linux system administration solidified, maintaining Portainer shifted from a convenience to an unnecessary security and resource liability.
1. Root-Equivalent Host Exposure#
Binding /var/run/docker.sock into an application container is functionally equivalent to granting unconstrained root access to the host. Any vulnerability in the management web layer, session hijacking, or reverse proxy misconfiguration could allow an adversary to break out of the container and control the underlying host filesystem.
2. Unnecessary Public Ingress Surface#
Exposing a dedicated subdomain (bastion.ownchain.systems) required active DNS records, SSL/TLS termination, and reverse proxy routing blocks—creating an external target footprint solely for administrative tasks.
3. Background Resource Overhead#
Continuous web polling loops, telemetry services, and heavy front-end asset delivery consumed persistent CPU cycles and memory on constrained hardware.
Phase 3: Decommissioning & Remediation#
1. Container Teardown & Socket Revocation#
The management container was cleanly stopped, its persistent volume purged, and the host Docker daemon socket binding removed:
doas docker compose down -v