Skip to content
Automation
Skill

/docker-security

Opt-in advanced Docker security hardening beyond the docker-setup baseline — LAN containment with DNS policy, resource bounds with kernel-hygiene sysctls, and a boot-time plugin install audit log. Applied as a reversible docker-compose overlay (does not touch the base compose

From plugin
claude-code-hermit
7486 skills11 agents
Install
$ npx -y skills add gtapps/claude-code-hermit --skill docker-security --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/docker-security

Context preview

The summary Claude sees to decide when to auto-load this skill.

Opt-in advanced Docker security hardening beyond the docker-setup baseline — LAN containment with DNS policy, resource bounds with kernel-hygiene sysctls, and a boot-time plugin install audit log. Applied as a reversible docker-compose overlay (does not touch the base compose

SKILL.md

docker-security.SKILL.md
name: docker-security
description: Opt-in advanced Docker security hardening beyond the docker-setup baseline — LAN containment with DNS policy, resource bounds with kernel-hygiene sysctls, and a boot-time plugin install audit log. Applied as a reversible docker-compose overlay (does not touch the base compose file) and verified against the live container. Run after /docker-setup; requires bridge networking.
disable-model-invocation: true

Docker Security

Advanced hardening for already-deployed hermit containers. Each toggle is opt-in, presented with honest cost/benefit framing, and applied as a `docker-compose.security.yml` overlay that the `hermit-docker` wrapper auto-detects. Reversal: re-run and answer No to every prompt, or delete `docker-compose.security.yml` directly.

**Tone:** Honest about tradeoffs. Tell operators what each toggle does AND does not protect. Do not oversell.

Each step's commands depend on the previous step's answer, so run them in order.

Templates live in `${CLAUDE_SKILL_DIR}/../../state-templates/docker/security/`.

Trust model framing (read to operator at the start of step 2)

> Installing a plugin runs that plugin's hooks and skills with the same authority as hermit. The container hardening here reduces what a *compromised* plugin can do to the host kernel and your local network — it does not vet the plugin's intent, sandbox its file access within the project, or prevent it from acting on your behalf via the agent. A malicious or careless plugin still runs as you. > > **Honest limitation:** DNS policy below blocks domain-based exfil/C2 but cannot stop direct-IP egress to a hardcoded public address.

Plan

0. Refuse to run inside the hermit container

This skill is host-only — it writes a `docker-compose.security.yml` overlay on the host and recreates the container with stronger isolation.

Run: `[ -f /.dockerenv ] || [ -f /run/.containerenv ] && echo container || echo host`

If the output is `container`, **stop immediately** — do not proceed to step 1. Print:

> This skill writes a `docker-compose.security.yml` overlay on the host and recreates the container with stronger isolation. Run it from your host shell in the project root. To inspect the live security posture *inside* the running container, run `/claude-code-hermit:hermit-doctor` — it includes a `docker-security` check.

1. Prerequisites

1. Read `.claude-code-hermit/config.json`. If missing: "Run `/claude-code-hermit:hatch` first." Stop. 2. Verify `docker-compose.hermit.yml` exists at the project root. If missing: "Run `/claude-code-hermit:docker-setup` first." Stop. 3. **Docker daemon check**: run `timeout 10s docker info >/dev/null 2>&1`. If it fails or times out: tell the operator "Docker daemon is not reachable or timed out. Start Docker before re-running `/docker-security`." Stop. 4. Read `docker.network_mode` from config (default: `"bridge"`). If `"host"`, set `HOST_NETWORK_MODE=true` and surface to operator: "Detected `network_mode: host` in your config. The LAN containment toggle (Prompt 1) will be skipped — it would replace host mode and break your HA / host-bound service access. Resource bounds (Prompt 2) will not apply network sysctls in host mode either; Docker rejects them and the container would fail to start." 5. **Detect hermit ports**: run `timeout 10s docker compose -f docker-compose.hermit.yml config --format json 2>/dev/null` and parse `.services.hermit.ports`. Store as in-memory `detected_hermit_ports` (array of long-form Compose port objects: `{target, published, host_ip, protocol, mode}`). If the command fails or returns no JSON, fall back to `grep -n '^\s*ports:' docker-compose.hermit.yml` and set `detected_hermit_ports_unparsed=true` if found. Either way, a non-empty result means ports are present. 6. Check whether the container is currently running: `docker compose -f docker-compose.hermit.yml ps --status running --format '{{.Service}}' 2>/dev/null | grep -x hermit`. If absent: tell the operator "Container is not running. The wizard will still write the overlay; you'll see the live verification only after starting the container with `hermit-docker up`." 7. Read current `docker.security.*` from config.json. Also read `sandbox.enabled` from the target settings file (same `hatch_target` routing as hatch/docker-setup: `hatch_target == "local"` → `.claude/settings.local.json`; else → `.claude/settings.json`) — display only, hermit does not configure this key. Print a "current posture" summary. Example:

   Current security posture:
     LAN containment: off
     Resource bounds: off
     Audit log: off

   Baseline (always on):
     cap_drop: ALL, no-new-privileges, pids_limit: 2048

   Sandbox (bash tool isolation, operator-managed via /sandbox):
     enabled: true  (or: false / not configured)

2. Trust model framing

Print the trust-model paragraph from the top of this file (the blockquote). Then continue.

3. Prompt 1 — LAN containment + DNS policy

If `HOST_NETWORK_MODE` is true, **do not present this prompt**. Tell the operator: "Skipping LAN containment — incompatible with `network_mode: host`. Run `/claude-code-hermit:docker-setup` to switch to bridge mode if you want this hardening." Continue to step 4.

Otherwise, ask with `AskUserQuestion` (header: `"LAN containment"`):

question: "Add LAN containment with DNS policy? (firewall sidecar + DNS allowlist)"
options:
  - label: "Yes — recommended (LAN block + DNS log-only)"
    description: "Blocks RFC1918 + cloud metadata. DNS in log-only mode: allows everything, logs blocked queries for tuning."
  - label: "Yes — strict (LAN block + DNS enforce)"
    description: "Same LAN block. DNS returns NXDOMAIN for any domain not on the allowlist."
  - label: "No"
    description: "Skip this toggle."

Map: `"Yes — recommended"` → `dns_mode: "log-only"`. `"Yes — strict"` → `dns_mode: "enforce"`. `"No"` → skip to step 4.

3-pre. Port conflict handling (only if a "Yes" optio

Read more
Ships withclaude-code-hermit

If you know Claude Tag, the idea will feel familiar: hand Claude work through a channel, such as Discord, Telegram, or your custom integration, and get results back there.

Get the whole plugin

Other skills on claude-code-hermit.