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

# Security

> Harden your self-hosted Tracecat deployment: replace default infrastructure credentials, generate and store platform secrets, sandbox executor code, and set up SSO and TLS.

## Infrastructure credentials

The default configuration ships with weak, well-known passwords for PostgreSQL, MinIO, and Redis. Replace them with strong, unique values before exposing Tracecat to production traffic.

```bash theme={null}
# PostgreSQL
TRACECAT__POSTGRES_USER=tracecat
TRACECAT__POSTGRES_PASSWORD=<strong random password>

# Temporal PostgreSQL
TEMPORAL__POSTGRES_USER=temporal
TEMPORAL__POSTGRES_PASSWORD=<strong random password>

# MinIO / S3
MINIO_ROOT_USER=<strong random user>
MINIO_ROOT_PASSWORD=<strong random password>

# Redis — add a password and update the URL
REDIS_URL=redis://:<strong random password>@redis:6379
```

For Redis, also pass the password to the container. Add a `command` override in your `docker-compose.yml`:

```yaml theme={null}
services:
  redis:
    command: ["redis-server", "--requirepass", "<same password as above>"]
```

In production, prefer managed services (e.g., Amazon RDS, ElastiCache) over self-hosted PostgreSQL and Redis: they handle encryption at rest, automated backups, and credential rotation.

## Platform secrets

Tracecat requires four cryptographic secrets, plus an optional keyring if you enable Temporal payload encryption.

| Secret                                 | Protects                                                                                                                                 |
| -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `TRACECAT__DB_ENCRYPTION_KEY`          | Fernet key for credentials and sensitive settings stored in PostgreSQL.                                                                  |
| `TRACECAT__SERVICE_KEY`                | Service-to-service JWT signing.                                                                                                          |
| `TRACECAT__SIGNING_SECRET`             | Webhook URL signing and HMAC operations.                                                                                                 |
| `USER_AUTH_SECRET`                     | Password reset tokens, email verification, OAuth state, the MCP OIDC issuer keypair, and the internal OIDC client secret.                |
| `TEMPORAL__PAYLOAD_ENCRYPTION_KEYRING` | Versioned keyring for Temporal payload encryption. Optional. Tracecat reads it only when `TEMPORAL__PAYLOAD_ENCRYPTION_ENABLED` is true. |

Tracecat requires four secrets. Generate them with `openssl`:

```bash theme={null}
# Service key (hex, 32 bytes) — used for internal service-to-service JWT signing
openssl rand -hex 32

# Signing secret (hex, 32 bytes) — used for webhook URL signing and HMAC operations
openssl rand -hex 32

# User auth secret (hex, 32 bytes) — used for password reset, email verification, OAuth state, and OIDC key derivation
openssl rand -hex 32

# DB encryption key (Fernet-compatible base64, 32 bytes) — used for encrypting secrets at rest
openssl rand 32 | base64 | tr -d '\n' | tr '+/' '-_'
```

<Warning>
  Store these securely. Losing `TRACECAT__DB_ENCRYPTION_KEY` makes encrypted credentials unrecoverable.
  Losing `TRACECAT__SIGNING_SECRET` invalidates existing webhook URLs and agent channel endpoint URLs.
</Warning>

See [Where to store them](/self-hosting/security#where-to-store-them) for the recommended storage on each deployment target, and which of these secrets can be rotated.

### Temporal payload keyring

`TEMPORAL__PAYLOAD_ENCRYPTION_KEYRING` holds a JSON keyring rather than a single key. Each entry maps a key ID to a root secret, and `current_key_id` selects the key that encrypts new payloads:

```json theme={null}
{"current_key_id": "v1", "keys": {"v1": "<root secret>"}}
```

Generate each root secret the same way as the other secrets:

```bash theme={null}
openssl rand -hex 32
```

Tracecat derives a separate AES-256-GCM key per workspace from the root secret, and stamps the key ID into every payload it encrypts. That stamp is what lets you rotate the keyring while older histories stay readable. On AWS, supply `TEMPORAL__PAYLOAD_ENCRYPTION_KEYRING_ARN` instead, and Tracecat fetches the keyring from Secrets Manager at runtime.

### Where to store them

Keep these out of your application configuration and out of version control. Use the mechanism your platform already provides.

| Deployment                                                | Recommended storage                                                                                                                 |
| --------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| [AWS ECS Fargate](/self-hosting/aws-fargate)              | AWS Secrets Manager. Pass secret ARNs to Terraform; ECS resolves the values at task launch, so they never appear in your `.tfvars`. |
| [Kubernetes](/self-hosting/kubernetes#secrets-management) | External Secrets Operator syncing from your secret manager, or an existing Kubernetes Secret you create out of band.                |
| [Docker Compose](/self-hosting/docker-compose)            | A `.env` file on the host. Restrict it to the service account that runs Tracecat and exclude it from version control.               |

On Kubernetes, prefer External Secrets Operator over a hand-created Secret. Your secret manager stays the source of truth, the operator re-syncs values rather than copying them, and no plaintext passes through a shell history or a manifest. Reserve chart-managed secret templates for pipelines that encrypt values at rest with Sealed Secrets or SOPS.

### Rotation

Rotation support differs by secret. Check the differences before you plan a rotation window.

<Warning>
  **`TRACECAT__DB_ENCRYPTION_KEY` cannot be rotated**

  Tracecat encrypts under a single Fernet key with no re-encryption path.
  Changing it makes every stored credential unrecoverable, and there is no
  migration to re-key existing rows. Treat this key as permanent for the life of
  the deployment: back it up, and control access to it at least as tightly as
  the credentials it encrypts.
</Warning>

| Secret                                 | Overlap window | Rotation procedure                                                                                                                                      | Blast radius                                                                                                                                                                                                                                                                           |
| -------------------------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `TEMPORAL__PAYLOAD_ENCRYPTION_KEYRING` | Yes            | Add the new key to `keys` and let every service pick it up, then point `current_key_id` at it. Keep retired keys as long as you retain their histories. | None for existing histories, which stay readable under the key they were written with. Between the two steps, a service still on the old keyring cannot decrypt payloads written under the new key. In ARN mode that gap lasts up to `TEMPORAL__PAYLOAD_ENCRYPTION_CACHE_TTL_SECONDS`. |
| `TRACECAT__SIGNING_SECRET`             | No             | Rotate, then reissue every affected URL.                                                                                                                | Every webhook URL and agent channel endpoint URL. Breaks in-flight Slack OAuth installs, and pending Slack approval buttons for up to 24 hours.                                                                                                                                        |
| `TRACECAT__SERVICE_KEY`                | No             | Restart every service that holds it in one window, including `ui`, which uses it for the SAML ACS proxy.                                                | While services disagree, in-flight agent turns fail their next tool or LLM call, executor calls fail, and service-to-service requests return `401`. Miss `ui` and SSO login breaks.                                                                                                    |
| `USER_AUTH_SECRET`                     | No             | Restart `api` and `mcp` together.                                                                                                                       | Active MCP access tokens (1-hour lifetime), and in-flight password reset and verification links. Sessions are database-backed, so users stay logged in. MCP refresh tokens are hashed and survive.                                                                                     |

## Isolation

Tracecat executes user-defined Python scripts, custom actions, and agents inside the executor service. You choose between nsjail isolation and no isolation.

Defaults differ by deployment target.

| Deployment                                      | Default                                                                               |
| ----------------------------------------------- | ------------------------------------------------------------------------------------- |
| [Kubernetes](/self-hosting/kubernetes#security) | nsjail sandbox. The chart applies the required security context to the executor pods. |
| [Docker Compose](/self-hosting/docker-compose)  | No isolation. `TRACECAT__DISABLE_NSJAIL=true` with the `direct` backend.              |
| [AWS Fargate](/self-hosting/aws-fargate)        | No isolation. Fargate cannot grant the capabilities nsjail requires.                  |

### nsjail sandbox (recommended for production)

For production, enable [nsjail](https://github.com/google/nsjail) — a process isolation tool from Google that enforces:

* **Filesystem isolation** — scripts reach only their job directory and explicitly mounted paths. The host filesystem stays invisible.
* **Resource limits** — nsjail caps CPU time, memory, file size, and process count per execution, so a runaway script cannot starve the host.
* **User namespace separation** — scripts run as unprivileged users even when the container runs as root.
* **Network access** — scripts keep network access, since they need to reach databases, APIs, and S3, but nsjail confines it to the container's network namespace.

To enable nsjail, set the following in your `.env`:

```bash theme={null}
TRACECAT__DISABLE_NSJAIL=false
TRACECAT__EXECUTOR_BACKEND=ephemeral
```

nsjail requires:

* Linux with kernel 4.6+
* Docker privileged mode or `CAP_SYS_ADMIN` capability on the executor container
* The nsjail binary and sandbox rootfs (included in Tracecat images)

<Info>
  nsjail is not supported on macOS or Windows. Use the `direct` backend on those platforms.
</Info>

### No isolation

Without nsjail, scripts, custom actions, and agents run as regular subprocesses in the executor.

This is a supported production configuration when you trust everything that runs. That means your own workflow and custom registry code, the third-party dependencies those actions install, and the agents, tools, and MCP servers you enable.

Review that code and pin those dependencies as you would any code with direct access to your systems. Choose nsjail instead when you run code you have not reviewed, such as untrusted third-party packages or agents that generate and execute their own code.

### Choosing a backend

| Backend     | Isolation                        | Latency  | Use case                                 |
| :---------- | :------------------------------- | :------- | :--------------------------------------- |
| `direct`    | None                             | \~50ms   | Trusted code, dependencies, and agents   |
| `ephemeral` | nsjail sandbox (cold per action) | \~4000ms | Untrusted code, dependencies, and agents |

## Authentication

Docker Compose deployments default to basic email/password authentication. For production, configure [OIDC](/authentication/oidc) or [SAML](/authentication/saml) SSO.

See [Roles and permissions](/manage-platform/rbac) for the roles you assign to users and groups once they can sign in.

## TLS

Never run production traffic over plain HTTP. See [TLS and certificates](/self-hosting/tls) for Caddy-based automatic TLS setup, custom certificates, and trusting internal CAs.

## Related pages

* See [Architecture](/security/architecture) for the platform and AI agent trust model.
