> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tinfoil.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Runtime & security

> Security defaults applied to every container, plus healthchecks and restart policies that govern the container lifecycle.

## 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.                                                                 |

<Note>
  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`.
</Note>

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](/containers/models), 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.

```yaml theme={"dark"}
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.

<Tip>
  `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.
</Tip>

**See also.** The schema is taken from Docker Compose — see the [Compose healthcheck reference](https://docs.docker.com/reference/compose-file/services/#healthcheck) 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.

```yaml theme={"dark"}
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](https://docs.docker.com/reference/compose-file/services/#restart).
