Network and security

VNET layout

Jail sandboxes attach to coppicenet0 with a per-sandbox epair pair. IPv4 lives under 10.78.0.0/24; IPv6 uses the fd77::/64 ULA. The gateway records both addresses on the sandbox detail response.

Each sandbox gets a source-IP-scoped pf anchor. Policy updates do not reload the root ruleset; they mutate the sandbox anchor.

Air-gap

Air-gap mode installs a default-deny fragment for outbound traffic while keeping gateway/DNS control-plane paths reachable. New connections fail after air-gap is enabled. Existing pf states need to be killed when the operator wants an immediate cut; the gateway does that on policy flips.

API keys

By default, a tunnelled local deployment has no API auth. Set COPPICE_API_KEYS or COPPICE_API_KEYS_FILE to require credentials on the API and envd surfaces:

export COPPICE_API_KEYS='team-a:sk-team-a:admin|exec'

Send X-API-Key: sk-team-a or Authorization: Bearer sk-team-a. Use /auth/whoami to confirm which tenant/scopes the gateway matched. Scopes are coarse on purpose: read can inspect state, exec can operate sandbox/envd surfaces, and admin can mutate templates, pools, secrets, schedules, volumes, webhooks, limits, and network policy.

Authenticated creates are labelled with reserved coppice_tenant_id metadata. To cap concurrent running/paused sandboxes per tenant, set:

export COPPICE_TENANT_MAX_SANDBOXES=8
export COPPICE_TENANT_SANDBOX_LIMITS='team-a=2,team-b=10,*=4'

The specific map is optional; * is the fallback when present. Quota checks run before a backend clone starts, so a tenant at its cap gets a fast 403 instead of consuming pool capacity.

Mutating requests, auth failures, scope denials, and HTTP errors are kept in the in-memory audit ring:

curl /audit/events?limit=20

Set COPPICE_AUDIT_LOG=/var/log/coppice-audit.jsonl for a durable JSONL copy. The admin dashboard renders the same feed.

Secrets

Use the secrets store for env-var injection and the credential proxy for host-side request brokering. The first writes selected values into /run/coppice/secrets.env. The second keeps the real upstream credential on the host and gives the sandbox only a proxy token.

VNET wedge diagnostics

If a FreeBSD VNET attach wedges in the kernel, the gateway now captures a bundle under /var/log/coppice-diagnostics. The admin panel and API expose live status through:

curl /diagnostics/vnet
curl /diagnostics/vnet/latest

A reboot clears the D-state process; the retained bundle explains what happened before the reboot.