Skip to main content

Configuration

Greywall reads settings from ~/.config/greywall/greywall.json by default (or ~/Library/Application Support/greywall/greywall.json on macOS). Legacy ~/.greywall.json is also supported. Pass --settings ./greywall.json to use a custom path. Config files support JSONC.

Example config:

{
"network": {
"proxyUrl": "socks5://localhost:43052",
"dnsAddr": "localhost:43053"
},
"filesystem": {
"denyRead": ["/etc/passwd"],
"allowWrite": [".", "/tmp"],
"denyWrite": [".git/hooks"]
},
"command": {
"deny": ["git push", "npm publish"]
},
"ssh": {
"allowedHosts": ["*.example.com"],
"allowedCommands": ["ls", "cat", "grep", "tail", "head"]
}
}

Config Inheritance​

You can extend built-in templates or other config files using the extends field. This reduces boilerplate by inheriting settings from a base and only specifying your overrides.

Extending a template​

{
"extends": "code",
"filesystem": {
"allowWrite": [".", "/tmp"]
}
}

This config:

  • Inherits all settings from the code template (filesystem protections, command restrictions)
  • Adds custom writable paths

Extending a file​

You can also extend other config files using absolute or relative paths:

{
"extends": "./base-config.json",
"command": {
"deny": ["git push"]
}
}
{
"extends": "/etc/greywall/company-base.json",
"filesystem": {
"denyRead": ["~/company-secrets/**"]
}
}

Relative paths are resolved relative to the config file's directory. The extended file is validated before merging.

Detection​

The extends value is treated as a file path if it contains / or \, or starts with .. Otherwise it's treated as a template name.

Merge behavior​

  • Slice fields (paths, commands) are appended and deduplicated
  • Boolean fields use OR logic (true if either base or override enables it)
  • Integer fields (ports) use override-wins semantics (0 keeps base value)

Chaining​

Extends chains are supported—a file can extend a template, and another file can extend that file. Circular extends are detected and rejected. Maximum chain depth is 10.

See templates.md for available templates.

Network Configuration​

Greywall routes all network traffic through an external SOCKS5 proxy. Domain filtering and access control are handled by the proxy (e.g., GreyProxy), not by greywall itself.

FieldDescription
proxyUrlExternal SOCKS5 proxy URL (default: socks5://localhost:43052)
dnsAddrHost-side DNS server address (default: localhost:43053)
allowUnixSocketsList of allowed Unix socket paths (macOS)
allowAllUnixSocketsAllow all Unix sockets
allowLocalBindingAllow binding to local ports
allowLocalOutboundAllow outbound connections to host localhost, e.g., local DBs. Defaults to allowLocalBinding if not set. macOS only; on Linux, use forwardPorts to reach specific host ports.
forwardPortsHost localhost ports to forward into the sandbox (Linux only; array of integers). Equivalent to repeated -f/--forward flags.
httpProxyUrlHTTP CONNECT proxy URL (default: http://localhost:43051)

Filesystem Configuration​

FieldDescription
defaultDenyReadDeny reads by default, allowing only system paths, CWD, and allowRead entries (default: true when not set)
allowReadPaths to allow reading (used when defaultDenyRead is enabled)
denyReadPaths to deny reading (overrides allowRead)
allowWritePaths to allow writing
denyWritePaths to deny writing (takes precedence over allowWrite)
allowGitConfigAllow writes to .git/config files

To opt out of deny-by-default reads, set "defaultDenyRead": false. Use --learning mode to automatically discover which paths a command needs. See Learning Mode.

Command Configuration​

Block specific commands from being executed, even within command chains.

FieldDescription
denyList of command prefixes to block (e.g., ["git push", "rm -rf"])
allowList of command prefixes to allow, overriding deny
useDefaultsEnable default deny list of dangerous system commands (default: true)

Example:

{
"command": {
"deny": ["git push", "npm publish"],
"allow": ["git push origin docs"]
}
}

Default Denied Commands​

When useDefaults is true (the default), greywall blocks these dangerous commands:

  • System control: shutdown, reboot, halt, poweroff, init 0/6
  • Kernel manipulation: insmod, rmmod, modprobe, kexec
  • Disk operations: mkfs*, fdisk, parted, dd if=
  • Container escape: docker run -v /:/, docker run --privileged
  • Namespace escape: chroot, unshare, nsenter

To disable defaults: "useDefaults": false

Command Detection​

Greywall detects blocked commands in:

  • Direct commands: git push origin main
  • Command chains: ls && git push or ls; git push
  • Pipelines: echo test | git push
  • Shell invocations: bash -c "git push" or sh -lc "ls && git push"

SSH Configuration​

Control which SSH commands are allowed. By default, SSH uses allowlist mode for security - only explicitly allowed hosts and commands can be used.

FieldDescription
allowedHostsHost patterns to allow SSH connections to (supports wildcards like *.example.com, prod-*)
deniedHostsHost patterns to deny SSH connections to (checked before allowed)
allowedCommandsCommands allowed over SSH (allowlist mode)
deniedCommandsCommands denied over SSH (checked before allowed)
allowAllCommandsIf true, use denylist mode instead of allowlist (allow all commands except denied)
inheritDenyIf true, also apply global command.deny rules to SSH commands

Basic Example (Allowlist Mode)​

{
"ssh": {
"allowedHosts": ["*.example.com"],
"allowedCommands": ["ls", "cat", "grep", "tail", "head", "find"]
}
}

This allows:

  • SSH to any *.example.com host
  • Only the listed commands (and their arguments)
  • Interactive sessions (no remote command)

Denylist Mode Example​

{
"ssh": {
"allowedHosts": ["dev-*.example.com"],
"allowAllCommands": true,
"deniedCommands": ["rm -rf", "shutdown", "chmod"]
}
}

This allows:

  • SSH to any dev-*.example.com host
  • Any command except the denied ones

Inheriting Global Denies​

{
"command": {
"deny": ["shutdown", "reboot", "rm -rf /"]
},
"ssh": {
"allowedHosts": ["*.example.com"],
"allowAllCommands": true,
"inheritDeny": true
}
}

With inheritDeny: true, SSH commands also check against:

  • Global command.deny list
  • Default denied commands (if command.useDefaults is true)

Host Pattern Matching​

SSH host patterns support wildcards anywhere:

PatternMatches
server1.example.comExact match only
*.example.comAny subdomain of example.com
prod-*Any hostname starting with prod-
prod-*.us-east.*Multiple wildcards
*All hosts

Evaluation Order​

  1. Check if host matches deniedHosts → DENY
  2. Check if host matches allowedHosts → continue (else DENY)
  3. If no remote command (interactive session) → ALLOW
  4. Check if command matches deniedCommands → DENY
  5. If inheritDeny, check global command.deny → DENY
  6. If allowAllCommands → ALLOW
  7. Check if command matches allowedCommands → ALLOW
  8. Default → DENY

Credential Protection​

Greywall can keep API keys and secrets out of sandboxed processes by replacing them with opaque placeholders and letting greyproxy substitute the real values at the HTTP layer. See Credential Protection for the full walkthrough.

FieldDescription
credentials.secretsAdditional environment variables to treat as credentials, beyond the auto-detected list. Equivalent to repeated --secret flags.
credentials.injectLabels of credentials stored in the greyproxy dashboard to inject into the sandbox as environment variables. Equivalent to repeated --inject flags.
credentials.ignoreEnvironment variables to exclude from credential detection even if they match the auto-detection heuristics. Equivalent to repeated --ignore-secret flags.

Example:

{
"credentials": {
"secrets": ["LITELLM_NOTRACK_API_KEY"],
"inject": ["ANTHROPIC_API_KEY", "OPENAI_API_KEY"],
"ignore": ["PUBLIC_API_TOKEN"]
}
}

Other Options​

FieldDescription
allowPtyAllow pseudo-terminal (PTY) allocation in the sandbox (macOS)
allowAudioExpose PulseAudio and PipeWire sockets inside the sandbox so commands can produce audio output (Linux only; disabled by default). Note that these sockets also permit microphone capture and, via PipeWire, camera and screen access.

See Also​