# Security

How OpenBerth isolates and protects your server.

OpenBerth assumes all deployed code is potentially hostile and sandboxes everything:

## Container isolation

- **gVisor (runsc)** — every container runs under gVisor, a user-space kernel that intercepts system calls. Even if code exploits a vulnerability, it can’t reach the host.
- **All capabilities dropped** — containers have no Linux capabilities (no `CAP_NET_RAW`, no `CAP_SYS_ADMIN`, nothing).
- **No host access** — containers can’t see host filesystems, processes, or network interfaces.
- **Localhost-only ports** — containers bind to `127.0.0.1:port`. Caddy handles all external traffic and TLS termination.

## Resource limits

| Resource | Default Limit |
| --- | --- |
| Memory | 512 MB (runtime), 1 GB (sandbox) |
| CPU | 0.5 cores |
| PIDs | 256 processes |
| Disk | Configurable via `diskSize` |
| Network transfer | Configurable via `networkQuota` (Caddy access log based) |

## TLS modes

OpenBerth supports three TLS modes, set at install time:

| Mode | Install flag | Behavior |
| --- | --- | --- |
| Direct (default) | — | Caddy auto-provisions Let’s Encrypt certificates via ACME. URLs are `https://`. |
| Cloudflare | `--cloudflare` | Caddy uses self-signed internal certs. Cloudflare handles public TLS at the edge (SSL mode “Full”). URLs are `https://`. |
| Insecure | `--insecure` | Caddy serves plain HTTP only. No certificates. URLs are `http://`. For local networks and testing. |

No manual certificate management needed in any mode.

## Hard delete

Destroying a deployment removes _everything_ — the database record, source code, Docker volumes, persistent data, and Caddy proxy config. Nothing is left behind.

## Two-phase deployment

- **Build phase** — unconstrained memory, gVisor sandboxed, produces artifacts in a Docker volume
- **Runtime phase** — tight resource limits (512 MB, 0.5 CPU default), gVisor sandboxed, serves the pre-built output

## Blue-green updates

When you update a deployment, a new volume is created and the build runs while the old container continues serving. On success, traffic swaps to the new container. On failure, the old container stays running (automatic rollback).
