Configuration Reference
Configuration file location: ~/.config/jailoc/config.toml
The file is auto-created with defaults on first run. All fields are optional unless noted.
Top-level fields
Fields set at the root level of config.toml, outside any TOML table.
| Field | Type | Default | Description |
|---|---|---|---|
password_mode |
string | "auto" |
Password storage mode. Accepted values: "auto" (env var override → OS keyring → password file), "env" (env var only — error if unset), "keyring" (OS keyring only — error if unavailable), "file" (file only, skips keyring). |
jailoc auto-generates a 64-character hex password on first run and stores it in the OS keyring (preferred) with a fallback file at ~/.local/share/jailoc/{workspace}/password. When the keyring is used, a marker file is written instead of the actual password. If the keyring becomes unavailable later, jailoc reports an error with the marker file path — delete it to generate a new file-based password. jailoc status shows the source label (env, keyring, or file).
Example
password_mode = "auto"
[base]
Global base image settings. Controls the fallback image used when no workspace-level image is set.
| Field | Type | Default | Description |
|---|---|---|---|
dockerfile |
string | (none) | Local path (/..., ~/...) or HTTP(S) URL to a Dockerfile for the base image. When set, takes priority over the embedded fallback. Build failure is fatal. Maximum file size for HTTP sources: 1 MiB. Supports ~ expansion for local paths. |
Example
[base]
dockerfile = "https://example.com/Dockerfiles/custom"
Or with a local Dockerfile:
[base]
dockerfile = "/opt/myorg/base.Dockerfile"
[defaults]
Global defaults applied to all workspaces. All fields are optional and default to empty.
| Field | Type | Default | Description |
|---|---|---|---|
image |
string | (none) | Pre-built Docker image used as the base for workspace Dockerfile builds, or pulled directly when no workspace dockerfile is set. |
env |
string[] | [] |
Environment variables applied to all workspaces. Each entry must be in KEY=VALUE format. Workspace env entries take precedence over defaults with the same key. |
env_file |
string[] | [] |
Paths to .env files loaded for all workspaces. Each file must exist at config load time. Paths must be absolute (/...) or start with ~. Parsed before workspace-level env_file entries. |
mounts |
string[] | [] |
Additional bind mounts for all workspaces. Each entry follows host:container[:mode] format where mode is ro or rw (default rw). An empty host source removes a default mount matching the container path. Merged with per-workspace mounts — see Merge Semantics below. Supports ~ expansion on both host and container sides. |
allowed_hosts |
string[] | [] |
Hostnames allowed through the firewall for all workspaces. Merged with per-workspace allowed_hosts. |
allowed_networks |
string[] | [] |
CIDR ranges allowed through the firewall for all workspaces. Merged with per-workspace allowed_networks. |
ssh_auth_sock |
bool | false |
Mount the host SSH agent socket into the container. Auto-detects the socket: Docker Desktop/OrbStack magic path first, then $SSH_AUTH_SOCK. Also mounts ~/.ssh/known_hosts read-only when enabled. |
git_config |
bool | true |
Mount the host Git configuration (~/.gitconfig or ~/.config/git/config) read-only into the container. |
cpu |
float64 | 2.0 |
Number of CPU cores allocated to the opencode container. Must be greater than 0. |
memory |
string | "4g" |
Memory limit for the opencode container. Accepts Docker memory format: a positive integer optionally followed by k, m, or g suffix (e.g. 512m, 4g, 1024). Must be greater than 0. |
Example
[defaults]
image = "myregistry.example.com/myteam/opencode-base:v1.2.3"
env = ["GOPRIVATE=*.example.com", "NPM_REGISTRY=https://npm.example.com"]
env_file = ["~/.config/jailoc/shared.env"]
mounts = ["~/.local/share/opencode:/home/agent/.local/share/opencode"]
allowed_hosts = ["internal-registry.example.com"]
allowed_networks = ["10.0.0.0/8"]
ssh_auth_sock = true
git_config = true
cpu = 4.0
memory = "8g"
[workspaces.<name>]
Each workspace is declared as a TOML table under [workspaces], keyed by name.
Workspace name constraints: must match ^[a-z0-9-]+$ (lowercase letters, digits, and hyphens only).
| Field | Type | Default | Description |
|---|---|---|---|
paths |
string[] | (required) | Directories bind-mounted into the container at their original absolute paths. The first path becomes the container's working directory. Supports ~ expansion. |
mounts |
string[] | [] |
Bind mounts for this workspace. Format: host:container[:mode] — mode is ro or rw (default rw). An empty host source (e.g. ":/home/agent/.opencode:ro") removes a default mount matching the container path. Container destinations under /home/agent/... are allowed (unlike paths); see mounts validation for the full list of forbidden container prefixes. |
allowed_hosts |
string[] | [] |
Hostnames resolved at container start and added as iptables ACCEPT rules before the private-range DROP rules. |
allowed_networks |
string[] | [] |
CIDR ranges explicitly allowed through the container firewall. |
image |
string | (none) | Pre-built Docker image to use directly for this workspace, bypassing all build steps. Compose pulls the image natively at startup. Cannot be combined with dockerfile or build_context. |
build_context |
string | (none) | Docker build context directory for the workspace overlay build. When empty and dockerfile is a local path, defaults to the parent directory of the Dockerfile. When empty and dockerfile is an HTTP URL, a temporary directory is used. Supports ~ expansion. |
mode |
string | "" |
Connection mode for jailoc. Accepted values: "remote", "exec", "" (auto-detect). |
dockerfile |
string | (none) | Local path (/..., ~/...) or HTTP(S) URL to a Dockerfile for a workspace-specific overlay image. Builds on top of the base image resolved by [base] settings. Build failure is fatal. Maximum file size for HTTP sources: 1 MiB. Supports ~ expansion for local paths. |
env |
string[] | [] |
Environment variables for this workspace. Each entry in KEY=VALUE format. These override any global defaults.env entry with the same key. Reserved keys are rejected (see Validation Rules). |
env_file |
string[] | [] |
Paths to .env files for this workspace. Each file must exist at config load time. Paths must be absolute (/...) or start with ~. Loaded after global defaults.env_file entries. |
ssh_auth_sock |
bool | (inherit) | Mount the host SSH agent socket into the container. When not set, inherits from [defaults]. Also mounts ~/.ssh/known_hosts read-only when enabled. |
git_config |
bool | (inherit) | Mount the host Git configuration read-only into the container. When not set, inherits from [defaults]. Falls back to true when neither the workspace nor defaults set it. |
cpu |
float64 | (inherit) | Number of CPU cores allocated to the opencode container. When not set, inherits from [defaults]. Falls back to 2.0 when neither the workspace nor defaults set it. |
memory |
string | (inherit) | Memory limit for the opencode container. When not set, inherits from [defaults]. Falls back to "4g" when neither the workspace nor defaults set it. |
Note
image is mutually exclusive with dockerfile and build_context. Setting image alongside either of those fields is a validation error.
Example
[workspaces.my-project]
paths = ["~/projects/my-project", "~/shared/libs"]
allowed_hosts = ["api.example.com", "pypi.org"]
allowed_networks = ["10.0.0.0/8"]
mounts = ["~/.local/share/opencode:/home/agent/.local/share/opencode"]
build_context = "~/projects/my-project/docker"
mode = "remote"
dockerfile = "~/projects/my-project/overlay.Dockerfile"
Validation Rules
Workspace names
Must match the regular expression ^[a-z0-9-]+$. Names containing uppercase letters, underscores, or other special characters are rejected.
paths
Each entry is validated against a list of forbidden path prefixes. Paths starting with any of the following are rejected:
| Forbidden prefix |
|---|
/home/agent |
/usr |
/etc |
/var |
/bin |
/sbin |
/lib |
/lib64 |
~ is expanded to $HOME before validation. HTTP(S) URLs in dockerfile fields are not subject to ~ expansion; local paths starting with ~ are expanded.
mounts
Each entry uses the format host:container[:mode].
host: a local path (absolute or starting with~). An empty string signals removal of a default mount matching the container path.container: must be an absolute path after~expansion. Validated against a separate set of forbidden prefixes:/usr,/etc,/var,/bin,/sbin,/lib,/lib64,/opt,/root,/proc,/sys,/dev,/run,/tmp,/certs. Unlikepaths, destinations under/home/agent/...are allowed.mode:roorrw. Defaults torwwhen omitted.
The following host paths are forbidden:
| Forbidden host path |
|---|
/ |
/boot |
/dev |
/etc |
/private |
/proc |
/sys |
/run |
/var |
~/.ssh |
~/.gnupg |
~/.aws |
Any host path equal to or starting with these prefixes is rejected.
allowed_networks
Each entry must be a valid CIDR notation string as accepted by Go's net.ParseCIDR. Invalid CIDR values are rejected at config load time.
Workspace image
The workspace image field is mutually exclusive with dockerfile and build_context. The following combinations are rejected at config load time:
imageset together withdockerfileimageset together withbuild_context
cpu
Must be a positive number (greater than 0). Applies to both [defaults] and workspace sections. Zero and negative values are rejected at config load time.
memory
Must match the regular expression ^[1-9][0-9]*[kmgKMG]?$ — a positive integer optionally followed by a k, m, or g suffix (case-insensitive). Examples: 512m, 4g, 1024. Values like 0, 0m, or empty strings are rejected at config load time.
dockerfile fields
Accepted values:
- Absolute local paths: must start with
/(e.g./opt/my.Dockerfile) - Tilde paths: must start with
~(e.g.~/my.Dockerfile);~is expanded to$HOMEbefore use - HTTP(S) URLs: must have an
httporhttpsscheme and a non-empty host component. Paths likehttp:///pathare rejected.
Relative paths and other URL schemes (e.g. ftp://, file://) are not accepted.
env
Each entry must be in KEY=VALUE format (key cannot be empty, must contain =). The following keys are reserved and cannot be set by users:
| Reserved key | Reason |
|---|---|
OPENCODE_LOG |
opencode runtime config |
OPENCODE_SERVER_PASSWORD |
managed automatically by jailoc; set to override the automatic password cascade |
DOCKER_HOST |
DinD TLS connection |
DOCKER_TLS_CERTDIR |
DinD TLS certs |
DOCKER_CERT_PATH |
DinD TLS certs |
DOCKER_TLS_VERIFY |
DinD TLS verification |
SSH_AUTH_SOCK |
SSH agent passthrough |
env_file
Each path must be absolute (starting with /) or start with ~ (expanded to $HOME). Files must exist at config load time. The file format is Docker .env compatible:
- Lines in
KEY=VALUEformat - Lines starting with
#are comments - Empty lines are ignored
- Values may be quoted (
KEY="value with spaces") - Inline comments after values are stripped
Values are treated as literal strings — no host environment variable expansion is performed.
Merge semantics
Environment variables from multiple sources are merged in this order (later entries win for the same key):
[defaults].env— global inline values[defaults].env_file— global file values (in list order)- Workspace
env_file— per-workspace file values (in list order) - Workspace
env— per-workspace inline values (highest priority)
allowed_hosts and allowed_networks use union deduplication: the global list is merged with the workspace list, with duplicates removed, preserving order.
mounts follows a three-layer merge keyed by container path. Default mounts (built into jailoc) are applied first, then [defaults].mounts, then per-workspace mounts. For each container path, the last layer to set it wins. An entry with an empty host source removes the mount for that container path. The built-in default mounts are:
| Container path | Host source | Mode |
|---|---|---|
/home/agent/.config/opencode |
~/.config/opencode |
ro |
/home/agent/.opencode |
~/.opencode |
ro |
/home/agent/.claude/transcripts |
~/.claude/transcripts |
rw |
/home/agent/.agents |
~/.agents |
ro |
ssh_auth_sock and git_config inherit from [defaults] when not set in the workspace. When set explicitly in a workspace, the workspace value takes precedence. git_config falls back to true when neither the workspace nor defaults set it.
cpu and memory inherit from [defaults] when not set in the workspace. When set explicitly in a workspace, the workspace value takes precedence. cpu falls back to 2.0 and memory falls back to "4g" when neither the workspace nor defaults set them.
Port Allocation
Each workspace is assigned a fixed host port based on the alphabetical sort order of all configured workspace names:
port = 4096 + index
Where index is the zero-based position of the workspace name when all workspace names are sorted alphabetically.
| Example workspaces (sorted) | Assigned port |
|---|---|
alpha (index 0) |
4096 |
beta (index 1) |
4097 |
gamma (index 2) |
4098 |
Port assignments shift when workspace names are added or removed. Run jailoc status to see current assignments.
See the workspace configuration how-to for step-by-step setup instructions.