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

# Networking & routing

> Control container egress with named networks and expose ports and paths through the shim.

By default a container has **no network access** — it cannot reach the internet or other containers. The exception is the container the [shim routes to](#routing): the enclave wires the shim to it automatically, with no configuration on your part.

You only need a `networks` block when a container has to make **outbound** connections (calling an external API) or talk to **another container** in the same enclave.

<Note>
  The `networks` block requires `cvm-version` 0.10.0 or newer.
</Note>

## Defining networks

`networks` is a top-level map of named networks. Each has an `egress` policy that controls what containers attached to it can reach:

| `egress`           | Meaning                                                                                                                                                                  |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `closed` (default) | No outbound access. Containers on the same `closed` network can talk to each other, but not to the internet. Use this for internal container-to-container communication. |
| `allowlist`        | Outbound allowed only to the hostnames in `allow`. Everything else is blocked.                                                                                           |
| `open`             | Outbound allowed to any public address. Private/internal ranges (RFC 1918, link-local, loopback) are always blocked.                                                     |

```yaml theme={"dark"}
networks:
  backend:
    egress: allowlist
    allow:
      - api.stripe.com
      - api.openai.com

  public:
    egress: open

  internal: {}              # empty body = egress: closed
```

| Field                    | Type   | Description                                                                     |
| ------------------------ | ------ | ------------------------------------------------------------------------------- |
| `networks.<name>.egress` | string | One of `closed`, `allowlist`, `open`. Defaults to `closed`.                     |
| `networks.<name>.allow`  | list   | Hostnames allowed for `egress: allowlist`. Only valid when `egress: allowlist`. |

Rules for `allow` entries:

* Must be **hostnames** (e.g. `api.example.com`), not IP addresses; wildcards are not supported.
* Allow every hostname the request may contact, including redirect targets and separate CDN or API hostnames.
* Hostnames are re-resolved periodically (about every 60 seconds), so allowlisting works with rotating DNS. Only IPv4 addresses are allowlisted today.

Network names must be lowercase alphanumeric with hyphens, at most 15 characters. The name `shim-net` is reserved for the enclave's internal shim-to-container channel and cannot be used (see [Routing](#routing)).

## Attaching containers to networks

List the networks a container joins under its `networks` field:

```yaml theme={"dark"}
networks:
  backend:
    egress: allowlist
    allow: [api.stripe.com]
  internal: {}

containers:
  - name: api
    image: ghcr.io/myorg/api@sha256:...
    networks: [backend, internal]   # egress via backend; talk to peers on internal

  - name: worker
    image: ghcr.io/myorg/worker@sha256:...
    networks: [internal]            # no egress; can reach `api` over internal
```

* A container may attach to any number of networks, but **at most one** may have `egress` other than `closed`.
* Containers on a shared network reach each other by container name (e.g. `http://api:8000`).
* A container with no `networks` (and that isn't the shim's target) has no connectivity.

## Routing

The `shim` section controls which ports and paths your container exposes.

| Field                     | Type    | Required | Description                                                                                   |
| ------------------------- | ------- | -------- | --------------------------------------------------------------------------------------------- |
| `shim.upstream-port`      | integer | Yes      | Port your container listens on                                                                |
| `shim.paths`              | list    | Yes      | URL paths to expose (supports `*` wildcards)                                                  |
| `shim.upstream-container` | string  | No       | Which container receives traffic. Defaults to the first container in `containers`.            |
| `shim.origins`            | list    | No       | Allowed CORS origins for browser clients. When set, requests from other origins are rejected. |

Only listed paths are reachable from outside the enclave. Any request to an unlisted path is rejected with a 404 error code. The enclave reaches the target container over a private internal channel — you don't declare a network for it.

<Note>
  **The `shim-net` channel.** The shim reaches your upstream container over an automatic, private Docker bridge named `shim-net` (a fixed `172.31.255.0/30` subnet). It carries only shim → container traffic and is always closed to the internet. You don't create it, and the name `shim-net` is reserved — you can't declare a network called `shim-net` or attach a container to it yourself.
</Note>
