SockguardSockguard

Migration

Drop-in migration paths from Tecnativa, LinuxServer, wollomatic, 11notes, and CetusGuard socket proxies — current env compatibility, same intent, stronger inspection underneath.

From Tecnativa/docker-socket-proxy

Sockguard accepts the current Tecnativa environment-variable surface, including section vars, ALLOW_RESTARTS, SOCKET_PATH, and LOG_LEVEL. Replace the image:

 services:
   socket-proxy:
-    image: tecnativa/docker-socket-proxy
+    image: codeswhat/sockguard
     volumes:
       - /var/run/docker.sock:/var/run/docker.sock:ro
    environment:
      - CONTAINERS=1
      - POST=0

That gets you current Tecnativa env-surface compatibility. If you intentionally want section-wide raw archive/export or log/attach streaming parity from CONTAINERS=1 or IMAGES=1, also set SOCKGUARD_INSECURE_ALLOW_READ_EXFILTRATION=true; otherwise move to YAML and allow only the list/inspect endpoints you actually need.

When ready, migrate to YAML config for more control:

rules:
  - match: { method: GET, path: "/containers/json" }
    action: allow
  - match: { method: GET, path: "/containers/*/json" }
    action: allow
  - match: { method: GET, path: "/_ping" }
    action: allow
  - match: { method: GET, path: "/version" }
    action: allow
  - match: { method: GET, path: "/events" }
    action: allow
  - match: { method: "*", path: "/**" }
    action: deny

From LinuxServer/socket-proxy

Same process as Tecnativa. Additionally, granular operation env vars are supported:

ALLOW_START=1
ALLOW_STOP=1
ALLOW_RESTARTS=1  # or the legacy singular ALLOW_RESTART=1; both map to the same rules

From wollomatic/socket-proxy

wollomatic already does more than a basic path gate: regex allowlists per method, IP or hostname admission, per-container label allowlists, optional bind-mount restrictions, JSON logging, active upstream watchdog checks, and a filtered unix-socket endpoint. Sockguard's migration story is mostly direct: body policy, named profiles, mTLS selectors, owner isolation, Prometheus metrics, trace/log correlation, and read-side visibility are the main upgrades; hostname admission maps best to mTLS DNS/URI selectors, CIDRs, unix peers, or container labels.

wollomaticsockguard
-allowGET "^/(v[0-9.]+/)?containers/json$"{ method: GET, path: "/containers/json" }
-allowGET "^/(v[0-9.]+/)?events$"{ method: GET, path: "/events" }
-allowPOST "^/(v[0-9.]+/)?containers/[a-z0-9]+/start$"{ method: POST, path: "/containers/*/start" }
-allowfrom=172.18.0.0/16clients.allowed_cidrs: ["172.18.0.0/16"]
-allowfrom=traefik (hostname admission)clients.allowed_cidrs with the caller's IP, or clients.container_labels for name-based resolution. For cryptographic caller identity, clients.client_certificate_profiles (mTLS) or clients.unix_peer_profiles are a stronger upgrade.
socket-proxy.allow.get=.*clients.container_labels.label_prefix: socket-proxy.allow.
-allowbindmountfrom=/srv/data,/var/logrequest_body.container_create.allowed_bind_mounts: ["/srv/data", "/var/log"]
-proxysocketendpoint=/tmp/filtered.socklisten.socket: /tmp/filtered.sock

Key differences:

  • Sockguard auto-strips API version prefixes — no need for (v[0-9.]+/)? in patterns
  • Glob patterns (*, **) instead of regex
  • YAML config instead of CLI flags
  • Auto-anchoring built in (no need for ^ and $)
  • Wollomatic already supports hostname allowlists and a filtered unix-socket endpoint today; Sockguard is stronger on exec/pull/build inspection, named profiles, ownership isolation, and visibility-controlled reads

From 11notes/docker-socket-proxy

11notes/docker-socket-proxy is a fixed read-only proxy — it allows every Docker API GET except seven exfiltration-prone endpoints and blocks every write. There is no rule syntax to translate; the equivalent in Sockguard is a default-deny config that allows reads broadly while denying those same endpoints first (first-match-wins):

rules:
  # Deny the seven exfiltration-prone reads 11notes blocks
  - match: { method: GET, path: "/containers/*/attach/ws" }
    action: deny
  - match: { method: GET, path: "/containers/*/export" }
    action: deny
  - match: { method: GET, path: "/containers/*/archive" }
    action: deny
  - match: { method: GET, path: "/secrets" }
    action: deny
  - match: { method: GET, path: "/configs" }
    action: deny
  - match: { method: GET, path: "/swarm/unlockkey" }
    action: deny
  - match: { method: GET, path: "/images/*/get" }
    action: deny
  # Allow everything else read-only — writes fall through to default-deny
  - match: { method: GET, path: "/**" }
    action: allow

The 11notes environment variables configure the process, not the policy, so they map to Sockguard's listener and upstream settings rather than to rules:

11notes env varSockguard equivalent
SOCKET_PROXY_DOCKER_SOCKETupstream.socket (env: SOCKGUARD_UPSTREAM_SOCKET)
SOCKET_PROXY_VOLUMElisten.socket (env: SOCKGUARD_LISTEN_SOCKET)
SOCKET_PROXY_HTTP_LISTEN_IPlisten.address — mTLS is required for any non-loopback bind
SOCKET_PROXY_UID / SOCKET_PROXY_GIDSockguard's image already runs as UID 65532; set container runtime user: / group_add only when you need to match the host Docker socket's numeric UID/GID
DEBUGlog.level: debug (env: SOCKGUARD_LOG_LEVEL)

Once migrated, tighten the broad GET /** allow into the specific list/inspect endpoints your client actually needs, then re-enable individual writes with body inspection instead of leaving the whole API read-only.

From hectorm/cetusguard

CetusGuard is the closest in spirit to Sockguard — a zero-dependency, default-deny proxy with method + path rules. Its rules use a METHOD[,METHOD] PATTERN grammar with regex patterns and %VARIABLE% placeholders; Sockguard expresses the same intent as YAML glob rules:

CetusGuard ruleSockguard rule
GET %API_PREFIX_CONTAINERS%/json{ method: GET, path: "/containers/json" }
GET %API_PREFIX_CONTAINERS%/%CONTAINER_ID_OR_NAME%/json{ method: GET, path: "/containers/*/json" }
POST %API_PREFIX_CONTAINERS%/%CONTAINER_ID_OR_NAME%/start{ method: POST, path: "/containers/*/start" }

%API_PREFIX_*% placeholders become literal path segments (/containers, /images, …), id placeholders such as %CONTAINER_ID_OR_NAME% become a * glob, and a GET,POST method list becomes two rules. CetusGuard's flags and env vars map to Sockguard's listener and upstream config:

CetusGuardSockguard
-frontend-addr / CETUSGUARD_FRONTEND_ADDRlisten.address (TCP) or listen.socket (unix)
-backend-addr / CETUSGUARD_BACKEND_ADDRupstream.socket
-frontend-tls-cert / -frontend-tls-keylisten.tls.cert_file / listen.tls.key_file
-frontend-tls-cacertlisten.tls.client_ca_file (enables mTLS)
-rules / -rules-file / CETUSGUARD_RULES*The YAML rules: block
-log-level / CETUSGUARD_LOG_LEVELlog.level
builtin /_ping, /info, /version rulesAllow them explicitly — Sockguard has no implicit allows

Key differences:

  • Sockguard auto-strips Docker API version prefixes (/v1.45/…) before matching, so patterns never account for them
  • Glob patterns (*, **) with auto-anchoring instead of regex
  • CetusGuard filters on method + path only; Sockguard adds request-body inspection, named per-client profiles, owner isolation, read-side visibility/redaction, rate limits, and metrics on top
  • CetusGuard can dial a remote daemon over backend TLS today; Sockguard's upstream is the local socket, with remote TCP upstreams on the v1.1 roadmap

On this page