# Proxy Settings

**Page:** foundation/proxy/settings

[Download Raw Markdown](./foundation/proxy/settings.md)

---

# Proxy Settings

**Proxy Settings control two container-wide knobs: is the proxy on, and what is the default policy when no rule matches.** They live in a small, dedicated document with ETag concurrency — independent of the permissions matrix, hooks, and aliases.

```json title="GET /api/v1/containers/{id}/proxy/settings → data"
{
  "enable_proxy": true,
  "default": "allow",
  "file_version": 3,
  "etag": "file:v3"
}
```

- **`enable_proxy`** — boolean. When `false`, the proxy refuses to route any traffic for this container regardless of what's in the permissions document. Useful as a global kill-switch.
- **`default`** — `"allow"` or `"deny"`. The fallback decision when no group in the permissions document matches the incoming request.


The permissions document is the large, frequently-edited policy file (groups, per-program access, hooks). Settings is the small, rarely-edited switch. Splitting them means you can flip `enable_proxy` without re-sending (and re-validating) a multi-kilobyte permissions JSON. Each document has its own ETag.


---

## API surface

| Verb | Path | What it does |
|---|---|---|
| `GET` | `/api/v1/containers/{id}/proxy/settings` | Return current `enable_proxy` + `default` + ETag |
| `PUT` | `/api/v1/containers/{id}/proxy/settings` | Update one or both fields. Requires `If-Match: file:v`. |

The `PUT` body accepts either field independently — you can flip `enable_proxy` without touching `default` or vice versa.

### Via the Hoody CLI

```bash
# Read current settings
hoody containers proxy settings get <container-id>

# Enable the proxy (pass --enable-proxy as a boolean flag; no value)
hoody containers proxy settings update <container-id> \
    --enable-proxy \
    --if-match file:v3

# Change the default policy to deny-by-default
hoody containers proxy settings update <container-id> \
    --default deny \
    --if-match file:v4
```

### Via the SDK (TypeScript)

```ts
const current = await client.api.proxyDiscovery.getContainerProxySettings(containerId);
// current.data: { enable_proxy: true, default: 'allow', file_version: 3, etag: 'file:v3' }

await client.api.proxyDiscovery.updateContainerProxySettings(
  containerId,
  { enable_proxy: false },
  { ifMatch: current.data.etag },
);
```


Mutating calls **require** an `If-Match: file:v` header matching the most recent `file_version`. If the version has moved since your last read, the server returns `412 Precondition Failed` with `message: etag_mismatch` — re-read, re-apply your change, and retry. This mirrors the concurrency contract used by [permissions](/foundation/proxy/permissions/) and [hooks](/foundation/proxy/hooks/).


---

## When to use Settings vs. Permissions

| Task | Document |
|---|---|
| Turn the whole proxy off for a container | **Settings** — `enable_proxy: false` |
| Set the catch-all allow/deny when no group matches | **Settings** — `default` |
| Define who (IP, JWT, password, token) can call what program | [Permissions](/foundation/proxy/permissions/) |
| Attach MITM scripts to matching traffic | [Hooks](/foundation/proxy/hooks/) |
| Expose a container on a custom subdomain | [Aliases](/foundation/proxy/aliases/) |

---

## Scope

Proxy Settings are **container-level only**. There is no project-level `settings` endpoint; the per-container `enable_proxy` / `default` is the authoritative source for a given container. Project-level default policy can be set via the project's [proxy permissions](/foundation/proxy/permissions/) document.

---

## Further reading

- [Proxy Permissions](/foundation/proxy/permissions/) — the larger document that lists groups and per-program access.
- [Proxy Hooks](/foundation/proxy/hooks/) — attaching MITM scripts that run inside your own `hoody-exec`.
- [Hoody Proxy overview](/foundation/proxy/) — how Settings, Permissions, Hooks, and Aliases fit together.