feat: add podman and ssh plugin support#89
Open
wongtsejian wants to merge 23 commits into
Open
Conversation
…ardening Add container runtime detection that supports both Docker and Podman, with automatic fallback to podman-compose standalone when the built-in compose plugin is unavailable. Changes: - New internal/runtime package with Detect()/DetectOrDefault() functions - Compose passthrough uses detected runtime instead of hardcoded docker - Fleet mode expands include directives into multiple -f flags (podman-compose compat) - cap_drop: ALL on all containers, adding back only required capabilities - userns_mode: keep-id on agent containers when podman detected (single mode) - Explicit default network declaration for podman-compose compatibility - Integration tests use detected runtime binary Security hardening: - Gateway: cap_drop ALL, cap_add NET_ADMIN + NET_BIND_SERVICE - Agent: cap_drop ALL, cap_add NET_ADMIN + DAC_OVERRIDE + CHOWN + SETUID + SETGID + FOWNER - Single mode: cap_drop ALL (no capabilities needed) Tested with podman 5.8.2 + podman-compose 1.5.0 on local-coding and multi-agent examples. Backward compatible with Docker Compose.
15fc53b to
11e2d02
Compare
…nv var Runtime detection now uses only the config override parameter and PATH auto-detection. The CONTAINER_RUNTIME environment variable is no longer consulted — callers pass the config value explicitly via DetectWithOverride(). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add SSH feature plugin for remote development access (host key persistence, authorized_keys, root hooks for sshd setup) - Extend FeatureContributions with RootHooks, Capabilities, and Ports - Add HTTP reverse proxy to gateway for plain HTTP credential injection - Gateway entrypoint template: iptables rules for HTTP port redirect - Fix rewriter domain normalization (strip scheme/port for matching) - Gate /etc/hosts cleanup and CA cert wait on HasMITM (not HasGateway) - Split feature ports (agent) from runtime ports (gateway) in compose Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove stale HTTPDomains code from gateway main and update tests to use HTTPServices structs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The private key was committed to the repo and must be considered compromised. Replace with runtime generation on first boot. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…example Remove SSH plugin, scripts, and key files from local-coding so it stays focused on external-services + custom-runtime. The new local-coding-ssh example preserves the full SSH setup for users who need shell access to the agent container.
Allows plain HTTP URLs for services reachable without a Docker network (e.g., host.containers.internal from inside a container). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The SSH plugin no longer reads private key contents at generate time. Instead, it contributes volume mounts that bind the key files into /run/ssh/ and the entrypoint copies them to the correct locations at container start. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Without this, Zed remote sessions fail with "codex-acp is not registered" since the settings aren't in the home override. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The gateway service now loads environment variables from ../.env, allowing credentials like API keys to be injected without hardcoding them in the compose file or agent.yaml. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…jection The gateway rewriter injects the real API key from .env into HTTP requests, replacing the dummy token in codex config. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove duplicate .zed/settings.json file - Fix JSON formatting in .config/zed/settings.json - Update gateway endpoints from localhost to production
- Modified AuthHeaderRewriter and OAuthRewriter to match against host:port first, then bare hostname - Refactored domain normalization to preserve port information instead of stripping it - Updated gateway config generation to use refined domain splitting logic - Added env_file reference to docker-compose service template
Agent-level container_runtime overrides fleet-level shared config. Priority: agent.yaml > fleet.yaml shared > PATH auto-detect. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
feat(plugins): add SSH plugin and HTTP reverse proxy for gateway
The external-services plugin now supports http:// URLs, so the test needs to use a truly unsupported scheme (ftp://) instead. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Lift http.Transport to HTTPProxy struct for connection reuse - Add path traversal protection on SSH volume mount paths - Validate SSH port range (1-65535) - Handle non-NotExist os.Stat errors for host key - Use port-aware domain matching in HTTP proxy (normalize to host:port) - Remove dead collectHTTPPortsFromDomains function - Remove unused Podman field from ComposeBuilder Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Add podman as a first-class supported container runtime alongside Docker, with automatic detection and security hardening via Linux capability dropping.
internal/runtimepackage auto-detects docker/podman (configurable viaCONTAINER_RUNTIMEenv var)dockerincludedirectives into multiple-fflags for podman-compose compatibilityuserns_mode: keep-idon podman (single mode) to limit container escape blast radiusContext
The tool's purpose is secure sandboxing of AI coding agents. Podman offers stronger isolation out of the box (no root daemon, native rootless support, daemonless architecture). Supporting it gives users a more secure default without changing the existing Docker workflow.
Security hardening
cap_drop: ALL+NET_ADMIN,NET_BIND_SERVICEcap_drop: ALL+NET_ADMIN,DAC_OVERRIDE,CHOWN,SETUID,SETGID,FOWNERcap_drop: ALLTesting
examples/local-codingwith podman 5.8.2 + podman-compose 1.5.0examples/multi-agent(fleet mode) — all 4 containers healthygo test ./internal/...all greenuserns_modeis behind template conditional)Deployment notes
None — this is additive. Existing Docker users see no change unless they set
CONTAINER_RUNTIME=podmanor have podman on PATH without docker.