Repository files navigation

securetty

Sandboxed AI development environment. All AI CLI agents run inside ephemeral rootless podman containers with credential isolation, egress filtering, delayed package ingestion, and nftables-enforced network policy. Fully declarative via Ansible.

Architecture

graph TD
Internet["Internet + VPN"]
subgraph host["Host"]
CLI["securetty CLI"]
SSHAgent["SSH agent (restricted)"]
Pass["GNU pass (secrets)"]
Egress["nftables egress whitelist"]
end
subgraph network["Container Network (172.30.100.0/24)"]
OmniRoute["omniroute :4000\nAI provider router"]
Headroom["headroom :8787\nToken compression MCP"]
CloudCLI["cloudcli :3001\nClaude Code Web UI"]
Ollama["ollama :11434\nLocal LLM (GPU)"]
Creds["creds :8800\nCredential proxy"]
Dispatcher["dispatcher :8900\nmTLS work router"]
subgraph mcp["MCP Servers"]
Jira["mcp-jira :8801"]
GitLab["mcp-gitlab :8802"]
GitHub["mcp-github :8803"]
Slack["mcp-slack :8804"]
WordPress["mcp-wordpress :8805"]
end
subgraph scanners["Package Scanners"]
GuardDog["guarddog\nBehavioral + YARA"]
OSV["osv-scanner\nVulnerability DB"]
end
subgraph agents["Ephemeral Agent Containers"]
Dev["securetty-claude-*\nsecuretty-codex-*\n..."]
end
subgraph daemons["Background Daemons"]
JiraPoller["jira-poller\nAuto-triage"]
ReviewMgr["review-manager\nMR/PR feedback"]
end
end
CLI --> Dev
Pass -->|"generate-env.sh"| Creds
SSHAgent -->|"socket (ro)"| Dev
Egress -->|"default-drop"| Internet
Dev --> OmniRoute
Dev --> Headroom
Dev --> Ollama
OmniRoute --> Internet
style network fill:#0f3460,stroke:#e94560,color:#fff
style host fill:#1a1a2e,stroke:#e94560,color:#fff
style mcp fill:#16213e,stroke:#0f3460,color:#fff
style scanners fill:#16213e,stroke:#0f3460,color:#fff
style agents fill:#16213e,stroke:#0f3460,color:#fff
style daemons fill:#16213e,stroke:#0f3460,color:#fff
Loading

Security Model

Credential Isolation

Secrets live in GNU pass on the host. generate-env.sh resolves them at container start into per-service .env files. Agent containers receive only OMNIROUTE_API_KEY — never raw provider keys. The credential proxy (securetty-creds) brokers access to everything else.

Egress Filtering

Default-drop nftables policy in the rootless network namespace. Only resolved IPs from approved domains pass. Domain whitelist is in group_vars/all.yml (securetty_allowed_domains). Covers AI providers, git hosts, package registries, and configured services.

Container Hardening

Every agent container runs with:

  • --cap-drop ALL — no Linux capabilities
  • --security-opt no-new-privileges:true — no privilege escalation
  • --read-only — immutable root filesystem
  • --pids-limit 4096 — fork bomb protection
  • --userns=keep-id — rootless user namespace
  • Masked proc/sys paths — no host information leakage
  • Named volumes for caches only — code is bind-mounted

SSH

Dedicated ssh-agent on host with only one key loaded (configurable via securetty_ssh_key). Socket forwarded read-only. Private key never enters container.

Delayed Ingestion

AI agents installed from package versions published >= 7 days ago (configurable via securetty_quarantine_days). npm: queries npm view <pkg> time for version dates. pip: uses uv --exclude-newer. GuardDog and OSV-Scanner continuously scan cached packages for malicious behavior and known vulnerabilities.

DNS

Aardvark DNS resolves container names on the bridge network and forwards external queries to host DNS (169.254.1.1, patched from Google DNS to avoid VPN leaks). VPN domains resolve automatically.

Quick Start

# Prerequisites: podman, podman-compose, ansible, pass (GNU password manager)# Full setup — builds images, configures services, installs CLI + aliases
make setup
# Launch an agent
securetty run claude ~/src/myproject # Personal mode (OmniRoute)
securetty run-work claude ~/src/myproject # Work mode (Vertex AI)# Or use shell aliases
claude ~/src/myproject
claude-work ~/src/myproject

CLI Reference

Usage: securetty <command> [options]
Agent commands:
run <agent> [options] [args] Launch agent in personal mode
run-work <agent> [options] [args] Launch agent in work mode (Vertex AI)
shell [dir] Interactive shell in container
connect [<container>] Reattach to running agent container
code-review <PR-URL> Review a PR/MR via agent
Agent options:
--read Read-only mode (blocks writes)
--max-turns N Limit agent to N turns
--timeout T Kill session after T (e.g. 30m, 1h, 90s)
-p, --prompt <text> Non-interactive prompt (no TTY)
--cleanup keep|remove Container lifecycle (default: remove)
--image <ref> Override container image
-v <host:container> Extra volume mount (repeatable)
Lifecycle:
setup [--ide cursor|vscode] Full setup or generate IDE devcontainer
build Build container images (skip if exist)
rebuild Full rebuild (all image layers)
rebuild-agents Rebuild dev image only (fast)
up / down / restart Start / stop / restart services
nuke Remove containers + volumes (destructive)
update [release|rc|latest] Update securetty (channel-based)
rollback --list|--set <tag> Version management
Configuration:
config list|get|set|unset Runtime configuration management
config profile <name> Switch named profile
check [--fix] [--ai] Health check with auto-repair
egress Reload nftables egress rules + DNS patch
env Regenerate .env files from pass store
Monitoring:
status Dashboard — containers, network, egress, scanners
list [--all] [--json] List securetty containers
top [--live] Container resource usage
scan [alerts|logs] Package scanner results (GuardDog + OSV)
volumes Show volume sizes
preflight Check prerequisites
cost [today|week|all] Session usage tracking
clean [--yes] Remove orphaned containers + stale files
logs <service> [--follow] Show container logs
exec <container> <cmd> Run command in container
version Show CLI and image version info
Orchestration:
dispatch <work-item> Route work item to agent via dispatcher
jobs [status] List dispatched jobs
watch <repo>|--list|--delete Manage polling triggers for repo events
daemon start|stop|status Background agent daemon
dashboard [--once|--json] Real-time TUI dashboard
alerts --check|--notify SLI alerting
jira-triage start|stop|run Jira auto-triage poller
review-manager start|stop MR/PR review feedback manager
Analysis:
retro [--json] [--since] Retrospective failure analysis
confidence --score|--report Agent confidence scoring
eval run|list|report Run promptfoo evaluation suite
skill list|search|install Skill marketplace management
skill run <name> <URL> Run skill against PR/MR/repo URL
init <project-dir> Bootstrap securetty in a new project
Project management:
group <repo> [ls|status|add|clean] Git worktree management
cursor [<path>] Launch Cursor with devcontainer
plugin list|install|remove|update Plugin management
Security:
scan [alerts|logs] Package scanner results (GuardDog + OSV)
audit Run npm audit + pip-audit inside container
test Run shellcheck, yamllint, ansible-lint
migrate Remove AI agents from host (destructive)

Note: All commands go through securetty. The Makefile targets (make setup, make rebuild, etc.) are thin wrappers that call the same ansible playbooks. Use securetty as the single CLI interface.

Two Modes

ModeCLIAliasProviderUse case
Personalsecuretty run <agent>claude, cOmniRoute (auto-routes)Personal projects
Worksecuretty run-work <agent>claude-work, cwGoogle Vertex AIWork projects

Agents

AgentPackageAliasShortType
claude@anthropic-ai/claude-codeclaude / claude-workc / cwnpm
codex@openai/codexcodex / codex-workcx / cxwnpm
gemini@anthropic-ai/claude-codegemini / gemini-workgm / gmwnpm
clineclinecline / cline-workcl / clwnpm
opencodeopencodeopencode / opencode-workocd / ocdwnpm
aideraider-chataider / aider-workai / aiwpip
goosegoose-aigoose / goose-workgs / gswpip
grokgrok-buildgrok / grok-workgr / grwnpm
forge@anthropic-ai/claude-codeforge / forge-workfg / fgwnpm
kiro-clikirokiro-cli / kiro-workki / kiwnpm
pi-aipi-aipi-ai / pi-ai-workpi / piwnpm
kimikimi-clikimi / kimi-workkm / kmwnpm
jcodejcodejcode / jcode-workjc / jcwnpm
ampcodeampcodeamp / amp-worknpm
cursorcursor / cursor-workcr / crwbinary

All agents run with skip-permissions flags. The container is the sandbox.

Services

ContainerPurposePort
securetty-omnirouteAI provider router + dashboard4000
securetty-headroomToken compression MCP server8787
securetty-cloudcliClaude Code Web UI3001
securetty-ollamaLocal LLM server (GPU passthrough)11434
securetty-credsCredential proxy8800
securetty-dispatchermTLS work item router (DAG workflows)8900
securetty-mcp-jiraJira MCP server8801
securetty-mcp-gitlabGitLab MCP server8802
securetty-mcp-githubGitHub MCP server8803
securetty-mcp-slackSlack MCP server8804
securetty-mcp-wordpressWordPress MCP server8805
securetty-guarddogBehavioral + YARA package scanner
securetty-osv-scannerOSV vulnerability scanner
securetty-jira-pollerJira auto-triage daemon
securetty-review-managerMR/PR review feedback daemon
securetty-podman-proxyContainer metrics exporter9402

OmniRoute Providers

Configured via securetty_providers in group_vars/all.yml:

ProviderModelPriority
OpenAIgpt-4o100
Google AI Studiogemini-2.5-flash100
Mistralmistral-large-latest100
OpenRouter(routing)50
Groqllama-3.3-70b-versatile50
Cerebras50
SambaNova50
Ollama (local)(configurable)1 (fallback)

Dashboard: http://localhost:4000

Image Layers

Three container image layers, each building on the previous:

  1. base — Fedora 45 minimal with system packages (dnf)
  2. devbase — Development tools, compilers, language runtimes, pip/npm tooling
  3. dev — AI agents installed via delayed ingestion (7-day quarantine), user account matching host UID/GID

Makefile Targets

TargetDescription
make setupFull setup (all roles)
make buildBuild container images (skips if exist)
make rebuildForce rebuild all images
make rebuild-agentsRebuild dev layer only (fast iteration)
make upStart services
make downStop all containers
make envRegenerate .env files from pass store
make aliasesInstall shell aliases + CLI
make egressResolve domains and load nftables whitelist
make omnirouteConfigure AI providers via REST API
make ollamaPull local LLM models
make certsGenerate TLS certificates for mTLS
make scanScan history for leaked secrets
make migrateRemove AI agents from host (destructive)
make nukeRemove containers + volumes
make statusShow container status
make evalRun promptfoo evaluation suite
make lintLint configuration
make auditSecurity audit

Ansible Roles

flowchart TD
Setup["make setup"] --> Prereqs["prereqs\npodman, dirs, validation"]
Prereqs --> Certs["certs\nTLS for mTLS"]
Certs --> Env["env\n.env from pass"]
Env --> SSH["ssh\nrestricted agent"]
SSH --> Containers["containers\nbuild + compose up"]
Containers --> Egress["egress\nnftables whitelist"]
Egress --> OmniRoute["omniroute\nprovider API setup"]
OmniRoute --> Ollama["ollama\nmodel pulling"]
Ollama --> Aliases["aliases\nCLI + shell integration"]
style Setup fill:#533483,stroke:#e94560,color:#fff
Loading
RolePurposeTag
prereqsInstall podman, create dirs, auto-detect UID/GID, validate SSH key + pass entriesprereqs
certsGenerate CA and service TLS certificates for mTLScerts
envGenerate per-service .env files from GNU passenv
sshRestricted SSH agent (single key)ssh
containersTemplate Containerfiles + compose, build images, start servicescontainers, build, up
egressResolve allowed domains and load nftables whitelistegress
omnirouteConfigure AI providers via REST APIomniroute
ollamaPull local LLM modelsollama
aliasesTemplate and install securetty CLI + shell aliasesaliases
scanScan AI conversation history for leaked secretsscan
migrateRemove AI agents from host (destructive, never tag)migrate

Configuration

All configuration lives in group_vars/all.yml:

SectionWhat it controls
User/pathsUsername, home dir, SSH key name (UID/GID auto-detected)
ProvidersOmniRoute provider list + priorities
API keysGNU pass paths for each key (securetty_pass_keys)
Agentsnpm/pip/binary packages, alias config, skip-flags
Allowed domainsEgress whitelist for nftables
OllamaModels to pull
ResourcesCPU/memory limits per container
Packagesdnf + pip packages for dev container
MCP serversJira, GitLab, GitHub, Slack, WordPress config

Common Changes

  • Add a new AI agent: Edit group_vars/all.yml — add to securetty_npm_agents, securetty_pip_agents, or securetty_binary_agents. Add alias entry to securetty_agents. Run securetty rebuild-agents.
  • Add a new AI provider: Store API key in pass, add entry to securetty_pass_keys and securetty_providers in group_vars/all.yml. Run securetty setup.
  • Add an egress domain: Add to securetty_allowed_domains in group_vars/all.yml. Run securetty egress.
  • Add a pip/npm package: Add to securetty_pip_tools or securetty_npm_tools in group_vars/all.yml. Run securetty rebuild-agents.

Design Documents

DocumentDescription
THREAT_MODEL.md8-section threat assessment
docs/security-tiers.mdGraduated 3-tier isolation model + enforcement status
docs/trust-model.mdTrusted/untrusted input boundaries
docs/escalation-gates.mdConfidence gates and risk classification
docs/confidence-scoring.mdLearned escalation model
docs/observability.mdPrometheus metrics and OTEL tracing
docs/sli-dashboard.mdReal-time dashboard and SLI alerting
docs/evaluation-framework.mdpromptfoo eval harness
docs/jira-auto-triage.mdJira auto-triage agent
docs/closed-loop-remediation.mdAutomated SKILL.md fixes
docs/skill-marketplace.mdSkill management and sharing
docs/daemon-mode.mdBackground agent daemon
docs/provenance.mdAgent action provenance
docs/sigstore-verification.mdSupply chain verification

License

See LICENSE.

About

Secure container-based development environment with MCP gateway

Topics

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

securetty

Sandboxed AI development environment. All AI CLI agents run inside ephemeral rootless podman containers with credential isolation, egress filtering, delayed package ingestion, and nftables-enforced network policy. Fully declarative via Ansible.

Architecture

graph TD
Internet["Internet + VPN"]
subgraph host["Host"]
CLI["securetty CLI"]
SSHAgent["SSH agent (restricted)"]
Pass["GNU pass (secrets)"]
Egress["nftables egress whitelist"]
end
subgraph network["Container Network (172.30.100.0/24)"]
OmniRoute["omniroute :4000\nAI provider router"]
Headroom["headroom :8787\nToken compression MCP"]
CloudCLI["cloudcli :3001\nClaude Code Web UI"]
Ollama["ollama :11434\nLocal LLM (GPU)"]
Creds["creds :8800\nCredential proxy"]
Dispatcher["dispatcher :8900\nmTLS work router"]
subgraph mcp["MCP Servers"]
Jira["mcp-jira :8801"]
GitLab["mcp-gitlab :8802"]
GitHub["mcp-github :8803"]
Slack["mcp-slack :8804"]
WordPress["mcp-wordpress :8805"]
end
subgraph scanners["Package Scanners"]
GuardDog["guarddog\nBehavioral + YARA"]
OSV["osv-scanner\nVulnerability DB"]
end
subgraph agents["Ephemeral Agent Containers"]
Dev["securetty-claude-*\nsecuretty-codex-*\n..."]
end
subgraph daemons["Background Daemons"]
JiraPoller["jira-poller\nAuto-triage"]
ReviewMgr["review-manager\nMR/PR feedback"]
end
end
CLI --> Dev
Pass -->|"generate-env.sh"| Creds
SSHAgent -->|"socket (ro)"| Dev
Egress -->|"default-drop"| Internet
Dev --> OmniRoute
Dev --> Headroom
Dev --> Ollama
OmniRoute --> Internet
style network fill:#0f3460,stroke:#e94560,color:#fff
style host fill:#1a1a2e,stroke:#e94560,color:#fff
style mcp fill:#16213e,stroke:#0f3460,color:#fff
style scanners fill:#16213e,stroke:#0f3460,color:#fff
style agents fill:#16213e,stroke:#0f3460,color:#fff
style daemons fill:#16213e,stroke:#0f3460,color:#fff
Loading

Security Model

Credential Isolation

Secrets live in GNU pass on the host. generate-env.sh resolves them at container start into per-service .env files. Agent containers receive only OMNIROUTE_API_KEY — never raw provider keys. The credential proxy (securetty-creds) brokers access to everything else.

Egress Filtering

Default-drop nftables policy in the rootless network namespace. Only resolved IPs from approved domains pass. Domain whitelist is in group_vars/all.yml (securetty_allowed_domains). Covers AI providers, git hosts, package registries, and configured services.

Container Hardening

Every agent container runs with:

  • --cap-drop ALL — no Linux capabilities
  • --security-opt no-new-privileges:true — no privilege escalation
  • --read-only — immutable root filesystem
  • --pids-limit 4096 — fork bomb protection
  • --userns=keep-id — rootless user namespace
  • Masked proc/sys paths — no host information leakage
  • Named volumes for caches only — code is bind-mounted

SSH

Dedicated ssh-agent on host with only one key loaded (configurable via securetty_ssh_key). Socket forwarded read-only. Private key never enters container.

Delayed Ingestion

AI agents installed from package versions published >= 7 days ago (configurable via securetty_quarantine_days). npm: queries npm view <pkg> time for version dates. pip: uses uv --exclude-newer. GuardDog and OSV-Scanner continuously scan cached packages for malicious behavior and known vulnerabilities.

DNS

Aardvark DNS resolves container names on the bridge network and forwards external queries to host DNS (169.254.1.1, patched from Google DNS to avoid VPN leaks). VPN domains resolve automatically.

Quick Start

# Prerequisites: podman, podman-compose, ansible, pass (GNU password manager)# Full setup — builds images, configures services, installs CLI + aliases
make setup
# Launch an agent
securetty run claude ~/src/myproject # Personal mode (OmniRoute)
securetty run-work claude ~/src/myproject # Work mode (Vertex AI)# Or use shell aliases
claude ~/src/myproject
claude-work ~/src/myproject

CLI Reference

Usage: securetty <command> [options]
Agent commands:
run <agent> [options] [args] Launch agent in personal mode
run-work <agent> [options] [args] Launch agent in work mode (Vertex AI)
shell [dir] Interactive shell in container
connect [<container>] Reattach to running agent container
code-review <PR-URL> Review a PR/MR via agent
Agent options:
--read Read-only mode (blocks writes)
--max-turns N Limit agent to N turns
--timeout T Kill session after T (e.g. 30m, 1h, 90s)
-p, --prompt <text> Non-interactive prompt (no TTY)
--cleanup keep|remove Container lifecycle (default: remove)
--image <ref> Override container image
-v <host:container> Extra volume mount (repeatable)
Lifecycle:
setup [--ide cursor|vscode] Full setup or generate IDE devcontainer
build Build container images (skip if exist)
rebuild Full rebuild (all image layers)
rebuild-agents Rebuild dev image only (fast)
up / down / restart Start / stop / restart services
nuke Remove containers + volumes (destructive)
update [release|rc|latest] Update securetty (channel-based)
rollback --list|--set <tag> Version management
Configuration:
config list|get|set|unset Runtime configuration management
config profile <name> Switch named profile
check [--fix] [--ai] Health check with auto-repair
egress Reload nftables egress rules + DNS patch
env Regenerate .env files from pass store
Monitoring:
status Dashboard — containers, network, egress, scanners
list [--all] [--json] List securetty containers
top [--live] Container resource usage
scan [alerts|logs] Package scanner results (GuardDog + OSV)
volumes Show volume sizes
preflight Check prerequisites
cost [today|week|all] Session usage tracking
clean [--yes] Remove orphaned containers + stale files
logs <service> [--follow] Show container logs
exec <container> <cmd> Run command in container
version Show CLI and image version info
Orchestration:
dispatch <work-item> Route work item to agent via dispatcher
jobs [status] List dispatched jobs
watch <repo>|--list|--delete Manage polling triggers for repo events
daemon start|stop|status Background agent daemon
dashboard [--once|--json] Real-time TUI dashboard
alerts --check|--notify SLI alerting
jira-triage start|stop|run Jira auto-triage poller
review-manager start|stop MR/PR review feedback manager
Analysis:
retro [--json] [--since] Retrospective failure analysis
confidence --score|--report Agent confidence scoring
eval run|list|report Run promptfoo evaluation suite
skill list|search|install Skill marketplace management
skill run <name> <URL> Run skill against PR/MR/repo URL
init <project-dir> Bootstrap securetty in a new project
Project management:
group <repo> [ls|status|add|clean] Git worktree management
cursor [<path>] Launch Cursor with devcontainer
plugin list|install|remove|update Plugin management
Security:
scan [alerts|logs] Package scanner results (GuardDog + OSV)
audit Run npm audit + pip-audit inside container
test Run shellcheck, yamllint, ansible-lint
migrate Remove AI agents from host (destructive)

Note: All commands go through securetty. The Makefile targets (make setup, make rebuild, etc.) are thin wrappers that call the same ansible playbooks. Use securetty as the single CLI interface.

Two Modes

ModeCLIAliasProviderUse case
Personalsecuretty run <agent>claude, cOmniRoute (auto-routes)Personal projects
Worksecuretty run-work <agent>claude-work, cwGoogle Vertex AIWork projects

Agents

AgentPackageAliasShortType
claude@anthropic-ai/claude-codeclaude / claude-workc / cwnpm
codex@openai/codexcodex / codex-workcx / cxwnpm
gemini@anthropic-ai/claude-codegemini / gemini-workgm / gmwnpm
clineclinecline / cline-workcl / clwnpm
opencodeopencodeopencode / opencode-workocd / ocdwnpm
aideraider-chataider / aider-workai / aiwpip
goosegoose-aigoose / goose-workgs / gswpip
grokgrok-buildgrok / grok-workgr / grwnpm
forge@anthropic-ai/claude-codeforge / forge-workfg / fgwnpm
kiro-clikirokiro-cli / kiro-workki / kiwnpm
pi-aipi-aipi-ai / pi-ai-workpi / piwnpm
kimikimi-clikimi / kimi-workkm / kmwnpm
jcodejcodejcode / jcode-workjc / jcwnpm
ampcodeampcodeamp / amp-worknpm
cursorcursor / cursor-workcr / crwbinary

All agents run with skip-permissions flags. The container is the sandbox.

Services

ContainerPurposePort
securetty-omnirouteAI provider router + dashboard4000
securetty-headroomToken compression MCP server8787
securetty-cloudcliClaude Code Web UI3001
securetty-ollamaLocal LLM server (GPU passthrough)11434
securetty-credsCredential proxy8800
securetty-dispatchermTLS work item router (DAG workflows)8900
securetty-mcp-jiraJira MCP server8801
securetty-mcp-gitlabGitLab MCP server8802
securetty-mcp-githubGitHub MCP server8803
securetty-mcp-slackSlack MCP server8804
securetty-mcp-wordpressWordPress MCP server8805
securetty-guarddogBehavioral + YARA package scanner
securetty-osv-scannerOSV vulnerability scanner
securetty-jira-pollerJira auto-triage daemon
securetty-review-managerMR/PR review feedback daemon
securetty-podman-proxyContainer metrics exporter9402

OmniRoute Providers

Configured via securetty_providers in group_vars/all.yml:

ProviderModelPriority
OpenAIgpt-4o100
Google AI Studiogemini-2.5-flash100
Mistralmistral-large-latest100
OpenRouter(routing)50
Groqllama-3.3-70b-versatile50
Cerebras50
SambaNova50
Ollama (local)(configurable)1 (fallback)

Dashboard: http://localhost:4000

Image Layers

Three container image layers, each building on the previous:

  1. base — Fedora 45 minimal with system packages (dnf)
  2. devbase — Development tools, compilers, language runtimes, pip/npm tooling
  3. dev — AI agents installed via delayed ingestion (7-day quarantine), user account matching host UID/GID

Makefile Targets

TargetDescription
make setupFull setup (all roles)
make buildBuild container images (skips if exist)
make rebuildForce rebuild all images
make rebuild-agentsRebuild dev layer only (fast iteration)
make upStart services
make downStop all containers
make envRegenerate .env files from pass store
make aliasesInstall shell aliases + CLI
make egressResolve domains and load nftables whitelist
make omnirouteConfigure AI providers via REST API
make ollamaPull local LLM models
make certsGenerate TLS certificates for mTLS
make scanScan history for leaked secrets
make migrateRemove AI agents from host (destructive)
make nukeRemove containers + volumes
make statusShow container status
make evalRun promptfoo evaluation suite
make lintLint configuration
make auditSecurity audit

Ansible Roles

flowchart TD
Setup["make setup"] --> Prereqs["prereqs\npodman, dirs, validation"]
Prereqs --> Certs["certs\nTLS for mTLS"]
Certs --> Env["env\n.env from pass"]
Env --> SSH["ssh\nrestricted agent"]
SSH --> Containers["containers\nbuild + compose up"]
Containers --> Egress["egress\nnftables whitelist"]
Egress --> OmniRoute["omniroute\nprovider API setup"]
OmniRoute --> Ollama["ollama\nmodel pulling"]
Ollama --> Aliases["aliases\nCLI + shell integration"]
style Setup fill:#533483,stroke:#e94560,color:#fff
Loading
RolePurposeTag
prereqsInstall podman, create dirs, auto-detect UID/GID, validate SSH key + pass entriesprereqs
certsGenerate CA and service TLS certificates for mTLScerts
envGenerate per-service .env files from GNU passenv
sshRestricted SSH agent (single key)ssh
containersTemplate Containerfiles + compose, build images, start servicescontainers, build, up
egressResolve allowed domains and load nftables whitelistegress
omnirouteConfigure AI providers via REST APIomniroute
ollamaPull local LLM modelsollama
aliasesTemplate and install securetty CLI + shell aliasesaliases
scanScan AI conversation history for leaked secretsscan
migrateRemove AI agents from host (destructive, never tag)migrate

Configuration

All configuration lives in group_vars/all.yml:

SectionWhat it controls
User/pathsUsername, home dir, SSH key name (UID/GID auto-detected)
ProvidersOmniRoute provider list + priorities
API keysGNU pass paths for each key (securetty_pass_keys)
Agentsnpm/pip/binary packages, alias config, skip-flags
Allowed domainsEgress whitelist for nftables
OllamaModels to pull
ResourcesCPU/memory limits per container
Packagesdnf + pip packages for dev container
MCP serversJira, GitLab, GitHub, Slack, WordPress config

Common Changes

  • Add a new AI agent: Edit group_vars/all.yml — add to securetty_npm_agents, securetty_pip_agents, or securetty_binary_agents. Add alias entry to securetty_agents. Run securetty rebuild-agents.
  • Add a new AI provider: Store API key in pass, add entry to securetty_pass_keys and securetty_providers in group_vars/all.yml. Run securetty setup.
  • Add an egress domain: Add to securetty_allowed_domains in group_vars/all.yml. Run securetty egress.
  • Add a pip/npm package: Add to securetty_pip_tools or securetty_npm_tools in group_vars/all.yml. Run securetty rebuild-agents.

Design Documents

DocumentDescription
THREAT_MODEL.md8-section threat assessment
docs/security-tiers.mdGraduated 3-tier isolation model + enforcement status
docs/trust-model.mdTrusted/untrusted input boundaries
docs/escalation-gates.mdConfidence gates and risk classification
docs/confidence-scoring.mdLearned escalation model
docs/observability.mdPrometheus metrics and OTEL tracing
docs/sli-dashboard.mdReal-time dashboard and SLI alerting
docs/evaluation-framework.mdpromptfoo eval harness
docs/jira-auto-triage.mdJira auto-triage agent
docs/closed-loop-remediation.mdAutomated SKILL.md fixes
docs/skill-marketplace.mdSkill management and sharing
docs/daemon-mode.mdBackground agent daemon
docs/provenance.mdAgent action provenance
docs/sigstore-verification.mdSupply chain verification

License

See LICENSE.

About

Secure container-based development environment with MCP gateway

Topics

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

securetty

Sandboxed AI development environment. All AI CLI agents run inside ephemeral rootless podman containers with credential isolation, egress filtering, delayed package ingestion, and nftables-enforced network policy. Fully declarative via Ansible.

Architecture

graph TD
Internet["Internet + VPN"]
subgraph host["Host"]
CLI["securetty CLI"]
SSHAgent["SSH agent (restricted)"]
Pass["GNU pass (secrets)"]
Egress["nftables egress whitelist"]
end
subgraph network["Container Network (172.30.100.0/24)"]
OmniRoute["omniroute :4000\nAI provider router"]
Headroom["headroom :8787\nToken compression MCP"]
CloudCLI["cloudcli :3001\nClaude Code Web UI"]
Ollama["ollama :11434\nLocal LLM (GPU)"]
Creds["creds :8800\nCredential proxy"]
Dispatcher["dispatcher :8900\nmTLS work router"]
subgraph mcp["MCP Servers"]
Jira["mcp-jira :8801"]
GitLab["mcp-gitlab :8802"]
GitHub["mcp-github :8803"]
Slack["mcp-slack :8804"]
WordPress["mcp-wordpress :8805"]
end
subgraph scanners["Package Scanners"]
GuardDog["guarddog\nBehavioral + YARA"]
OSV["osv-scanner\nVulnerability DB"]
end
subgraph agents["Ephemeral Agent Containers"]
Dev["securetty-claude-*\nsecuretty-codex-*\n..."]
end
subgraph daemons["Background Daemons"]
JiraPoller["jira-poller\nAuto-triage"]
ReviewMgr["review-manager\nMR/PR feedback"]
end
end
CLI --> Dev
Pass -->|"generate-env.sh"| Creds
SSHAgent -->|"socket (ro)"| Dev
Egress -->|"default-drop"| Internet
Dev --> OmniRoute
Dev --> Headroom
Dev --> Ollama
OmniRoute --> Internet
style network fill:#0f3460,stroke:#e94560,color:#fff
style host fill:#1a1a2e,stroke:#e94560,color:#fff
style mcp fill:#16213e,stroke:#0f3460,color:#fff
style scanners fill:#16213e,stroke:#0f3460,color:#fff
style agents fill:#16213e,stroke:#0f3460,color:#fff
style daemons fill:#16213e,stroke:#0f3460,color:#fff
Loading

Security Model

Credential Isolation

Secrets live in GNU pass on the host. generate-env.sh resolves them at container start into per-service .env files. Agent containers receive only OMNIROUTE_API_KEY — never raw provider keys. The credential proxy (securetty-creds) brokers access to everything else.

Egress Filtering

Default-drop nftables policy in the rootless network namespace. Only resolved IPs from approved domains pass. Domain whitelist is in group_vars/all.yml (securetty_allowed_domains). Covers AI providers, git hosts, package registries, and configured services.

Container Hardening

Every agent container runs with:

  • --cap-drop ALL — no Linux capabilities
  • --security-opt no-new-privileges:true — no privilege escalation
  • --read-only — immutable root filesystem
  • --pids-limit 4096 — fork bomb protection
  • --userns=keep-id — rootless user namespace
  • Masked proc/sys paths — no host information leakage
  • Named volumes for caches only — code is bind-mounted

SSH

Dedicated ssh-agent on host with only one key loaded (configurable via securetty_ssh_key). Socket forwarded read-only. Private key never enters container.

Delayed Ingestion

AI agents installed from package versions published >= 7 days ago (configurable via securetty_quarantine_days). npm: queries npm view <pkg> time for version dates. pip: uses uv --exclude-newer. GuardDog and OSV-Scanner continuously scan cached packages for malicious behavior and known vulnerabilities.

DNS

Aardvark DNS resolves container names on the bridge network and forwards external queries to host DNS (169.254.1.1, patched from Google DNS to avoid VPN leaks). VPN domains resolve automatically.

Quick Start

# Prerequisites: podman, podman-compose, ansible, pass (GNU password manager)# Full setup — builds images, configures services, installs CLI + aliases
make setup
# Launch an agent
securetty run claude ~/src/myproject # Personal mode (OmniRoute)
securetty run-work claude ~/src/myproject # Work mode (Vertex AI)# Or use shell aliases
claude ~/src/myproject
claude-work ~/src/myproject

CLI Reference

Usage: securetty <command> [options]
Agent commands:
run <agent> [options] [args] Launch agent in personal mode
run-work <agent> [options] [args] Launch agent in work mode (Vertex AI)
shell [dir] Interactive shell in container
connect [<container>] Reattach to running agent container
code-review <PR-URL> Review a PR/MR via agent
Agent options:
--read Read-only mode (blocks writes)
--max-turns N Limit agent to N turns
--timeout T Kill session after T (e.g. 30m, 1h, 90s)
-p, --prompt <text> Non-interactive prompt (no TTY)
--cleanup keep|remove Container lifecycle (default: remove)
--image <ref> Override container image
-v <host:container> Extra volume mount (repeatable)
Lifecycle:
setup [--ide cursor|vscode] Full setup or generate IDE devcontainer
build Build container images (skip if exist)
rebuild Full rebuild (all image layers)
rebuild-agents Rebuild dev image only (fast)
up / down / restart Start / stop / restart services
nuke Remove containers + volumes (destructive)
update [release|rc|latest] Update securetty (channel-based)
rollback --list|--set <tag> Version management
Configuration:
config list|get|set|unset Runtime configuration management
config profile <name> Switch named profile
check [--fix] [--ai] Health check with auto-repair
egress Reload nftables egress rules + DNS patch
env Regenerate .env files from pass store
Monitoring:
status Dashboard — containers, network, egress, scanners
list [--all] [--json] List securetty containers
top [--live] Container resource usage
scan [alerts|logs] Package scanner results (GuardDog + OSV)
volumes Show volume sizes
preflight Check prerequisites
cost [today|week|all] Session usage tracking
clean [--yes] Remove orphaned containers + stale files
logs <service> [--follow] Show container logs
exec <container> <cmd> Run command in container
version Show CLI and image version info
Orchestration:
dispatch <work-item> Route work item to agent via dispatcher
jobs [status] List dispatched jobs
watch <repo>|--list|--delete Manage polling triggers for repo events
daemon start|stop|status Background agent daemon
dashboard [--once|--json] Real-time TUI dashboard
alerts --check|--notify SLI alerting
jira-triage start|stop|run Jira auto-triage poller
review-manager start|stop MR/PR review feedback manager
Analysis:
retro [--json] [--since] Retrospective failure analysis
confidence --score|--report Agent confidence scoring
eval run|list|report Run promptfoo evaluation suite
skill list|search|install Skill marketplace management
skill run <name> <URL> Run skill against PR/MR/repo URL
init <project-dir> Bootstrap securetty in a new project
Project management:
group <repo> [ls|status|add|clean] Git worktree management
cursor [<path>] Launch Cursor with devcontainer
plugin list|install|remove|update Plugin management
Security:
scan [alerts|logs] Package scanner results (GuardDog + OSV)
audit Run npm audit + pip-audit inside container
test Run shellcheck, yamllint, ansible-lint
migrate Remove AI agents from host (destructive)

Note: All commands go through securetty. The Makefile targets (make setup, make rebuild, etc.) are thin wrappers that call the same ansible playbooks. Use securetty as the single CLI interface.

Two Modes

ModeCLIAliasProviderUse case
Personalsecuretty run <agent>claude, cOmniRoute (auto-routes)Personal projects
Worksecuretty run-work <agent>claude-work, cwGoogle Vertex AIWork projects

Agents

AgentPackageAliasShortType
claude@anthropic-ai/claude-codeclaude / claude-workc / cwnpm
codex@openai/codexcodex / codex-workcx / cxwnpm
gemini@anthropic-ai/claude-codegemini / gemini-workgm / gmwnpm
clineclinecline / cline-workcl / clwnpm
opencodeopencodeopencode / opencode-workocd / ocdwnpm
aideraider-chataider / aider-workai / aiwpip
goosegoose-aigoose / goose-workgs / gswpip
grokgrok-buildgrok / grok-workgr / grwnpm
forge@anthropic-ai/claude-codeforge / forge-workfg / fgwnpm
kiro-clikirokiro-cli / kiro-workki / kiwnpm
pi-aipi-aipi-ai / pi-ai-workpi / piwnpm
kimikimi-clikimi / kimi-workkm / kmwnpm
jcodejcodejcode / jcode-workjc / jcwnpm
ampcodeampcodeamp / amp-worknpm
cursorcursor / cursor-workcr / crwbinary

All agents run with skip-permissions flags. The container is the sandbox.

Services

ContainerPurposePort
securetty-omnirouteAI provider router + dashboard4000
securetty-headroomToken compression MCP server8787
securetty-cloudcliClaude Code Web UI3001
securetty-ollamaLocal LLM server (GPU passthrough)11434
securetty-credsCredential proxy8800
securetty-dispatchermTLS work item router (DAG workflows)8900
securetty-mcp-jiraJira MCP server8801
securetty-mcp-gitlabGitLab MCP server8802
securetty-mcp-githubGitHub MCP server8803
securetty-mcp-slackSlack MCP server8804
securetty-mcp-wordpressWordPress MCP server8805
securetty-guarddogBehavioral + YARA package scanner
securetty-osv-scannerOSV vulnerability scanner
securetty-jira-pollerJira auto-triage daemon
securetty-review-managerMR/PR review feedback daemon
securetty-podman-proxyContainer metrics exporter9402

OmniRoute Providers

Configured via securetty_providers in group_vars/all.yml:

ProviderModelPriority
OpenAIgpt-4o100
Google AI Studiogemini-2.5-flash100
Mistralmistral-large-latest100
OpenRouter(routing)50
Groqllama-3.3-70b-versatile50
Cerebras50
SambaNova50
Ollama (local)(configurable)1 (fallback)

Dashboard: http://localhost:4000

Image Layers

Three container image layers, each building on the previous:

  1. base — Fedora 45 minimal with system packages (dnf)
  2. devbase — Development tools, compilers, language runtimes, pip/npm tooling
  3. dev — AI agents installed via delayed ingestion (7-day quarantine), user account matching host UID/GID

Makefile Targets

TargetDescription
make setupFull setup (all roles)
make buildBuild container images (skips if exist)
make rebuildForce rebuild all images
make rebuild-agentsRebuild dev layer only (fast iteration)
make upStart services
make downStop all containers
make envRegenerate .env files from pass store
make aliasesInstall shell aliases + CLI
make egressResolve domains and load nftables whitelist
make omnirouteConfigure AI providers via REST API
make ollamaPull local LLM models
make certsGenerate TLS certificates for mTLS
make scanScan history for leaked secrets
make migrateRemove AI agents from host (destructive)
make nukeRemove containers + volumes
make statusShow container status
make evalRun promptfoo evaluation suite
make lintLint configuration
make auditSecurity audit

Ansible Roles

flowchart TD
Setup["make setup"] --> Prereqs["prereqs\npodman, dirs, validation"]
Prereqs --> Certs["certs\nTLS for mTLS"]
Certs --> Env["env\n.env from pass"]
Env --> SSH["ssh\nrestricted agent"]
SSH --> Containers["containers\nbuild + compose up"]
Containers --> Egress["egress\nnftables whitelist"]
Egress --> OmniRoute["omniroute\nprovider API setup"]
OmniRoute --> Ollama["ollama\nmodel pulling"]
Ollama --> Aliases["aliases\nCLI + shell integration"]
style Setup fill:#533483,stroke:#e94560,color:#fff
Loading
RolePurposeTag
prereqsInstall podman, create dirs, auto-detect UID/GID, validate SSH key + pass entriesprereqs
certsGenerate CA and service TLS certificates for mTLScerts
envGenerate per-service .env files from GNU passenv
sshRestricted SSH agent (single key)ssh
containersTemplate Containerfiles + compose, build images, start servicescontainers, build, up
egressResolve allowed domains and load nftables whitelistegress
omnirouteConfigure AI providers via REST APIomniroute
ollamaPull local LLM modelsollama
aliasesTemplate and install securetty CLI + shell aliasesaliases
scanScan AI conversation history for leaked secretsscan
migrateRemove AI agents from host (destructive, never tag)migrate

Configuration

All configuration lives in group_vars/all.yml:

SectionWhat it controls
User/pathsUsername, home dir, SSH key name (UID/GID auto-detected)
ProvidersOmniRoute provider list + priorities
API keysGNU pass paths for each key (securetty_pass_keys)
Agentsnpm/pip/binary packages, alias config, skip-flags
Allowed domainsEgress whitelist for nftables
OllamaModels to pull
ResourcesCPU/memory limits per container
Packagesdnf + pip packages for dev container
MCP serversJira, GitLab, GitHub, Slack, WordPress config

Common Changes

  • Add a new AI agent: Edit group_vars/all.yml — add to securetty_npm_agents, securetty_pip_agents, or securetty_binary_agents. Add alias entry to securetty_agents. Run securetty rebuild-agents.
  • Add a new AI provider: Store API key in pass, add entry to securetty_pass_keys and securetty_providers in group_vars/all.yml. Run securetty setup.
  • Add an egress domain: Add to securetty_allowed_domains in group_vars/all.yml. Run securetty egress.
  • Add a pip/npm package: Add to securetty_pip_tools or securetty_npm_tools in group_vars/all.yml. Run securetty rebuild-agents.

Design Documents

DocumentDescription
THREAT_MODEL.md8-section threat assessment
docs/security-tiers.mdGraduated 3-tier isolation model + enforcement status
docs/trust-model.mdTrusted/untrusted input boundaries
docs/escalation-gates.mdConfidence gates and risk classification
docs/confidence-scoring.mdLearned escalation model
docs/observability.mdPrometheus metrics and OTEL tracing
docs/sli-dashboard.mdReal-time dashboard and SLI alerting
docs/evaluation-framework.mdpromptfoo eval harness
docs/jira-auto-triage.mdJira auto-triage agent
docs/closed-loop-remediation.mdAutomated SKILL.md fixes
docs/skill-marketplace.mdSkill management and sharing
docs/daemon-mode.mdBackground agent daemon
docs/provenance.mdAgent action provenance
docs/sigstore-verification.mdSupply chain verification

License

See LICENSE.

About

Secure container-based development environment with MCP gateway

Topics

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

securetty

Sandboxed AI development environment. All AI CLI agents run inside ephemeral rootless podman containers with credential isolation, egress filtering, delayed package ingestion, and nftables-enforced network policy. Fully declarative via Ansible.

Architecture

graph TD
Internet["Internet + VPN"]
subgraph host["Host"]
CLI["securetty CLI"]
SSHAgent["SSH agent (restricted)"]
Pass["GNU pass (secrets)"]
Egress["nftables egress whitelist"]
end
subgraph network["Container Network (172.30.100.0/24)"]
OmniRoute["omniroute :4000\nAI provider router"]
Headroom["headroom :8787\nToken compression MCP"]
CloudCLI["cloudcli :3001\nClaude Code Web UI"]
Ollama["ollama :11434\nLocal LLM (GPU)"]
Creds["creds :8800\nCredential proxy"]
Dispatcher["dispatcher :8900\nmTLS work router"]
subgraph mcp["MCP Servers"]
Jira["mcp-jira :8801"]
GitLab["mcp-gitlab :8802"]
GitHub["mcp-github :8803"]
Slack["mcp-slack :8804"]
WordPress["mcp-wordpress :8805"]
end
subgraph scanners["Package Scanners"]
GuardDog["guarddog\nBehavioral + YARA"]
OSV["osv-scanner\nVulnerability DB"]
end
subgraph agents["Ephemeral Agent Containers"]
Dev["securetty-claude-*\nsecuretty-codex-*\n..."]
end
subgraph daemons["Background Daemons"]
JiraPoller["jira-poller\nAuto-triage"]
ReviewMgr["review-manager\nMR/PR feedback"]
end
end
CLI --> Dev
Pass -->|"generate-env.sh"| Creds
SSHAgent -->|"socket (ro)"| Dev
Egress -->|"default-drop"| Internet
Dev --> OmniRoute
Dev --> Headroom
Dev --> Ollama
OmniRoute --> Internet
style network fill:#0f3460,stroke:#e94560,color:#fff
style host fill:#1a1a2e,stroke:#e94560,color:#fff
style mcp fill:#16213e,stroke:#0f3460,color:#fff
style scanners fill:#16213e,stroke:#0f3460,color:#fff
style agents fill:#16213e,stroke:#0f3460,color:#fff
style daemons fill:#16213e,stroke:#0f3460,color:#fff
Loading

Security Model

Credential Isolation

Secrets live in GNU pass on the host. generate-env.sh resolves them at container start into per-service .env files. Agent containers receive only OMNIROUTE_API_KEY — never raw provider keys. The credential proxy (securetty-creds) brokers access to everything else.

Egress Filtering

Default-drop nftables policy in the rootless network namespace. Only resolved IPs from approved domains pass. Domain whitelist is in group_vars/all.yml (securetty_allowed_domains). Covers AI providers, git hosts, package registries, and configured services.

Container Hardening

Every agent container runs with:

  • --cap-drop ALL — no Linux capabilities
  • --security-opt no-new-privileges:true — no privilege escalation
  • --read-only — immutable root filesystem
  • --pids-limit 4096 — fork bomb protection
  • --userns=keep-id — rootless user namespace
  • Masked proc/sys paths — no host information leakage
  • Named volumes for caches only — code is bind-mounted

SSH

Dedicated ssh-agent on host with only one key loaded (configurable via securetty_ssh_key). Socket forwarded read-only. Private key never enters container.

Delayed Ingestion

AI agents installed from package versions published >= 7 days ago (configurable via securetty_quarantine_days). npm: queries npm view <pkg> time for version dates. pip: uses uv --exclude-newer. GuardDog and OSV-Scanner continuously scan cached packages for malicious behavior and known vulnerabilities.

DNS

Aardvark DNS resolves container names on the bridge network and forwards external queries to host DNS (169.254.1.1, patched from Google DNS to avoid VPN leaks). VPN domains resolve automatically.

Quick Start

# Prerequisites: podman, podman-compose, ansible, pass (GNU password manager)# Full setup — builds images, configures services, installs CLI + aliases
make setup
# Launch an agent
securetty run claude ~/src/myproject # Personal mode (OmniRoute)
securetty run-work claude ~/src/myproject # Work mode (Vertex AI)# Or use shell aliases
claude ~/src/myproject
claude-work ~/src/myproject

CLI Reference

Usage: securetty <command> [options]
Agent commands:
run <agent> [options] [args] Launch agent in personal mode
run-work <agent> [options] [args] Launch agent in work mode (Vertex AI)
shell [dir] Interactive shell in container
connect [<container>] Reattach to running agent container
code-review <PR-URL> Review a PR/MR via agent
Agent options:
--read Read-only mode (blocks writes)
--max-turns N Limit agent to N turns
--timeout T Kill session after T (e.g. 30m, 1h, 90s)
-p, --prompt <text> Non-interactive prompt (no TTY)
--cleanup keep|remove Container lifecycle (default: remove)
--image <ref> Override container image
-v <host:container> Extra volume mount (repeatable)
Lifecycle:
setup [--ide cursor|vscode] Full setup or generate IDE devcontainer
build Build container images (skip if exist)
rebuild Full rebuild (all image layers)
rebuild-agents Rebuild dev image only (fast)
up / down / restart Start / stop / restart services
nuke Remove containers + volumes (destructive)
update [release|rc|latest] Update securetty (channel-based)
rollback --list|--set <tag> Version management
Configuration:
config list|get|set|unset Runtime configuration management
config profile <name> Switch named profile
check [--fix] [--ai] Health check with auto-repair
egress Reload nftables egress rules + DNS patch
env Regenerate .env files from pass store
Monitoring:
status Dashboard — containers, network, egress, scanners
list [--all] [--json] List securetty containers
top [--live] Container resource usage
scan [alerts|logs] Package scanner results (GuardDog + OSV)
volumes Show volume sizes
preflight Check prerequisites
cost [today|week|all] Session usage tracking
clean [--yes] Remove orphaned containers + stale files
logs <service> [--follow] Show container logs
exec <container> <cmd> Run command in container
version Show CLI and image version info
Orchestration:
dispatch <work-item> Route work item to agent via dispatcher
jobs [status] List dispatched jobs
watch <repo>|--list|--delete Manage polling triggers for repo events
daemon start|stop|status Background agent daemon
dashboard [--once|--json] Real-time TUI dashboard
alerts --check|--notify SLI alerting
jira-triage start|stop|run Jira auto-triage poller
review-manager start|stop MR/PR review feedback manager
Analysis:
retro [--json] [--since] Retrospective failure analysis
confidence --score|--report Agent confidence scoring
eval run|list|report Run promptfoo evaluation suite
skill list|search|install Skill marketplace management
skill run <name> <URL> Run skill against PR/MR/repo URL
init <project-dir> Bootstrap securetty in a new project
Project management:
group <repo> [ls|status|add|clean] Git worktree management
cursor [<path>] Launch Cursor with devcontainer
plugin list|install|remove|update Plugin management
Security:
scan [alerts|logs] Package scanner results (GuardDog + OSV)
audit Run npm audit + pip-audit inside container
test Run shellcheck, yamllint, ansible-lint
migrate Remove AI agents from host (destructive)

Note: All commands go through securetty. The Makefile targets (make setup, make rebuild, etc.) are thin wrappers that call the same ansible playbooks. Use securetty as the single CLI interface.

Two Modes

ModeCLIAliasProviderUse case
Personalsecuretty run <agent>claude, cOmniRoute (auto-routes)Personal projects
Worksecuretty run-work <agent>claude-work, cwGoogle Vertex AIWork projects

Agents

AgentPackageAliasShortType
claude@anthropic-ai/claude-codeclaude / claude-workc / cwnpm
codex@openai/codexcodex / codex-workcx / cxwnpm
gemini@anthropic-ai/claude-codegemini / gemini-workgm / gmwnpm
clineclinecline / cline-workcl / clwnpm
opencodeopencodeopencode / opencode-workocd / ocdwnpm
aideraider-chataider / aider-workai / aiwpip
goosegoose-aigoose / goose-workgs / gswpip
grokgrok-buildgrok / grok-workgr / grwnpm
forge@anthropic-ai/claude-codeforge / forge-workfg / fgwnpm
kiro-clikirokiro-cli / kiro-workki / kiwnpm
pi-aipi-aipi-ai / pi-ai-workpi / piwnpm
kimikimi-clikimi / kimi-workkm / kmwnpm
jcodejcodejcode / jcode-workjc / jcwnpm
ampcodeampcodeamp / amp-worknpm
cursorcursor / cursor-workcr / crwbinary

All agents run with skip-permissions flags. The container is the sandbox.

Services

ContainerPurposePort
securetty-omnirouteAI provider router + dashboard4000
securetty-headroomToken compression MCP server8787
securetty-cloudcliClaude Code Web UI3001
securetty-ollamaLocal LLM server (GPU passthrough)11434
securetty-credsCredential proxy8800
securetty-dispatchermTLS work item router (DAG workflows)8900
securetty-mcp-jiraJira MCP server8801
securetty-mcp-gitlabGitLab MCP server8802
securetty-mcp-githubGitHub MCP server8803
securetty-mcp-slackSlack MCP server8804
securetty-mcp-wordpressWordPress MCP server8805
securetty-guarddogBehavioral + YARA package scanner
securetty-osv-scannerOSV vulnerability scanner
securetty-jira-pollerJira auto-triage daemon
securetty-review-managerMR/PR review feedback daemon
securetty-podman-proxyContainer metrics exporter9402

OmniRoute Providers

Configured via securetty_providers in group_vars/all.yml:

ProviderModelPriority
OpenAIgpt-4o100
Google AI Studiogemini-2.5-flash100
Mistralmistral-large-latest100
OpenRouter(routing)50
Groqllama-3.3-70b-versatile50
Cerebras50
SambaNova50
Ollama (local)(configurable)1 (fallback)

Dashboard: http://localhost:4000

Image Layers

Three container image layers, each building on the previous:

  1. base — Fedora 45 minimal with system packages (dnf)
  2. devbase — Development tools, compilers, language runtimes, pip/npm tooling
  3. dev — AI agents installed via delayed ingestion (7-day quarantine), user account matching host UID/GID

Makefile Targets

TargetDescription
make setupFull setup (all roles)
make buildBuild container images (skips if exist)
make rebuildForce rebuild all images
make rebuild-agentsRebuild dev layer only (fast iteration)
make upStart services
make downStop all containers
make envRegenerate .env files from pass store
make aliasesInstall shell aliases + CLI
make egressResolve domains and load nftables whitelist
make omnirouteConfigure AI providers via REST API
make ollamaPull local LLM models
make certsGenerate TLS certificates for mTLS
make scanScan history for leaked secrets
make migrateRemove AI agents from host (destructive)
make nukeRemove containers + volumes
make statusShow container status
make evalRun promptfoo evaluation suite
make lintLint configuration
make auditSecurity audit

Ansible Roles

flowchart TD
Setup["make setup"] --> Prereqs["prereqs\npodman, dirs, validation"]
Prereqs --> Certs["certs\nTLS for mTLS"]
Certs --> Env["env\n.env from pass"]
Env --> SSH["ssh\nrestricted agent"]
SSH --> Containers["containers\nbuild + compose up"]
Containers --> Egress["egress\nnftables whitelist"]
Egress --> OmniRoute["omniroute\nprovider API setup"]
OmniRoute --> Ollama["ollama\nmodel pulling"]
Ollama --> Aliases["aliases\nCLI + shell integration"]
style Setup fill:#533483,stroke:#e94560,color:#fff
Loading
RolePurposeTag
prereqsInstall podman, create dirs, auto-detect UID/GID, validate SSH key + pass entriesprereqs
certsGenerate CA and service TLS certificates for mTLScerts
envGenerate per-service .env files from GNU passenv
sshRestricted SSH agent (single key)ssh
containersTemplate Containerfiles + compose, build images, start servicescontainers, build, up
egressResolve allowed domains and load nftables whitelistegress
omnirouteConfigure AI providers via REST APIomniroute
ollamaPull local LLM modelsollama
aliasesTemplate and install securetty CLI + shell aliasesaliases
scanScan AI conversation history for leaked secretsscan
migrateRemove AI agents from host (destructive, never tag)migrate

Configuration

All configuration lives in group_vars/all.yml:

SectionWhat it controls
User/pathsUsername, home dir, SSH key name (UID/GID auto-detected)
ProvidersOmniRoute provider list + priorities
API keysGNU pass paths for each key (securetty_pass_keys)
Agentsnpm/pip/binary packages, alias config, skip-flags
Allowed domainsEgress whitelist for nftables
OllamaModels to pull
ResourcesCPU/memory limits per container
Packagesdnf + pip packages for dev container
MCP serversJira, GitLab, GitHub, Slack, WordPress config

Common Changes

  • Add a new AI agent: Edit group_vars/all.yml — add to securetty_npm_agents, securetty_pip_agents, or securetty_binary_agents. Add alias entry to securetty_agents. Run securetty rebuild-agents.
  • Add a new AI provider: Store API key in pass, add entry to securetty_pass_keys and securetty_providers in group_vars/all.yml. Run securetty setup.
  • Add an egress domain: Add to securetty_allowed_domains in group_vars/all.yml. Run securetty egress.
  • Add a pip/npm package: Add to securetty_pip_tools or securetty_npm_tools in group_vars/all.yml. Run securetty rebuild-agents.

Design Documents

DocumentDescription
THREAT_MODEL.md8-section threat assessment
docs/security-tiers.mdGraduated 3-tier isolation model + enforcement status
docs/trust-model.mdTrusted/untrusted input boundaries
docs/escalation-gates.mdConfidence gates and risk classification
docs/confidence-scoring.mdLearned escalation model
docs/observability.mdPrometheus metrics and OTEL tracing
docs/sli-dashboard.mdReal-time dashboard and SLI alerting
docs/evaluation-framework.mdpromptfoo eval harness
docs/jira-auto-triage.mdJira auto-triage agent
docs/closed-loop-remediation.mdAutomated SKILL.md fixes
docs/skill-marketplace.mdSkill management and sharing
docs/daemon-mode.mdBackground agent daemon
docs/provenance.mdAgent action provenance
docs/sigstore-verification.mdSupply chain verification

License

See LICENSE.

About

Secure container-based development environment with MCP gateway

Topics

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

securetty

Sandboxed AI development environment. All AI CLI agents run inside ephemeral rootless podman containers with credential isolation, egress filtering, delayed package ingestion, and nftables-enforced network policy. Fully declarative via Ansible.

Architecture

graph TD
Internet["Internet + VPN"]
subgraph host["Host"]
CLI["securetty CLI"]
SSHAgent["SSH agent (restricted)"]
Pass["GNU pass (secrets)"]
Egress["nftables egress whitelist"]
end
subgraph network["Container Network (172.30.100.0/24)"]
OmniRoute["omniroute :4000\nAI provider router"]
Headroom["headroom :8787\nToken compression MCP"]
CloudCLI["cloudcli :3001\nClaude Code Web UI"]
Ollama["ollama :11434\nLocal LLM (GPU)"]
Creds["creds :8800\nCredential proxy"]
Dispatcher["dispatcher :8900\nmTLS work router"]
subgraph mcp["MCP Servers"]
Jira["mcp-jira :8801"]
GitLab["mcp-gitlab :8802"]
GitHub["mcp-github :8803"]
Slack["mcp-slack :8804"]
WordPress["mcp-wordpress :8805"]
end
subgraph scanners["Package Scanners"]
GuardDog["guarddog\nBehavioral + YARA"]
OSV["osv-scanner\nVulnerability DB"]
end
subgraph agents["Ephemeral Agent Containers"]
Dev["securetty-claude-*\nsecuretty-codex-*\n..."]
end
subgraph daemons["Background Daemons"]
JiraPoller["jira-poller\nAuto-triage"]
ReviewMgr["review-manager\nMR/PR feedback"]
end
end
CLI --> Dev
Pass -->|"generate-env.sh"| Creds
SSHAgent -->|"socket (ro)"| Dev
Egress -->|"default-drop"| Internet
Dev --> OmniRoute
Dev --> Headroom
Dev --> Ollama
OmniRoute --> Internet
style network fill:#0f3460,stroke:#e94560,color:#fff
style host fill:#1a1a2e,stroke:#e94560,color:#fff
style mcp fill:#16213e,stroke:#0f3460,color:#fff
style scanners fill:#16213e,stroke:#0f3460,color:#fff
style agents fill:#16213e,stroke:#0f3460,color:#fff
style daemons fill:#16213e,stroke:#0f3460,color:#fff
Loading

Security Model

Credential Isolation

Secrets live in GNU pass on the host. generate-env.sh resolves them at container start into per-service .env files. Agent containers receive only OMNIROUTE_API_KEY — never raw provider keys. The credential proxy (securetty-creds) brokers access to everything else.

Egress Filtering

Default-drop nftables policy in the rootless network namespace. Only resolved IPs from approved domains pass. Domain whitelist is in group_vars/all.yml (securetty_allowed_domains). Covers AI providers, git hosts, package registries, and configured services.

Container Hardening

Every agent container runs with:

  • --cap-drop ALL — no Linux capabilities
  • --security-opt no-new-privileges:true — no privilege escalation
  • --read-only — immutable root filesystem
  • --pids-limit 4096 — fork bomb protection
  • --userns=keep-id — rootless user namespace
  • Masked proc/sys paths — no host information leakage
  • Named volumes for caches only — code is bind-mounted

SSH

Dedicated ssh-agent on host with only one key loaded (configurable via securetty_ssh_key). Socket forwarded read-only. Private key never enters container.

Delayed Ingestion

AI agents installed from package versions published >= 7 days ago (configurable via securetty_quarantine_days). npm: queries npm view <pkg> time for version dates. pip: uses uv --exclude-newer. GuardDog and OSV-Scanner continuously scan cached packages for malicious behavior and known vulnerabilities.

DNS

Aardvark DNS resolves container names on the bridge network and forwards external queries to host DNS (169.254.1.1, patched from Google DNS to avoid VPN leaks). VPN domains resolve automatically.

Quick Start

# Prerequisites: podman, podman-compose, ansible, pass (GNU password manager)# Full setup — builds images, configures services, installs CLI + aliases
make setup
# Launch an agent
securetty run claude ~/src/myproject # Personal mode (OmniRoute)
securetty run-work claude ~/src/myproject # Work mode (Vertex AI)# Or use shell aliases
claude ~/src/myproject
claude-work ~/src/myproject

CLI Reference

Usage: securetty <command> [options]
Agent commands:
run <agent> [options] [args] Launch agent in personal mode
run-work <agent> [options] [args] Launch agent in work mode (Vertex AI)
shell [dir] Interactive shell in container
connect [<container>] Reattach to running agent container
code-review <PR-URL> Review a PR/MR via agent
Agent options:
--read Read-only mode (blocks writes)
--max-turns N Limit agent to N turns
--timeout T Kill session after T (e.g. 30m, 1h, 90s)
-p, --prompt <text> Non-interactive prompt (no TTY)
--cleanup keep|remove Container lifecycle (default: remove)
--image <ref> Override container image
-v <host:container> Extra volume mount (repeatable)
Lifecycle:
setup [--ide cursor|vscode] Full setup or generate IDE devcontainer
build Build container images (skip if exist)
rebuild Full rebuild (all image layers)
rebuild-agents Rebuild dev image only (fast)
up / down / restart Start / stop / restart services
nuke Remove containers + volumes (destructive)
update [release|rc|latest] Update securetty (channel-based)
rollback --list|--set <tag> Version management
Configuration:
config list|get|set|unset Runtime configuration management
config profile <name> Switch named profile
check [--fix] [--ai] Health check with auto-repair
egress Reload nftables egress rules + DNS patch
env Regenerate .env files from pass store
Monitoring:
status Dashboard — containers, network, egress, scanners
list [--all] [--json] List securetty containers
top [--live] Container resource usage
scan [alerts|logs] Package scanner results (GuardDog + OSV)
volumes Show volume sizes
preflight Check prerequisites
cost [today|week|all] Session usage tracking
clean [--yes] Remove orphaned containers + stale files
logs <service> [--follow] Show container logs
exec <container> <cmd> Run command in container
version Show CLI and image version info
Orchestration:
dispatch <work-item> Route work item to agent via dispatcher
jobs [status] List dispatched jobs
watch <repo>|--list|--delete Manage polling triggers for repo events
daemon start|stop|status Background agent daemon
dashboard [--once|--json] Real-time TUI dashboard
alerts --check|--notify SLI alerting
jira-triage start|stop|run Jira auto-triage poller
review-manager start|stop MR/PR review feedback manager
Analysis:
retro [--json] [--since] Retrospective failure analysis
confidence --score|--report Agent confidence scoring
eval run|list|report Run promptfoo evaluation suite
skill list|search|install Skill marketplace management
skill run <name> <URL> Run skill against PR/MR/repo URL
init <project-dir> Bootstrap securetty in a new project
Project management:
group <repo> [ls|status|add|clean] Git worktree management
cursor [<path>] Launch Cursor with devcontainer
plugin list|install|remove|update Plugin management
Security:
scan [alerts|logs] Package scanner results (GuardDog + OSV)
audit Run npm audit + pip-audit inside container
test Run shellcheck, yamllint, ansible-lint
migrate Remove AI agents from host (destructive)

Note: All commands go through securetty. The Makefile targets (make setup, make rebuild, etc.) are thin wrappers that call the same ansible playbooks. Use securetty as the single CLI interface.

Two Modes

ModeCLIAliasProviderUse case
Personalsecuretty run <agent>claude, cOmniRoute (auto-routes)Personal projects
Worksecuretty run-work <agent>claude-work, cwGoogle Vertex AIWork projects

Agents

AgentPackageAliasShortType
claude@anthropic-ai/claude-codeclaude / claude-workc / cwnpm
codex@openai/codexcodex / codex-workcx / cxwnpm
gemini@anthropic-ai/claude-codegemini / gemini-workgm / gmwnpm
clineclinecline / cline-workcl / clwnpm
opencodeopencodeopencode / opencode-workocd / ocdwnpm
aideraider-chataider / aider-workai / aiwpip
goosegoose-aigoose / goose-workgs / gswpip
grokgrok-buildgrok / grok-workgr / grwnpm
forge@anthropic-ai/claude-codeforge / forge-workfg / fgwnpm
kiro-clikirokiro-cli / kiro-workki / kiwnpm
pi-aipi-aipi-ai / pi-ai-workpi / piwnpm
kimikimi-clikimi / kimi-workkm / kmwnpm
jcodejcodejcode / jcode-workjc / jcwnpm
ampcodeampcodeamp / amp-worknpm
cursorcursor / cursor-workcr / crwbinary

All agents run with skip-permissions flags. The container is the sandbox.

Services

ContainerPurposePort
securetty-omnirouteAI provider router + dashboard4000
securetty-headroomToken compression MCP server8787
securetty-cloudcliClaude Code Web UI3001
securetty-ollamaLocal LLM server (GPU passthrough)11434
securetty-credsCredential proxy8800
securetty-dispatchermTLS work item router (DAG workflows)8900
securetty-mcp-jiraJira MCP server8801
securetty-mcp-gitlabGitLab MCP server8802
securetty-mcp-githubGitHub MCP server8803
securetty-mcp-slackSlack MCP server8804
securetty-mcp-wordpressWordPress MCP server8805
securetty-guarddogBehavioral + YARA package scanner
securetty-osv-scannerOSV vulnerability scanner
securetty-jira-pollerJira auto-triage daemon
securetty-review-managerMR/PR review feedback daemon
securetty-podman-proxyContainer metrics exporter9402

OmniRoute Providers

Configured via securetty_providers in group_vars/all.yml:

ProviderModelPriority
OpenAIgpt-4o100
Google AI Studiogemini-2.5-flash100
Mistralmistral-large-latest100
OpenRouter(routing)50
Groqllama-3.3-70b-versatile50
Cerebras50
SambaNova50
Ollama (local)(configurable)1 (fallback)

Dashboard: http://localhost:4000

Image Layers

Three container image layers, each building on the previous:

  1. base — Fedora 45 minimal with system packages (dnf)
  2. devbase — Development tools, compilers, language runtimes, pip/npm tooling
  3. dev — AI agents installed via delayed ingestion (7-day quarantine), user account matching host UID/GID

Makefile Targets

TargetDescription
make setupFull setup (all roles)
make buildBuild container images (skips if exist)
make rebuildForce rebuild all images
make rebuild-agentsRebuild dev layer only (fast iteration)
make upStart services
make downStop all containers
make envRegenerate .env files from pass store
make aliasesInstall shell aliases + CLI
make egressResolve domains and load nftables whitelist
make omnirouteConfigure AI providers via REST API
make ollamaPull local LLM models
make certsGenerate TLS certificates for mTLS
make scanScan history for leaked secrets
make migrateRemove AI agents from host (destructive)
make nukeRemove containers + volumes
make statusShow container status
make evalRun promptfoo evaluation suite
make lintLint configuration
make auditSecurity audit

Ansible Roles

flowchart TD
Setup["make setup"] --> Prereqs["prereqs\npodman, dirs, validation"]
Prereqs --> Certs["certs\nTLS for mTLS"]
Certs --> Env["env\n.env from pass"]
Env --> SSH["ssh\nrestricted agent"]
SSH --> Containers["containers\nbuild + compose up"]
Containers --> Egress["egress\nnftables whitelist"]
Egress --> OmniRoute["omniroute\nprovider API setup"]
OmniRoute --> Ollama["ollama\nmodel pulling"]
Ollama --> Aliases["aliases\nCLI + shell integration"]
style Setup fill:#533483,stroke:#e94560,color:#fff
Loading
RolePurposeTag
prereqsInstall podman, create dirs, auto-detect UID/GID, validate SSH key + pass entriesprereqs
certsGenerate CA and service TLS certificates for mTLScerts
envGenerate per-service .env files from GNU passenv
sshRestricted SSH agent (single key)ssh
containersTemplate Containerfiles + compose, build images, start servicescontainers, build, up
egressResolve allowed domains and load nftables whitelistegress
omnirouteConfigure AI providers via REST APIomniroute
ollamaPull local LLM modelsollama
aliasesTemplate and install securetty CLI + shell aliasesaliases
scanScan AI conversation history for leaked secretsscan
migrateRemove AI agents from host (destructive, never tag)migrate

Configuration

All configuration lives in group_vars/all.yml:

SectionWhat it controls
User/pathsUsername, home dir, SSH key name (UID/GID auto-detected)
ProvidersOmniRoute provider list + priorities
API keysGNU pass paths for each key (securetty_pass_keys)
Agentsnpm/pip/binary packages, alias config, skip-flags
Allowed domainsEgress whitelist for nftables
OllamaModels to pull
ResourcesCPU/memory limits per container
Packagesdnf + pip packages for dev container
MCP serversJira, GitLab, GitHub, Slack, WordPress config

Common Changes

  • Add a new AI agent: Edit group_vars/all.yml — add to securetty_npm_agents, securetty_pip_agents, or securetty_binary_agents. Add alias entry to securetty_agents. Run securetty rebuild-agents.
  • Add a new AI provider: Store API key in pass, add entry to securetty_pass_keys and securetty_providers in group_vars/all.yml. Run securetty setup.
  • Add an egress domain: Add to securetty_allowed_domains in group_vars/all.yml. Run securetty egress.
  • Add a pip/npm package: Add to securetty_pip_tools or securetty_npm_tools in group_vars/all.yml. Run securetty rebuild-agents.

Design Documents

DocumentDescription
THREAT_MODEL.md8-section threat assessment
docs/security-tiers.mdGraduated 3-tier isolation model + enforcement status
docs/trust-model.mdTrusted/untrusted input boundaries
docs/escalation-gates.mdConfidence gates and risk classification
docs/confidence-scoring.mdLearned escalation model
docs/observability.mdPrometheus metrics and OTEL tracing
docs/sli-dashboard.mdReal-time dashboard and SLI alerting
docs/evaluation-framework.mdpromptfoo eval harness
docs/jira-auto-triage.mdJira auto-triage agent
docs/closed-loop-remediation.mdAutomated SKILL.md fixes
docs/skill-marketplace.mdSkill management and sharing
docs/daemon-mode.mdBackground agent daemon
docs/provenance.mdAgent action provenance
docs/sigstore-verification.mdSupply chain verification

License

See LICENSE.

About

Secure container-based development environment with MCP gateway

Topics

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

securetty

Sandboxed AI development environment. All AI CLI agents run inside ephemeral rootless podman containers with credential isolation, egress filtering, delayed package ingestion, and nftables-enforced network policy. Fully declarative via Ansible.

Architecture

graph TD
Internet["Internet + VPN"]
subgraph host["Host"]
CLI["securetty CLI"]
SSHAgent["SSH agent (restricted)"]
Pass["GNU pass (secrets)"]
Egress["nftables egress whitelist"]
end
subgraph network["Container Network (172.30.100.0/24)"]
OmniRoute["omniroute :4000\nAI provider router"]
Headroom["headroom :8787\nToken compression MCP"]
CloudCLI["cloudcli :3001\nClaude Code Web UI"]
Ollama["ollama :11434\nLocal LLM (GPU)"]
Creds["creds :8800\nCredential proxy"]
Dispatcher["dispatcher :8900\nmTLS work router"]
subgraph mcp["MCP Servers"]
Jira["mcp-jira :8801"]
GitLab["mcp-gitlab :8802"]
GitHub["mcp-github :8803"]
Slack["mcp-slack :8804"]
WordPress["mcp-wordpress :8805"]
end
subgraph scanners["Package Scanners"]
GuardDog["guarddog\nBehavioral + YARA"]
OSV["osv-scanner\nVulnerability DB"]
end
subgraph agents["Ephemeral Agent Containers"]
Dev["securetty-claude-*\nsecuretty-codex-*\n..."]
end
subgraph daemons["Background Daemons"]
JiraPoller["jira-poller\nAuto-triage"]
ReviewMgr["review-manager\nMR/PR feedback"]
end
end
CLI --> Dev
Pass -->|"generate-env.sh"| Creds
SSHAgent -->|"socket (ro)"| Dev
Egress -->|"default-drop"| Internet
Dev --> OmniRoute
Dev --> Headroom
Dev --> Ollama
OmniRoute --> Internet
style network fill:#0f3460,stroke:#e94560,color:#fff
style host fill:#1a1a2e,stroke:#e94560,color:#fff
style mcp fill:#16213e,stroke:#0f3460,color:#fff
style scanners fill:#16213e,stroke:#0f3460,color:#fff
style agents fill:#16213e,stroke:#0f3460,color:#fff
style daemons fill:#16213e,stroke:#0f3460,color:#fff
Loading

Security Model

Credential Isolation

Secrets live in GNU pass on the host. generate-env.sh resolves them at container start into per-service .env files. Agent containers receive only OMNIROUTE_API_KEY — never raw provider keys. The credential proxy (securetty-creds) brokers access to everything else.

Egress Filtering

Default-drop nftables policy in the rootless network namespace. Only resolved IPs from approved domains pass. Domain whitelist is in group_vars/all.yml (securetty_allowed_domains). Covers AI providers, git hosts, package registries, and configured services.

Container Hardening

Every agent container runs with:

  • --cap-drop ALL — no Linux capabilities
  • --security-opt no-new-privileges:true — no privilege escalation
  • --read-only — immutable root filesystem
  • --pids-limit 4096 — fork bomb protection
  • --userns=keep-id — rootless user namespace
  • Masked proc/sys paths — no host information leakage
  • Named volumes for caches only — code is bind-mounted

SSH

Dedicated ssh-agent on host with only one key loaded (configurable via securetty_ssh_key). Socket forwarded read-only. Private key never enters container.

Delayed Ingestion

AI agents installed from package versions published >= 7 days ago (configurable via securetty_quarantine_days). npm: queries npm view <pkg> time for version dates. pip: uses uv --exclude-newer. GuardDog and OSV-Scanner continuously scan cached packages for malicious behavior and known vulnerabilities.

DNS

Aardvark DNS resolves container names on the bridge network and forwards external queries to host DNS (169.254.1.1, patched from Google DNS to avoid VPN leaks). VPN domains resolve automatically.

Quick Start

# Prerequisites: podman, podman-compose, ansible, pass (GNU password manager)# Full setup — builds images, configures services, installs CLI + aliases
make setup
# Launch an agent
securetty run claude ~/src/myproject # Personal mode (OmniRoute)
securetty run-work claude ~/src/myproject # Work mode (Vertex AI)# Or use shell aliases
claude ~/src/myproject
claude-work ~/src/myproject

CLI Reference

Usage: securetty <command> [options]
Agent commands:
run <agent> [options] [args] Launch agent in personal mode
run-work <agent> [options] [args] Launch agent in work mode (Vertex AI)
shell [dir] Interactive shell in container
connect [<container>] Reattach to running agent container
code-review <PR-URL> Review a PR/MR via agent
Agent options:
--read Read-only mode (blocks writes)
--max-turns N Limit agent to N turns
--timeout T Kill session after T (e.g. 30m, 1h, 90s)
-p, --prompt <text> Non-interactive prompt (no TTY)
--cleanup keep|remove Container lifecycle (default: remove)
--image <ref> Override container image
-v <host:container> Extra volume mount (repeatable)
Lifecycle:
setup [--ide cursor|vscode] Full setup or generate IDE devcontainer
build Build container images (skip if exist)
rebuild Full rebuild (all image layers)
rebuild-agents Rebuild dev image only (fast)
up / down / restart Start / stop / restart services
nuke Remove containers + volumes (destructive)
update [release|rc|latest] Update securetty (channel-based)
rollback --list|--set <tag> Version management
Configuration:
config list|get|set|unset Runtime configuration management
config profile <name> Switch named profile
check [--fix] [--ai] Health check with auto-repair
egress Reload nftables egress rules + DNS patch
env Regenerate .env files from pass store
Monitoring:
status Dashboard — containers, network, egress, scanners
list [--all] [--json] List securetty containers
top [--live] Container resource usage
scan [alerts|logs] Package scanner results (GuardDog + OSV)
volumes Show volume sizes
preflight Check prerequisites
cost [today|week|all] Session usage tracking
clean [--yes] Remove orphaned containers + stale files
logs <service> [--follow] Show container logs
exec <container> <cmd> Run command in container
version Show CLI and image version info
Orchestration:
dispatch <work-item> Route work item to agent via dispatcher
jobs [status] List dispatched jobs
watch <repo>|--list|--delete Manage polling triggers for repo events
daemon start|stop|status Background agent daemon
dashboard [--once|--json] Real-time TUI dashboard
alerts --check|--notify SLI alerting
jira-triage start|stop|run Jira auto-triage poller
review-manager start|stop MR/PR review feedback manager
Analysis:
retro [--json] [--since] Retrospective failure analysis
confidence --score|--report Agent confidence scoring
eval run|list|report Run promptfoo evaluation suite
skill list|search|install Skill marketplace management
skill run <name> <URL> Run skill against PR/MR/repo URL
init <project-dir> Bootstrap securetty in a new project
Project management:
group <repo> [ls|status|add|clean] Git worktree management
cursor [<path>] Launch Cursor with devcontainer
plugin list|install|remove|update Plugin management
Security:
scan [alerts|logs] Package scanner results (GuardDog + OSV)
audit Run npm audit + pip-audit inside container
test Run shellcheck, yamllint, ansible-lint
migrate Remove AI agents from host (destructive)

Note: All commands go through securetty. The Makefile targets (make setup, make rebuild, etc.) are thin wrappers that call the same ansible playbooks. Use securetty as the single CLI interface.

Two Modes

ModeCLIAliasProviderUse case
Personalsecuretty run <agent>claude, cOmniRoute (auto-routes)Personal projects
Worksecuretty run-work <agent>claude-work, cwGoogle Vertex AIWork projects

Agents

AgentPackageAliasShortType
claude@anthropic-ai/claude-codeclaude / claude-workc / cwnpm
codex@openai/codexcodex / codex-workcx / cxwnpm
gemini@anthropic-ai/claude-codegemini / gemini-workgm / gmwnpm
clineclinecline / cline-workcl / clwnpm
opencodeopencodeopencode / opencode-workocd / ocdwnpm
aideraider-chataider / aider-workai / aiwpip
goosegoose-aigoose / goose-workgs / gswpip
grokgrok-buildgrok / grok-workgr / grwnpm
forge@anthropic-ai/claude-codeforge / forge-workfg / fgwnpm
kiro-clikirokiro-cli / kiro-workki / kiwnpm
pi-aipi-aipi-ai / pi-ai-workpi / piwnpm
kimikimi-clikimi / kimi-workkm / kmwnpm
jcodejcodejcode / jcode-workjc / jcwnpm
ampcodeampcodeamp / amp-worknpm
cursorcursor / cursor-workcr / crwbinary

All agents run with skip-permissions flags. The container is the sandbox.

Services

ContainerPurposePort
securetty-omnirouteAI provider router + dashboard4000
securetty-headroomToken compression MCP server8787
securetty-cloudcliClaude Code Web UI3001
securetty-ollamaLocal LLM server (GPU passthrough)11434
securetty-credsCredential proxy8800
securetty-dispatchermTLS work item router (DAG workflows)8900
securetty-mcp-jiraJira MCP server8801
securetty-mcp-gitlabGitLab MCP server8802
securetty-mcp-githubGitHub MCP server8803
securetty-mcp-slackSlack MCP server8804
securetty-mcp-wordpressWordPress MCP server8805
securetty-guarddogBehavioral + YARA package scanner
securetty-osv-scannerOSV vulnerability scanner
securetty-jira-pollerJira auto-triage daemon
securetty-review-managerMR/PR review feedback daemon
securetty-podman-proxyContainer metrics exporter9402

OmniRoute Providers

Configured via securetty_providers in group_vars/all.yml:

ProviderModelPriority
OpenAIgpt-4o100
Google AI Studiogemini-2.5-flash100
Mistralmistral-large-latest100
OpenRouter(routing)50
Groqllama-3.3-70b-versatile50
Cerebras50
SambaNova50
Ollama (local)(configurable)1 (fallback)

Dashboard: http://localhost:4000

Image Layers

Three container image layers, each building on the previous:

  1. base — Fedora 45 minimal with system packages (dnf)
  2. devbase — Development tools, compilers, language runtimes, pip/npm tooling
  3. dev — AI agents installed via delayed ingestion (7-day quarantine), user account matching host UID/GID

Makefile Targets

TargetDescription
make setupFull setup (all roles)
make buildBuild container images (skips if exist)
make rebuildForce rebuild all images
make rebuild-agentsRebuild dev layer only (fast iteration)
make upStart services
make downStop all containers
make envRegenerate .env files from pass store
make aliasesInstall shell aliases + CLI
make egressResolve domains and load nftables whitelist
make omnirouteConfigure AI providers via REST API
make ollamaPull local LLM models
make certsGenerate TLS certificates for mTLS
make scanScan history for leaked secrets
make migrateRemove AI agents from host (destructive)
make nukeRemove containers + volumes
make statusShow container status
make evalRun promptfoo evaluation suite
make lintLint configuration
make auditSecurity audit

Ansible Roles

flowchart TD
Setup["make setup"] --> Prereqs["prereqs\npodman, dirs, validation"]
Prereqs --> Certs["certs\nTLS for mTLS"]
Certs --> Env["env\n.env from pass"]
Env --> SSH["ssh\nrestricted agent"]
SSH --> Containers["containers\nbuild + compose up"]
Containers --> Egress["egress\nnftables whitelist"]
Egress --> OmniRoute["omniroute\nprovider API setup"]
OmniRoute --> Ollama["ollama\nmodel pulling"]
Ollama --> Aliases["aliases\nCLI + shell integration"]
style Setup fill:#533483,stroke:#e94560,color:#fff
Loading
RolePurposeTag
prereqsInstall podman, create dirs, auto-detect UID/GID, validate SSH key + pass entriesprereqs
certsGenerate CA and service TLS certificates for mTLScerts
envGenerate per-service .env files from GNU passenv
sshRestricted SSH agent (single key)ssh
containersTemplate Containerfiles + compose, build images, start servicescontainers, build, up
egressResolve allowed domains and load nftables whitelistegress
omnirouteConfigure AI providers via REST APIomniroute
ollamaPull local LLM modelsollama
aliasesTemplate and install securetty CLI + shell aliasesaliases
scanScan AI conversation history for leaked secretsscan
migrateRemove AI agents from host (destructive, never tag)migrate

Configuration

All configuration lives in group_vars/all.yml:

SectionWhat it controls
User/pathsUsername, home dir, SSH key name (UID/GID auto-detected)
ProvidersOmniRoute provider list + priorities
API keysGNU pass paths for each key (securetty_pass_keys)
Agentsnpm/pip/binary packages, alias config, skip-flags
Allowed domainsEgress whitelist for nftables
OllamaModels to pull
ResourcesCPU/memory limits per container
Packagesdnf + pip packages for dev container
MCP serversJira, GitLab, GitHub, Slack, WordPress config

Common Changes

  • Add a new AI agent: Edit group_vars/all.yml — add to securetty_npm_agents, securetty_pip_agents, or securetty_binary_agents. Add alias entry to securetty_agents. Run securetty rebuild-agents.
  • Add a new AI provider: Store API key in pass, add entry to securetty_pass_keys and securetty_providers in group_vars/all.yml. Run securetty setup.
  • Add an egress domain: Add to securetty_allowed_domains in group_vars/all.yml. Run securetty egress.
  • Add a pip/npm package: Add to securetty_pip_tools or securetty_npm_tools in group_vars/all.yml. Run securetty rebuild-agents.

Design Documents

DocumentDescription
THREAT_MODEL.md8-section threat assessment
docs/security-tiers.mdGraduated 3-tier isolation model + enforcement status
docs/trust-model.mdTrusted/untrusted input boundaries
docs/escalation-gates.mdConfidence gates and risk classification
docs/confidence-scoring.mdLearned escalation model
docs/observability.mdPrometheus metrics and OTEL tracing
docs/sli-dashboard.mdReal-time dashboard and SLI alerting
docs/evaluation-framework.mdpromptfoo eval harness
docs/jira-auto-triage.mdJira auto-triage agent
docs/closed-loop-remediation.mdAutomated SKILL.md fixes
docs/skill-marketplace.mdSkill management and sharing
docs/daemon-mode.mdBackground agent daemon
docs/provenance.mdAgent action provenance
docs/sigstore-verification.mdSupply chain verification

License

See LICENSE.

About

Secure container-based development environment with MCP gateway

Topics

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

securetty

Sandboxed AI development environment. All AI CLI agents run inside ephemeral rootless podman containers with credential isolation, egress filtering, delayed package ingestion, and nftables-enforced network policy. Fully declarative via Ansible.

Architecture

graph TD
Internet["Internet + VPN"]
subgraph host["Host"]
CLI["securetty CLI"]
SSHAgent["SSH agent (restricted)"]
Pass["GNU pass (secrets)"]
Egress["nftables egress whitelist"]
end
subgraph network["Container Network (172.30.100.0/24)"]
OmniRoute["omniroute :4000\nAI provider router"]
Headroom["headroom :8787\nToken compression MCP"]
CloudCLI["cloudcli :3001\nClaude Code Web UI"]
Ollama["ollama :11434\nLocal LLM (GPU)"]
Creds["creds :8800\nCredential proxy"]
Dispatcher["dispatcher :8900\nmTLS work router"]
subgraph mcp["MCP Servers"]
Jira["mcp-jira :8801"]
GitLab["mcp-gitlab :8802"]
GitHub["mcp-github :8803"]
Slack["mcp-slack :8804"]
WordPress["mcp-wordpress :8805"]
end
subgraph scanners["Package Scanners"]
GuardDog["guarddog\nBehavioral + YARA"]
OSV["osv-scanner\nVulnerability DB"]
end
subgraph agents["Ephemeral Agent Containers"]
Dev["securetty-claude-*\nsecuretty-codex-*\n..."]
end
subgraph daemons["Background Daemons"]
JiraPoller["jira-poller\nAuto-triage"]
ReviewMgr["review-manager\nMR/PR feedback"]
end
end
CLI --> Dev
Pass -->|"generate-env.sh"| Creds
SSHAgent -->|"socket (ro)"| Dev
Egress -->|"default-drop"| Internet
Dev --> OmniRoute
Dev --> Headroom
Dev --> Ollama
OmniRoute --> Internet
style network fill:#0f3460,stroke:#e94560,color:#fff
style host fill:#1a1a2e,stroke:#e94560,color:#fff
style mcp fill:#16213e,stroke:#0f3460,color:#fff
style scanners fill:#16213e,stroke:#0f3460,color:#fff
style agents fill:#16213e,stroke:#0f3460,color:#fff
style daemons fill:#16213e,stroke:#0f3460,color:#fff
Loading

Security Model

Credential Isolation

Secrets live in GNU pass on the host. generate-env.sh resolves them at container start into per-service .env files. Agent containers receive only OMNIROUTE_API_KEY — never raw provider keys. The credential proxy (securetty-creds) brokers access to everything else.

Egress Filtering

Default-drop nftables policy in the rootless network namespace. Only resolved IPs from approved domains pass. Domain whitelist is in group_vars/all.yml (securetty_allowed_domains). Covers AI providers, git hosts, package registries, and configured services.

Container Hardening

Every agent container runs with:

  • --cap-drop ALL — no Linux capabilities
  • --security-opt no-new-privileges:true — no privilege escalation
  • --read-only — immutable root filesystem
  • --pids-limit 4096 — fork bomb protection
  • --userns=keep-id — rootless user namespace
  • Masked proc/sys paths — no host information leakage
  • Named volumes for caches only — code is bind-mounted

SSH

Dedicated ssh-agent on host with only one key loaded (configurable via securetty_ssh_key). Socket forwarded read-only. Private key never enters container.

Delayed Ingestion

AI agents installed from package versions published >= 7 days ago (configurable via securetty_quarantine_days). npm: queries npm view <pkg> time for version dates. pip: uses uv --exclude-newer. GuardDog and OSV-Scanner continuously scan cached packages for malicious behavior and known vulnerabilities.

DNS

Aardvark DNS resolves container names on the bridge network and forwards external queries to host DNS (169.254.1.1, patched from Google DNS to avoid VPN leaks). VPN domains resolve automatically.

Quick Start

# Prerequisites: podman, podman-compose, ansible, pass (GNU password manager)# Full setup — builds images, configures services, installs CLI + aliases
make setup
# Launch an agent
securetty run claude ~/src/myproject # Personal mode (OmniRoute)
securetty run-work claude ~/src/myproject # Work mode (Vertex AI)# Or use shell aliases
claude ~/src/myproject
claude-work ~/src/myproject

CLI Reference

Usage: securetty <command> [options]
Agent commands:
run <agent> [options] [args] Launch agent in personal mode
run-work <agent> [options] [args] Launch agent in work mode (Vertex AI)
shell [dir] Interactive shell in container
connect [<container>] Reattach to running agent container
code-review <PR-URL> Review a PR/MR via agent
Agent options:
--read Read-only mode (blocks writes)
--max-turns N Limit agent to N turns
--timeout T Kill session after T (e.g. 30m, 1h, 90s)
-p, --prompt <text> Non-interactive prompt (no TTY)
--cleanup keep|remove Container lifecycle (default: remove)
--image <ref> Override container image
-v <host:container> Extra volume mount (repeatable)
Lifecycle:
setup [--ide cursor|vscode] Full setup or generate IDE devcontainer
build Build container images (skip if exist)
rebuild Full rebuild (all image layers)
rebuild-agents Rebuild dev image only (fast)
up / down / restart Start / stop / restart services
nuke Remove containers + volumes (destructive)
update [release|rc|latest] Update securetty (channel-based)
rollback --list|--set <tag> Version management
Configuration:
config list|get|set|unset Runtime configuration management
config profile <name> Switch named profile
check [--fix] [--ai] Health check with auto-repair
egress Reload nftables egress rules + DNS patch
env Regenerate .env files from pass store
Monitoring:
status Dashboard — containers, network, egress, scanners
list [--all] [--json] List securetty containers
top [--live] Container resource usage
scan [alerts|logs] Package scanner results (GuardDog + OSV)
volumes Show volume sizes
preflight Check prerequisites
cost [today|week|all] Session usage tracking
clean [--yes] Remove orphaned containers + stale files
logs <service> [--follow] Show container logs
exec <container> <cmd> Run command in container
version Show CLI and image version info
Orchestration:
dispatch <work-item> Route work item to agent via dispatcher
jobs [status] List dispatched jobs
watch <repo>|--list|--delete Manage polling triggers for repo events
daemon start|stop|status Background agent daemon
dashboard [--once|--json] Real-time TUI dashboard
alerts --check|--notify SLI alerting
jira-triage start|stop|run Jira auto-triage poller
review-manager start|stop MR/PR review feedback manager
Analysis:
retro [--json] [--since] Retrospective failure analysis
confidence --score|--report Agent confidence scoring
eval run|list|report Run promptfoo evaluation suite
skill list|search|install Skill marketplace management
skill run <name> <URL> Run skill against PR/MR/repo URL
init <project-dir> Bootstrap securetty in a new project
Project management:
group <repo> [ls|status|add|clean] Git worktree management
cursor [<path>] Launch Cursor with devcontainer
plugin list|install|remove|update Plugin management
Security:
scan [alerts|logs] Package scanner results (GuardDog + OSV)
audit Run npm audit + pip-audit inside container
test Run shellcheck, yamllint, ansible-lint
migrate Remove AI agents from host (destructive)

Note: All commands go through securetty. The Makefile targets (make setup, make rebuild, etc.) are thin wrappers that call the same ansible playbooks. Use securetty as the single CLI interface.

Two Modes

ModeCLIAliasProviderUse case
Personalsecuretty run <agent>claude, cOmniRoute (auto-routes)Personal projects
Worksecuretty run-work <agent>claude-work, cwGoogle Vertex AIWork projects

Agents

AgentPackageAliasShortType
claude@anthropic-ai/claude-codeclaude / claude-workc / cwnpm
codex@openai/codexcodex / codex-workcx / cxwnpm
gemini@anthropic-ai/claude-codegemini / gemini-workgm / gmwnpm
clineclinecline / cline-workcl / clwnpm
opencodeopencodeopencode / opencode-workocd / ocdwnpm
aideraider-chataider / aider-workai / aiwpip
goosegoose-aigoose / goose-workgs / gswpip
grokgrok-buildgrok / grok-workgr / grwnpm
forge@anthropic-ai/claude-codeforge / forge-workfg / fgwnpm
kiro-clikirokiro-cli / kiro-workki / kiwnpm
pi-aipi-aipi-ai / pi-ai-workpi / piwnpm
kimikimi-clikimi / kimi-workkm / kmwnpm
jcodejcodejcode / jcode-workjc / jcwnpm
ampcodeampcodeamp / amp-worknpm
cursorcursor / cursor-workcr / crwbinary

All agents run with skip-permissions flags. The container is the sandbox.

Services

ContainerPurposePort
securetty-omnirouteAI provider router + dashboard4000
securetty-headroomToken compression MCP server8787
securetty-cloudcliClaude Code Web UI3001
securetty-ollamaLocal LLM server (GPU passthrough)11434
securetty-credsCredential proxy8800
securetty-dispatchermTLS work item router (DAG workflows)8900
securetty-mcp-jiraJira MCP server8801
securetty-mcp-gitlabGitLab MCP server8802
securetty-mcp-githubGitHub MCP server8803
securetty-mcp-slackSlack MCP server8804
securetty-mcp-wordpressWordPress MCP server8805
securetty-guarddogBehavioral + YARA package scanner
securetty-osv-scannerOSV vulnerability scanner
securetty-jira-pollerJira auto-triage daemon
securetty-review-managerMR/PR review feedback daemon
securetty-podman-proxyContainer metrics exporter9402

OmniRoute Providers

Configured via securetty_providers in group_vars/all.yml:

ProviderModelPriority
OpenAIgpt-4o100
Google AI Studiogemini-2.5-flash100
Mistralmistral-large-latest100
OpenRouter(routing)50
Groqllama-3.3-70b-versatile50
Cerebras50
SambaNova50
Ollama (local)(configurable)1 (fallback)

Dashboard: http://localhost:4000

Image Layers

Three container image layers, each building on the previous:

  1. base — Fedora 45 minimal with system packages (dnf)
  2. devbase — Development tools, compilers, language runtimes, pip/npm tooling
  3. dev — AI agents installed via delayed ingestion (7-day quarantine), user account matching host UID/GID

Makefile Targets

TargetDescription
make setupFull setup (all roles)
make buildBuild container images (skips if exist)
make rebuildForce rebuild all images
make rebuild-agentsRebuild dev layer only (fast iteration)
make upStart services
make downStop all containers
make envRegenerate .env files from pass store
make aliasesInstall shell aliases + CLI
make egressResolve domains and load nftables whitelist
make omnirouteConfigure AI providers via REST API
make ollamaPull local LLM models
make certsGenerate TLS certificates for mTLS
make scanScan history for leaked secrets
make migrateRemove AI agents from host (destructive)
make nukeRemove containers + volumes
make statusShow container status
make evalRun promptfoo evaluation suite
make lintLint configuration
make auditSecurity audit

Ansible Roles

flowchart TD
Setup["make setup"] --> Prereqs["prereqs\npodman, dirs, validation"]
Prereqs --> Certs["certs\nTLS for mTLS"]
Certs --> Env["env\n.env from pass"]
Env --> SSH["ssh\nrestricted agent"]
SSH --> Containers["containers\nbuild + compose up"]
Containers --> Egress["egress\nnftables whitelist"]
Egress --> OmniRoute["omniroute\nprovider API setup"]
OmniRoute --> Ollama["ollama\nmodel pulling"]
Ollama --> Aliases["aliases\nCLI + shell integration"]
style Setup fill:#533483,stroke:#e94560,color:#fff
Loading
RolePurposeTag
prereqsInstall podman, create dirs, auto-detect UID/GID, validate SSH key + pass entriesprereqs
certsGenerate CA and service TLS certificates for mTLScerts
envGenerate per-service .env files from GNU passenv
sshRestricted SSH agent (single key)ssh
containersTemplate Containerfiles + compose, build images, start servicescontainers, build, up
egressResolve allowed domains and load nftables whitelistegress
omnirouteConfigure AI providers via REST APIomniroute
ollamaPull local LLM modelsollama
aliasesTemplate and install securetty CLI + shell aliasesaliases
scanScan AI conversation history for leaked secretsscan
migrateRemove AI agents from host (destructive, never tag)migrate

Configuration

All configuration lives in group_vars/all.yml:

SectionWhat it controls
User/pathsUsername, home dir, SSH key name (UID/GID auto-detected)
ProvidersOmniRoute provider list + priorities
API keysGNU pass paths for each key (securetty_pass_keys)
Agentsnpm/pip/binary packages, alias config, skip-flags
Allowed domainsEgress whitelist for nftables
OllamaModels to pull
ResourcesCPU/memory limits per container
Packagesdnf + pip packages for dev container
MCP serversJira, GitLab, GitHub, Slack, WordPress config

Common Changes

  • Add a new AI agent: Edit group_vars/all.yml — add to securetty_npm_agents, securetty_pip_agents, or securetty_binary_agents. Add alias entry to securetty_agents. Run securetty rebuild-agents.
  • Add a new AI provider: Store API key in pass, add entry to securetty_pass_keys and securetty_providers in group_vars/all.yml. Run securetty setup.
  • Add an egress domain: Add to securetty_allowed_domains in group_vars/all.yml. Run securetty egress.
  • Add a pip/npm package: Add to securetty_pip_tools or securetty_npm_tools in group_vars/all.yml. Run securetty rebuild-agents.

Design Documents

DocumentDescription
THREAT_MODEL.md8-section threat assessment
docs/security-tiers.mdGraduated 3-tier isolation model + enforcement status
docs/trust-model.mdTrusted/untrusted input boundaries
docs/escalation-gates.mdConfidence gates and risk classification
docs/confidence-scoring.mdLearned escalation model
docs/observability.mdPrometheus metrics and OTEL tracing
docs/sli-dashboard.mdReal-time dashboard and SLI alerting
docs/evaluation-framework.mdpromptfoo eval harness
docs/jira-auto-triage.mdJira auto-triage agent
docs/closed-loop-remediation.mdAutomated SKILL.md fixes
docs/skill-marketplace.mdSkill management and sharing
docs/daemon-mode.mdBackground agent daemon
docs/provenance.mdAgent action provenance
docs/sigstore-verification.mdSupply chain verification

License

See LICENSE.

About

Secure container-based development environment with MCP gateway

Topics

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

securetty

Sandboxed AI development environment. All AI CLI agents run inside ephemeral rootless podman containers with credential isolation, egress filtering, delayed package ingestion, and nftables-enforced network policy. Fully declarative via Ansible.

Architecture

graph TD
Internet["Internet + VPN"]
subgraph host["Host"]
CLI["securetty CLI"]
SSHAgent["SSH agent (restricted)"]
Pass["GNU pass (secrets)"]
Egress["nftables egress whitelist"]
end
subgraph network["Container Network (172.30.100.0/24)"]
OmniRoute["omniroute :4000\nAI provider router"]
Headroom["headroom :8787\nToken compression MCP"]
CloudCLI["cloudcli :3001\nClaude Code Web UI"]
Ollama["ollama :11434\nLocal LLM (GPU)"]
Creds["creds :8800\nCredential proxy"]
Dispatcher["dispatcher :8900\nmTLS work router"]
subgraph mcp["MCP Servers"]
Jira["mcp-jira :8801"]
GitLab["mcp-gitlab :8802"]
GitHub["mcp-github :8803"]
Slack["mcp-slack :8804"]
WordPress["mcp-wordpress :8805"]
end
subgraph scanners["Package Scanners"]
GuardDog["guarddog\nBehavioral + YARA"]
OSV["osv-scanner\nVulnerability DB"]
end
subgraph agents["Ephemeral Agent Containers"]
Dev["securetty-claude-*\nsecuretty-codex-*\n..."]
end
subgraph daemons["Background Daemons"]
JiraPoller["jira-poller\nAuto-triage"]
ReviewMgr["review-manager\nMR/PR feedback"]
end
end
CLI --> Dev
Pass -->|"generate-env.sh"| Creds
SSHAgent -->|"socket (ro)"| Dev
Egress -->|"default-drop"| Internet
Dev --> OmniRoute
Dev --> Headroom
Dev --> Ollama
OmniRoute --> Internet
style network fill:#0f3460,stroke:#e94560,color:#fff
style host fill:#1a1a2e,stroke:#e94560,color:#fff
style mcp fill:#16213e,stroke:#0f3460,color:#fff
style scanners fill:#16213e,stroke:#0f3460,color:#fff
style agents fill:#16213e,stroke:#0f3460,color:#fff
style daemons fill:#16213e,stroke:#0f3460,color:#fff
Loading

Security Model

Credential Isolation

Secrets live in GNU pass on the host. generate-env.sh resolves them at container start into per-service .env files. Agent containers receive only OMNIROUTE_API_KEY — never raw provider keys. The credential proxy (securetty-creds) brokers access to everything else.

Egress Filtering

Default-drop nftables policy in the rootless network namespace. Only resolved IPs from approved domains pass. Domain whitelist is in group_vars/all.yml (securetty_allowed_domains). Covers AI providers, git hosts, package registries, and configured services.

Container Hardening

Every agent container runs with:

  • --cap-drop ALL — no Linux capabilities
  • --security-opt no-new-privileges:true — no privilege escalation
  • --read-only — immutable root filesystem
  • --pids-limit 4096 — fork bomb protection
  • --userns=keep-id — rootless user namespace
  • Masked proc/sys paths — no host information leakage
  • Named volumes for caches only — code is bind-mounted

SSH

Dedicated ssh-agent on host with only one key loaded (configurable via securetty_ssh_key). Socket forwarded read-only. Private key never enters container.

Delayed Ingestion

AI agents installed from package versions published >= 7 days ago (configurable via securetty_quarantine_days). npm: queries npm view <pkg> time for version dates. pip: uses uv --exclude-newer. GuardDog and OSV-Scanner continuously scan cached packages for malicious behavior and known vulnerabilities.

DNS

Aardvark DNS resolves container names on the bridge network and forwards external queries to host DNS (169.254.1.1, patched from Google DNS to avoid VPN leaks). VPN domains resolve automatically.

Quick Start

# Prerequisites: podman, podman-compose, ansible, pass (GNU password manager)# Full setup — builds images, configures services, installs CLI + aliases
make setup
# Launch an agent
securetty run claude ~/src/myproject # Personal mode (OmniRoute)
securetty run-work claude ~/src/myproject # Work mode (Vertex AI)# Or use shell aliases
claude ~/src/myproject
claude-work ~/src/myproject

CLI Reference

Usage: securetty <command> [options]
Agent commands:
run <agent> [options] [args] Launch agent in personal mode
run-work <agent> [options] [args] Launch agent in work mode (Vertex AI)
shell [dir] Interactive shell in container
connect [<container>] Reattach to running agent container
code-review <PR-URL> Review a PR/MR via agent
Agent options:
--read Read-only mode (blocks writes)
--max-turns N Limit agent to N turns
--timeout T Kill session after T (e.g. 30m, 1h, 90s)
-p, --prompt <text> Non-interactive prompt (no TTY)
--cleanup keep|remove Container lifecycle (default: remove)
--image <ref> Override container image
-v <host:container> Extra volume mount (repeatable)
Lifecycle:
setup [--ide cursor|vscode] Full setup or generate IDE devcontainer
build Build container images (skip if exist)
rebuild Full rebuild (all image layers)
rebuild-agents Rebuild dev image only (fast)
up / down / restart Start / stop / restart services
nuke Remove containers + volumes (destructive)
update [release|rc|latest] Update securetty (channel-based)
rollback --list|--set <tag> Version management
Configuration:
config list|get|set|unset Runtime configuration management
config profile <name> Switch named profile
check [--fix] [--ai] Health check with auto-repair
egress Reload nftables egress rules + DNS patch
env Regenerate .env files from pass store
Monitoring:
status Dashboard — containers, network, egress, scanners
list [--all] [--json] List securetty containers
top [--live] Container resource usage
scan [alerts|logs] Package scanner results (GuardDog + OSV)
volumes Show volume sizes
preflight Check prerequisites
cost [today|week|all] Session usage tracking
clean [--yes] Remove orphaned containers + stale files
logs <service> [--follow] Show container logs
exec <container> <cmd> Run command in container
version Show CLI and image version info
Orchestration:
dispatch <work-item> Route work item to agent via dispatcher
jobs [status] List dispatched jobs
watch <repo>|--list|--delete Manage polling triggers for repo events
daemon start|stop|status Background agent daemon
dashboard [--once|--json] Real-time TUI dashboard
alerts --check|--notify SLI alerting
jira-triage start|stop|run Jira auto-triage poller
review-manager start|stop MR/PR review feedback manager
Analysis:
retro [--json] [--since] Retrospective failure analysis
confidence --score|--report Agent confidence scoring
eval run|list|report Run promptfoo evaluation suite
skill list|search|install Skill marketplace management
skill run <name> <URL> Run skill against PR/MR/repo URL
init <project-dir> Bootstrap securetty in a new project
Project management:
group <repo> [ls|status|add|clean] Git worktree management
cursor [<path>] Launch Cursor with devcontainer
plugin list|install|remove|update Plugin management
Security:
scan [alerts|logs] Package scanner results (GuardDog + OSV)
audit Run npm audit + pip-audit inside container
test Run shellcheck, yamllint, ansible-lint
migrate Remove AI agents from host (destructive)

Note: All commands go through securetty. The Makefile targets (make setup, make rebuild, etc.) are thin wrappers that call the same ansible playbooks. Use securetty as the single CLI interface.

Two Modes

ModeCLIAliasProviderUse case
Personalsecuretty run <agent>claude, cOmniRoute (auto-routes)Personal projects
Worksecuretty run-work <agent>claude-work, cwGoogle Vertex AIWork projects

Agents

AgentPackageAliasShortType
claude@anthropic-ai/claude-codeclaude / claude-workc / cwnpm
codex@openai/codexcodex / codex-workcx / cxwnpm
gemini@anthropic-ai/claude-codegemini / gemini-workgm / gmwnpm
clineclinecline / cline-workcl / clwnpm
opencodeopencodeopencode / opencode-workocd / ocdwnpm
aideraider-chataider / aider-workai / aiwpip
goosegoose-aigoose / goose-workgs / gswpip
grokgrok-buildgrok / grok-workgr / grwnpm
forge@anthropic-ai/claude-codeforge / forge-workfg / fgwnpm
kiro-clikirokiro-cli / kiro-workki / kiwnpm
pi-aipi-aipi-ai / pi-ai-workpi / piwnpm
kimikimi-clikimi / kimi-workkm / kmwnpm
jcodejcodejcode / jcode-workjc / jcwnpm
ampcodeampcodeamp / amp-worknpm
cursorcursor / cursor-workcr / crwbinary

All agents run with skip-permissions flags. The container is the sandbox.

Services

ContainerPurposePort
securetty-omnirouteAI provider router + dashboard4000
securetty-headroomToken compression MCP server8787
securetty-cloudcliClaude Code Web UI3001
securetty-ollamaLocal LLM server (GPU passthrough)11434
securetty-credsCredential proxy8800
securetty-dispatchermTLS work item router (DAG workflows)8900
securetty-mcp-jiraJira MCP server8801
securetty-mcp-gitlabGitLab MCP server8802
securetty-mcp-githubGitHub MCP server8803
securetty-mcp-slackSlack MCP server8804
securetty-mcp-wordpressWordPress MCP server8805
securetty-guarddogBehavioral + YARA package scanner
securetty-osv-scannerOSV vulnerability scanner
securetty-jira-pollerJira auto-triage daemon
securetty-review-managerMR/PR review feedback daemon
securetty-podman-proxyContainer metrics exporter9402

OmniRoute Providers

Configured via securetty_providers in group_vars/all.yml:

ProviderModelPriority
OpenAIgpt-4o100
Google AI Studiogemini-2.5-flash100
Mistralmistral-large-latest100
OpenRouter(routing)50
Groqllama-3.3-70b-versatile50
Cerebras50
SambaNova50
Ollama (local)(configurable)1 (fallback)

Dashboard: http://localhost:4000

Image Layers

Three container image layers, each building on the previous:

  1. base — Fedora 45 minimal with system packages (dnf)
  2. devbase — Development tools, compilers, language runtimes, pip/npm tooling
  3. dev — AI agents installed via delayed ingestion (7-day quarantine), user account matching host UID/GID

Makefile Targets

TargetDescription
make setupFull setup (all roles)
make buildBuild container images (skips if exist)
make rebuildForce rebuild all images
make rebuild-agentsRebuild dev layer only (fast iteration)
make upStart services
make downStop all containers
make envRegenerate .env files from pass store
make aliasesInstall shell aliases + CLI
make egressResolve domains and load nftables whitelist
make omnirouteConfigure AI providers via REST API
make ollamaPull local LLM models
make certsGenerate TLS certificates for mTLS
make scanScan history for leaked secrets
make migrateRemove AI agents from host (destructive)
make nukeRemove containers + volumes
make statusShow container status
make evalRun promptfoo evaluation suite
make lintLint configuration
make auditSecurity audit

Ansible Roles

flowchart TD
Setup["make setup"] --> Prereqs["prereqs\npodman, dirs, validation"]
Prereqs --> Certs["certs\nTLS for mTLS"]
Certs --> Env["env\n.env from pass"]
Env --> SSH["ssh\nrestricted agent"]
SSH --> Containers["containers\nbuild + compose up"]
Containers --> Egress["egress\nnftables whitelist"]
Egress --> OmniRoute["omniroute\nprovider API setup"]
OmniRoute --> Ollama["ollama\nmodel pulling"]
Ollama --> Aliases["aliases\nCLI + shell integration"]
style Setup fill:#533483,stroke:#e94560,color:#fff
Loading
RolePurposeTag
prereqsInstall podman, create dirs, auto-detect UID/GID, validate SSH key + pass entriesprereqs
certsGenerate CA and service TLS certificates for mTLScerts
envGenerate per-service .env files from GNU passenv
sshRestricted SSH agent (single key)ssh
containersTemplate Containerfiles + compose, build images, start servicescontainers, build, up
egressResolve allowed domains and load nftables whitelistegress
omnirouteConfigure AI providers via REST APIomniroute
ollamaPull local LLM modelsollama
aliasesTemplate and install securetty CLI + shell aliasesaliases
scanScan AI conversation history for leaked secretsscan
migrateRemove AI agents from host (destructive, never tag)migrate

Configuration

All configuration lives in group_vars/all.yml:

SectionWhat it controls
User/pathsUsername, home dir, SSH key name (UID/GID auto-detected)
ProvidersOmniRoute provider list + priorities
API keysGNU pass paths for each key (securetty_pass_keys)
Agentsnpm/pip/binary packages, alias config, skip-flags
Allowed domainsEgress whitelist for nftables
OllamaModels to pull
ResourcesCPU/memory limits per container
Packagesdnf + pip packages for dev container
MCP serversJira, GitLab, GitHub, Slack, WordPress config

Common Changes

  • Add a new AI agent: Edit group_vars/all.yml — add to securetty_npm_agents, securetty_pip_agents, or securetty_binary_agents. Add alias entry to securetty_agents. Run securetty rebuild-agents.
  • Add a new AI provider: Store API key in pass, add entry to securetty_pass_keys and securetty_providers in group_vars/all.yml. Run securetty setup.
  • Add an egress domain: Add to securetty_allowed_domains in group_vars/all.yml. Run securetty egress.
  • Add a pip/npm package: Add to securetty_pip_tools or securetty_npm_tools in group_vars/all.yml. Run securetty rebuild-agents.

Design Documents

DocumentDescription
THREAT_MODEL.md8-section threat assessment
docs/security-tiers.mdGraduated 3-tier isolation model + enforcement status
docs/trust-model.mdTrusted/untrusted input boundaries
docs/escalation-gates.mdConfidence gates and risk classification
docs/confidence-scoring.mdLearned escalation model
docs/observability.mdPrometheus metrics and OTEL tracing
docs/sli-dashboard.mdReal-time dashboard and SLI alerting
docs/evaluation-framework.mdpromptfoo eval harness
docs/jira-auto-triage.mdJira auto-triage agent
docs/closed-loop-remediation.mdAutomated SKILL.md fixes
docs/skill-marketplace.mdSkill management and sharing
docs/daemon-mode.mdBackground agent daemon
docs/provenance.mdAgent action provenance
docs/sigstore-verification.mdSupply chain verification

License

See LICENSE.

About

Secure container-based development environment with MCP gateway

Topics

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages