Security defaults
The enclave applies hardened defaults to every container, so the attested config honestly reflects what runs. These differ from stock Docker, so a container that relied on Docker’s permissive defaults may need adjustment.
| Behavior | Default | How to change it |
|---|
| All capabilities dropped | Containers start with zero Linux capabilities. | Add only what you need with cap_add. There is no cap_drop. |
| No new privileges | no-new-privileges:true is always set, blocking setuid-based privilege escalation. | Cannot be disabled. |
| Read-only root filesystem | read_only: true. | Set read_only: false, or mount writable scratch space with tmpfs / volumes. |
| Process limit | pids_limit: 65536, a backstop against fork bombs. | Set an explicit pids_limit (-1 for unlimited). |
| Attested config mount | /tinfoil is mounted read-only, exposing the verified config and attestation so clients can audit what’s running. | Not configurable. |
The most common migration surprises are the read-only root filesystem and dropped capabilities. If your app writes to its root filesystem, set read_only: false or add a tmpfs mount for its scratch directories. If it needs a capability (for example SYS_ADMIN for sandboxing, or NET_RAW for ping), list it under cap_add.
The read-only /tinfoil mount contains:
| Path | Contents |
|---|
/tinfoil/config.yml | The verified tinfoil-config.yml this enclave booted with |
/tinfoil/attestation.json | The enclave’s attestation document |
/tinfoil/container-status.json | Runtime status of the launched containers |
/tinfoil/mpk/mpk-<root_hash> | Mounted model weights, when models is set |
Healthchecks
Add a healthcheck block to a container to have the enclave verify it’s actually ready before the deployment transitions to Running. Without one, the container is considered ready the moment Docker starts it — fine for fast-starting apps, but a problem for workloads with long startup (model loading, cache warm-up) where the process is up but isn’t serving yet.
containers:
- name: "inference"
image: "vllm/vllm-openai:v0.14.1@sha256:..."
command: ["--port", "8001"]
healthcheck:
test: ["CMD", "curl", "-sf", "http://localhost:8001/health"]
interval: 30s
timeout: 5s
start_period: 30m
| Field | Type | Description |
|---|
test | list | Command to run inside the container. Prefix with CMD to exec directly, or CMD-SHELL to run through a shell. Exit code 0 = pass, non-zero = fail. |
interval | duration | How often to run the check (e.g. 30s). Docker default: 30s. |
timeout | duration | How long a single check can take before it’s counted as a failure (e.g. 5s). Docker default: 30s. |
retries | integer | Consecutive failures after start_period before the container is marked unhealthy. Docker default: 3. |
start_period | duration | Grace period after container start during which failures don’t count toward retries (e.g. 30m). Docker default: 0s. |
How it’s used during boot. The enclave’s boot process polls Docker’s health state every 5 seconds once the container starts and waits until Docker reports the container Healthy before finishing boot. If Docker reports Unhealthy (i.e. retries consecutive failures after start_period has elapsed), the deployment fails and the last healthcheck output is surfaced as the error detail.
The test command runs inside the container, so whatever you invoke (curl, wget, a language runtime) has to be available in the image. For an inference server like vLLM that already exposes /health, a curl -sf http://localhost:<port>/health check is idiomatic.
start_period is usually the most important field. If your container takes 15 minutes to load model weights, set start_period to at least 20 minutes — otherwise failing checks during the load phase will burn through retries and the deployment will fail before your app ever gets a chance to serve.
See also. The schema is taken from Docker Compose — see the Compose healthcheck reference for the full semantics (exit codes, CMD-SHELL vs CMD, disabling an inherited check with disable: true).
Restart policy
By default, a container whose process exits stays exited. Set restart to have Docker automatically restart the process if it crashes — useful for long-running servers that should stay up across transient failures.
containers:
- name: "inference"
image: "vllm/vllm-openai:v0.14.1@sha256:..."
restart: always
| Value | Behavior |
|---|
no | Don’t restart. This is the default when restart is omitted. |
always | Restart the container regardless of exit status. |
on-failure | Restart only if the process exits with a non-zero status. |
unless-stopped | Like always, but don’t restart if the container was stopped explicitly. |
Interaction with healthchecks. The restart policy fires when the container process exits — it has no effect when Docker marks the container Unhealthy (the process keeps running; only its health state changes). During boot, the enclave fails the deployment on Unhealthy regardless of restart. Once the container has been declared Healthy, restart governs what happens if the process later dies.
See also. Taken from Docker Compose — see the Compose restart reference.