---
title: Configuration
description: CLI flags, environment variables, TOML config file, operations level, health checks, and snapshots.
category: reference
tags: [configuration, environment, toml, operations-level]
---

import ConfigParam from '@/components/ConfigParam.astro'

# Configuration

Cetacean can be configured through CLI flags, environment variables, or a TOML config file. When the same setting is
specified in multiple places, the precedence order is:<br/>
**flag > env var > config file > default**.

Sensitive settings (secrets, keys) also accept a `_FILE` suffix on their env var to read the secret from that file at
startup. The `_FILE` variant has lower precedence than the direct env var.

## General Settings

<ConfigParam name="server.listen_addr" flag="-listen" env="CETACEAN_LISTEN_ADDR" default=":9000">
  Address and port the HTTP server binds to. Use `0.0.0.0:9000` to listen on all interfaces, or `127.0.0.1:9000` to restrict to localhost.
</ConfigParam>

<ConfigParam name="server.base_path" flag="-base-path" env="CETACEAN_BASE_PATH">
  URL prefix for hosting Cetacean under a sub-path behind a reverse proxy (e.g., `/cetacean` serves the dashboard at `https://example.com/cetacean/`). Leave unset when Cetacean owns the root path.
</ConfigParam>

<ConfigParam name="docker.host" flag="-docker-host" env="CETACEAN_DOCKER_HOST" default="unix:///var/run/docker.sock">
  Docker Engine API endpoint. Supports Unix sockets (`unix:///path`), TCP (`tcp://host:port`), and SSH (`ssh://user@host`).
</ConfigParam>

<ConfigParam name="prometheus.url" flag="-prometheus-url" env="CETACEAN_PROMETHEUS_URL">
  Base URL of a Prometheus server (e.g., `http://prometheus:9090`). When set, Cetacean proxies metric queries and enables resource usage charts, sizing recommendations, and the metrics stream. When unset, all metric-dependent features are disabled.
</ConfigParam>

<ConfigParam name="logging.level" flag="-log-level" env="CETACEAN_LOG_LEVEL" default="info">
  Minimum log severity. One of `debug`, `info`, `warn`, or `error`.
</ConfigParam>

<ConfigParam name="logging.format" flag="-log-format" env="CETACEAN_LOG_FORMAT" default="json">
  Log output format. `json` produces structured, machine-readable lines. `text` produces human-friendly console output.
</ConfigParam>

<ConfigParam name="server.pprof" flag="-pprof" env="CETACEAN_PPROF" default="false">
  Expose Go runtime profiling endpoints at `/debug/pprof/`. Useful for diagnosing CPU, memory, and goroutine issues in production. Should be disabled unless actively profiling.
</ConfigParam>

<ConfigParam name="server.self_metrics" flag="-self-metrics" env="CETACEAN_SELF_METRICS" default="true">
  Expose a Prometheus-compatible metrics endpoint at `/-/metrics` with internal counters for SSE connections, cache operations, and HTTP request latency.
</ConfigParam>

<ConfigParam name="server.recommendations" flag="-recommendations" env="CETACEAN_RECOMMENDATIONS" default="true">
  Enable the recommendation engine, which periodically analyzes swarm state and Prometheus metrics to surface suggestions (resource sizing, missing health checks, operational issues). See [Recommendations](recommendations) for details.
</ConfigParam>

<ConfigParam name="server.operations_level" flag="-operations-level" env="CETACEAN_OPERATIONS_LEVEL" default="1">
  Controls which write operations the dashboard exposes. `0` is fully read-only, `1` allows operational actions (scale, restart, rollback), `2` adds service configuration edits, and `3` enables destructive operations like node removal. See [Operations Level](#operations-level) for the full breakdown.
</ConfigParam>

<ConfigParam name="server.sse.batch_interval" flag="-sse-batch-interval" env="CETACEAN_SSE_BATCH_INTERVAL" default="100ms">
  How long the SSE broadcaster waits to batch multiple change events into a single push. Lower values reduce UI update latency; higher values reduce network overhead when many resources change at once. Accepts any Go duration string (e.g., `50ms`, `1s`).
</ConfigParam>

<ConfigParam name="server.cors.origins" flag="-cors-origins" env="CETACEAN_CORS_ORIGINS">
  Origins allowed to make cross-origin requests to the API. Comma-separated list of origins (e.g., `https://admin.example.com`) or `*` to allow all. When unset, CORS headers are not sent and cross-origin requests from browsers are blocked.
</ConfigParam>

<ConfigParam name="server.trusted_proxies" flag="-trusted-proxies" env="CETACEAN_TRUSTED_PROXIES">
  IP addresses or [CIDR](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing) ranges of reverse proxies whose `X-Forwarded-For` headers should be trusted for determining the real client IP (e.g., `10.0.0.0/8,172.16.0.0/12`). Required for [header-based authentication](#trusted-proxy-headers). When unset, all requests are treated as direct connections.
</ConfigParam>

<ConfigParam name="storage.snapshot" flag="-snapshot" env="CETACEAN_SNAPSHOT" default="true">
  Persist swarm state to disk after every sync. On restart, Cetacean loads the snapshot to serve data immediately while the live sync catches up, avoiding a blank dashboard during startup.
</ConfigParam>

<ConfigParam name="storage.data_dir" flag="-data-dir" env="CETACEAN_DATA_DIR" default="./data">
  Directory where the snapshot file (`snapshot.json`) is stored. Must be writable by the Cetacean process. In Docker, mount this as a volume for persistence across container restarts.
</ConfigParam>

<ConfigParam name="tls.cert" flag="-tls-cert" env="CETACEAN_TLS_CERT">
  Path to the [PEM](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail)-encoded server certificate for TLS termination. Must be paired with `tls.key`. Required for [client certificate authentication](#client-certificates) (mTLS), optional otherwise.
</ConfigParam>

<ConfigParam name="tls.key" flag="-tls-key" env="CETACEAN_TLS_KEY">
  Path to the [PEM](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail)-encoded private key matching `tls.cert`.
</ConfigParam>

<ConfigParam name="config" flag="-config" env="CETACEAN_CONFIG">
  Path to an optional TOML configuration file. All settings in this file can also be set via flags or environment variables. See [Config File](#config-file) for the format.
</ConfigParam>

> **Note:** TLS cert and key must be set together or not at all. Required for `cert` auth mode (mTLS), optional
> otherwise.

## Authentication and Authorization Settings

<ConfigParam name="auth.mode" flag="-auth-mode" env="CETACEAN_AUTH_MODE" default="none">
  Authentication provider to use. One of `none` (anonymous access), [`oidc`](#oidc) (OpenID Connect), [`tailscale`](#tailscale) (Tailscale identity), [`cert`](#client-certificates) (mTLS client certificates), or [`headers`](#trusted-proxy-headers) (trusted reverse proxy headers). Only one mode can be active at a time. See [Authentication](authentication) for detailed guides.
</ConfigParam>

### OIDC

<ConfigParam name="auth.oidc.issuer" flag="-auth-oidc-issuer" env="CETACEAN_AUTH_OIDC_ISSUER" required>
  Base URL of the OpenID Connect identity provider (e.g., `https://accounts.google.com` or `https://keycloak.example.com/realms/myorg`). Must support [OIDC Discovery](https://openid.net/specs/openid-connect-discovery-1_0.html) at `/.well-known/openid-configuration`.
</ConfigParam>

<ConfigParam name="auth.oidc.client_id" flag="-auth-oidc-client-id" env="CETACEAN_AUTH_OIDC_CLIENT_ID" required>
  OAuth 2.0 client ID registered with the identity provider for Cetacean.
</ConfigParam>

<ConfigParam name="auth.oidc.client_secret" flag="-auth-oidc-client-secret" env="CETACEAN_AUTH_OIDC_CLIENT_SECRET" required>
  OAuth 2.0 client secret for the registered client. Use the `_FILE` suffix to read from a Docker secret or mounted file.
</ConfigParam>

<ConfigParam name="auth.oidc.redirect_url" flag="-auth-oidc-redirect-url" env="CETACEAN_AUTH_OIDC_REDIRECT_URL" required>
  URL the identity provider redirects to after authentication (e.g., `https://cetacean.example.com/auth/callback`). Must use HTTPS in production; `http://localhost` and `http://127.0.0.1` are allowed for local development.
</ConfigParam>

<ConfigParam name="auth.oidc.scopes" flag="-auth-oidc-scopes" env="CETACEAN_AUTH_OIDC_SCOPES" default="openid,profile,email">
  Comma-separated list of OAuth 2.0 scopes to request from the identity provider. The defaults provide user identity, display name, and email. Add provider-specific scopes here if you need additional claims (e.g., group membership).
</ConfigParam>

<ConfigParam name="auth.oidc.session_key" flag="-auth-oidc-session-key" env="CETACEAN_AUTH_OIDC_SESSION_KEY" default="random">
  Hex-encoded 32-byte [HMAC](https://en.wikipedia.org/wiki/HMAC) key used to sign browser session cookies. When unset, a random key is generated at startup — restarting the process invalidates all sessions. Set a fixed value for session persistence across restarts. Generate one with `openssl rand -hex 32`.
</ConfigParam>

### Tailscale

<ConfigParam name="auth.tailscale.mode" flag="-auth-tailscale-mode" env="CETACEAN_AUTH_TAILSCALE_MODE" default="local">
  How Cetacean connects to Tailscale. `local` queries the host's Tailscale daemon (requires Tailscale installed on the host). `tsnet` embeds a Tailscale node directly inside the process (no host-level Tailscale needed, ideal for containers). See [Authentication — Tailscale](authentication#choosing-a-mode) for a detailed comparison.
</ConfigParam>

<ConfigParam name="auth.tailscale.authkey" flag="-auth-tailscale-authkey" env="CETACEAN_AUTH_TAILSCALE_AUTHKEY">
  Tailscale auth key for automatic node enrollment. Only required in `tsnet` mode. Generate one in the Tailscale admin console under Settings → Keys. Use the `_FILE` suffix to read from a Docker secret.
</ConfigParam>

<ConfigParam name="auth.tailscale.hostname" flag="-auth-tailscale-hostname" env="CETACEAN_AUTH_TAILSCALE_HOSTNAME" default="cetacean">
  The hostname the embedded Tailscale node registers as on the tailnet (tsnet mode only). The dashboard will be accessible at `http://cetacean.<tailnet-name>.ts.net`.
</ConfigParam>

<ConfigParam name="auth.tailscale.state_dir" flag="-auth-tailscale-state-dir" env="CETACEAN_AUTH_TAILSCALE_STATE_DIR">
  Directory for persisting tsnet node state (keys, registration). Mount this as a volume in Docker to avoid re-enrolling the node on every restart.
</ConfigParam>

<ConfigParam name="auth.tailscale.capability" flag="-auth-tailscale-capability" env="CETACEAN_AUTH_TAILSCALE_CAPABILITY">
  Tailscale ACL capability key used to map tailnet users to application groups (e.g., `example.com/cap/cetacean`). When set, Cetacean reads group grants from Tailscale's CapMap and populates the identity's `groups` array for [authorization](authorization).
</ConfigParam>

### Client Certificates

<ConfigParam name="auth.cert.ca" flag="-auth-cert-ca" env="CETACEAN_AUTH_CERT_CA" required>
  Path to a PEM-encoded CA certificate bundle. Client certificates must be signed by one of the CAs in this bundle to be accepted. Supports certificate chains and multiple CAs in a single file.
</ConfigParam>

> **Note:** Requires `-tls-cert` and `-tls-key` to be set (mTLS needs TLS termination at Cetacean).

### Trusted Proxy Headers

<ConfigParam name="auth.headers.subject" flag="-auth-headers-subject" env="CETACEAN_AUTH_HEADERS_SUBJECT" required>
  Name of the HTTP header containing the authenticated user's unique identifier (e.g., `X-Remote-User`). This becomes the `subject` in the identity and is used for [authorization](authorization) audience matching.
</ConfigParam>

<ConfigParam name="auth.headers.name" flag="-auth-headers-name" env="CETACEAN_AUTH_HEADERS_NAME">
  Name of the HTTP header containing the user's display name (e.g., `X-Remote-Name`). Shown in the dashboard's user badge.
</ConfigParam>

<ConfigParam name="auth.headers.email" flag="-auth-headers-email" env="CETACEAN_AUTH_HEADERS_EMAIL">
  Name of the HTTP header containing the user's email address (e.g., `X-Remote-Email`). Used for [authorization](authorization) audience matching alongside the subject.
</ConfigParam>

<ConfigParam name="auth.headers.groups" flag="-auth-headers-groups" env="CETACEAN_AUTH_HEADERS_GROUPS">
  Name of the HTTP header containing the user's group memberships as a comma-separated list (e.g., `X-Remote-Groups`). Groups are used for [authorization](authorization) audience matching.
</ConfigParam>

<ConfigParam name="auth.headers.secret_header" flag="-auth-headers-secret-header" env="CETACEAN_AUTH_HEADERS_SECRET_HEADER">
  Name of an HTTP header that must carry a shared secret for the request to be accepted. Provides an additional layer of protection beyond IP-based `server.trusted_proxies` — the proxy must include this header with the correct value on every request.
</ConfigParam>

<ConfigParam name="auth.headers.secret_value" flag="-auth-headers-secret-value" env="CETACEAN_AUTH_HEADERS_SECRET_VALUE">
  The expected value of the shared secret header. Required when `auth.headers.secret_header` is set. Use the `_FILE` suffix to read from a Docker secret.
</ConfigParam>

<ConfigParam name="auth.headers.trusted_proxies" flag="-auth-headers-trusted-proxies" env="CETACEAN_AUTH_HEADERS_TRUSTED_PROXIES" deprecated>
  Use `server.trusted_proxies` instead. This setting will be removed in v1.
</ConfigParam>

> **Note:** `trusted_proxies` is always required. The shared secret is optional, additional protection.

See [Authentication](authentication.md) for detailed usage guides, flow diagrams, and deployment examples.

## Config File

Pass a TOML file via `-config` or `CETACEAN_CONFIG`. Every field is optional — omitting a key uses the default.

```bash
cetacean -config /etc/cetacean/config.toml
```

See [`config.reference.toml`](./config.reference.toml) for a complete reference with all options, defaults, and
descriptions. Copy it as a starting point and uncomment what you need.

## Subcommands

```
cetacean                  Start the server
cetacean healthcheck      Exit 0 if ready, 1 otherwise (for Docker HEALTHCHECK)
```

## Snapshots

Cetacean saves all cached swarm state to `${data_dir}/snapshot.json` after every sync. On startup, it loads the snapshot
to serve stale-but-fast data while the live sync catches up. Writes are crash-safe.

## Health Checks

Two meta endpoints, exempt from authentication and content negotiation:

| Endpoint        | Behavior                                        | Use for                             |
|-----------------|-------------------------------------------------|-------------------------------------|
| `GET /-/health` | Always 200 if the process is running            | Uptime monitoring, restart policies |
| `GET /-/ready`  | 200 after the first Docker sync; 503 until then | Load balancers, `depends_on` gating |

The binary includes a `cetacean healthcheck` subcommand (used by the built-in Docker `HEALTHCHECK`).

## Operations Level

The `operations_level` setting controls which write operations are available. The default is `1`. Requests above the
configured level receive `403 Forbidden`. Each level includes everything below it.

| Operation                                                         | 0 Read-only | 1 Operational | 2 Configuration | 3 Impactful |
|-------------------------------------------------------------------|:-----------:|:-------------:|:---------------:|:-----------:|
| Browse all resources                                              |      ✔      |       ✔       |        ✔        |      ✔      |
| Scale, restart, rollback, update image                            |      —      |       ✔       |        ✔        |      ✔      |
| Edit service definitions (env, resources, ports, placement, etc.) |      —      |       —       |        ✔        |      ✔      |
| Create/edit configs, secrets, plugins                             |      —      |       —       |        ✔        |      ✔      |
| Edit swarm settings (raft, orchestration, dispatcher)             |      —      |       —       |        ✔        |      ✔      |
| Delete resources, change node availability/role                   |      —      |       —       |        —        |      ✔      |
| Change service/endpoint mode, remove nodes/stacks                 |      —      |       —       |        —        |      ✔      |
| Manage CA, encryption, rotate tokens, unlock swarm                |      —      |       —       |        —        |      ✔      |

When combined with [ACL](authorization.md#interaction-with-operations-level), both checks must pass — operations level
is the global ceiling, ACL controls per-user scope.

## Profiling

When `pprof` is enabled, standard Go profiling endpoints are available at `/debug/pprof/`:

```bash
go tool pprof http://localhost:9000/debug/pprof/profile   # 30s CPU profile
go tool pprof http://localhost:9000/debug/pprof/heap       # heap snapshot
```
