Configuration reference
This page is for operators. It lists the environment variables the API reads when it starts. You can also put them in a .env file in the API's working directory.
Single sign-on, email, Slack, workflow and risk settings live in their own YAML files. The settings below only give their paths.
| Setting | Purpose | Type | Default | Example |
|---|---|---|---|---|
CCF_AGENT_INSTANCE_ONESHOT_RETENTION | How long a one-shot agent instance (daemon=false) can go unseen before the prune job deletes it. (new in 0.21) | duration | 24h | CCF_AGENT_INSTANCE_ONESHOT_RETENTION=48h |
CCF_AGENT_INSTANCE_PRUNE_ENABLED | Schedules the job that prunes stale agent instances. It runs on the background worker, so it also needs CCF_WORKER_ENABLED. (new in 0.21) | bool | true | CCF_AGENT_INSTANCE_PRUNE_ENABLED=false |
CCF_AGENT_INSTANCE_PRUNE_SCHEDULE | When the agent instance prune job runs, as a six-field cron expression with seconds first. The job runs at most once an hour, whatever the schedule. (new in 0.21) | string | 0 17 * * * * | CCF_AGENT_INSTANCE_PRUNE_SCHEDULE="0 30 * * * *" |
CCF_AGENT_INSTANCE_RETENTION | How long a daemon agent instance can go unseen before the prune job deletes it. (new in 0.21) | duration | 720h | CCF_AGENT_INSTANCE_RETENTION=336h |
CCF_AGENT_INSTANCE_STALE_AFTER | How recently an agent instance must have sent a heartbeat or a report to count as fresh. (new in 0.21) | duration | 10m | CCF_AGENT_INSTANCE_STALE_AFTER=15m |
CCF_AGENT_MAX_INSTANCES | The most instances one agent can have that aren't due for pruning. At the cap, a new instance replaces the oldest stale one; when every instance is fresh, a report from a new instance gets 409 Conflict. (new in 0.21) | int | 500 | CCF_AGENT_MAX_INSTANCES=1000 |
CCF_AI_API_KEY | The API key for the AI provider that generates dashboard suggestions. Treat it as a secret. | string | none | CCF_AI_API_KEY=<your provider API key> |
CCF_AI_BASE_URL | Overrides the AI provider's API address, for example to go through a proxy. Empty uses the provider's default. | string | none | CCF_AI_BASE_URL=https://llm-proxy.example.com |
CCF_AI_ENABLED | Turns on AI-generated dashboard suggestions, which propose evidence filters for the controls of a system security plan. | bool | false | CCF_AI_ENABLED=true |
CCF_AI_MAX_CALLS_PER_RUN | The most model calls one suggestion run may plan. A run that would need more is refused. 0 means no limit. | int | 0 | CCF_AI_MAX_CALLS_PER_RUN=100 |
CCF_AI_MAX_CONTROLS_PER_CHUNK | How many controls go into one model call of a suggestion run. | int | 40 | CCF_AI_MAX_CONTROLS_PER_CHUNK=20 |
CCF_AI_MAX_LABEL_SETS_PER_CHUNK | How many evidence label sets go into one model call of a suggestion run. | int | 200 | CCF_AI_MAX_LABEL_SETS_PER_CHUNK=100 |
CCF_AI_MAX_SUGGESTIONS_PER_RUN | The most suggestions one run stores. Further suggestions from the run are dropped. | int | 500 | CCF_AI_MAX_SUGGESTIONS_PER_RUN=200 |
CCF_AI_MODEL | The model that generates dashboard suggestions. | string | claude-opus-4-8 | CCF_AI_MODEL=claude-opus-4-8 |
CCF_AI_PROVIDER | The AI provider. anthropic is the only supported value. | string | anthropic | CCF_AI_PROVIDER=anthropic |
CCF_AI_QUEUE_WORKERS | How many suggestion jobs the background worker runs at once. | int | 4 | CCF_AI_QUEUE_WORKERS=2 |
CCF_AI_REQUEST_TIMEOUT | How long one model call may take. | duration | 120s | CCF_AI_REQUEST_TIMEOUT=300s |
CCF_API_ALLOWED_ORIGINS | The origins allowed to call the API from a browser (CORS), comma separated. Set it to the address of your UI. | list | http://localhost:3000 | CCF_API_ALLOWED_ORIGINS=https://ccf.example.com,https://ccf-staging.example.com |
CCF_APP_PORT | The address the API listens on. A bare port such as 8080 is read as :8080. | string | :8080 | CCF_APP_PORT=:8443 |
CCF_ARTIFACT_MAX_BYTES | The largest policy evaluation artifact an agent can upload, in bytes. | int | 16777216 (16 MiB) | CCF_ARTIFACT_MAX_BYTES=33554432 |
CCF_ARTIFACT_MAX_CONCURRENT | How many artifact uploads the API stores at once. Further uploads wait briefly for a slot, then get 429 Too Many Requests. | int | 8 | CCF_ARTIFACT_MAX_CONCURRENT=16 |
CCF_AUTHZ_CACHE_TTL | How long the authzen driver caches each decision. Empty, 0 or an invalid value turns the cache off. | duration | 0 (off) | CCF_AUTHZ_CACHE_TTL=5s |
CCF_AUTHZ_CEDAR_POLICY_DIR | A directory of your own .cedar policy files, added to the bundled role policies. Only the cedar driver reads it. | string | none | CCF_AUTHZ_CEDAR_POLICY_DIR=/etc/ccf/policies |
CCF_AUTHZ_DRIVER | The authorization engine. builtin allows every signed-in user and keeps administration to admins; cedar enforces the bundled roles; authzen asks a remote AuthZen policy decision point. See Authentication and permissions. | string | builtin | CCF_AUTHZ_DRIVER=cedar |
CCF_AUTHZ_ENDPOINT | The evaluation URL of the remote policy decision point. Only the authzen driver reads it. | string | none | CCF_AUTHZ_ENDPOINT=https://pdp.example.com/access/v1/evaluation |
CCF_AUTHZ_FAIL_MODE | What happens when the policy decision point can't be reached. closed denies the request, open allows it; any other value is read as closed. | string | closed | CCF_AUTHZ_FAIL_MODE=closed |
CCF_AUTHZ_ROLE_ASSIGNMENTS | The file that assigns roles to users, groups and agents. Only the cedar driver reads it; a missing file authorizes agents only. | string | authz-roles.yaml | CCF_AUTHZ_ROLE_ASSIGNMENTS=/etc/ccf/authz-roles.yaml |
CCF_DB_CONNECTION | The PostgreSQL connection string. | string | required | CCF_DB_CONNECTION="host=db user=ccf dbname=ccf port=5432 sslmode=require" |
CCF_DB_DEBUG | Logs every SQL statement. The --debug flag sets it too. | bool | false | CCF_DB_DEBUG=true |
CCF_DB_DRIVER | The database driver. postgres is the only supported value. | string | required | CCF_DB_DRIVER=postgres |
CCF_DIGEST_ENABLED | Schedules the digest emails. | bool | true | CCF_DIGEST_ENABLED=false |
CCF_DIGEST_SCHEDULE | When the digest emails go out, as a cron expression or a descriptor such as @daily. | string | @weekly | CCF_DIGEST_SCHEDULE=@daily |
CCF_EMAIL_CONFIG | The path of the email configuration file. When the file can't be loaded, the API doesn't send email. | string | email.yaml | CCF_EMAIL_CONFIG=/etc/ccf/email.yaml |
CCF_ENVIRONMENT | The deployment environment. local and development let the sign-in cookie work over plain HTTP; anything else, including production, marks it Secure. | string | production | CCF_ENVIRONMENT=development |
CCF_EVIDENCE_DEFAULT_EXPIRY_MONTHS | How many months evidence stays valid when it doesn't set its own expiry. Values below 1 are read as 1. | int | 1 | CCF_EVIDENCE_DEFAULT_EXPIRY_MONTHS=3 |
CCF_EVIDENCE_REQUIRE_SUBJECT | What the API does with agent evidence that has no subject: off accepts it, warn accepts it and logs a warning, enforce rejects it. (new in 0.21) | string | off | CCF_EVIDENCE_REQUIRE_SUBJECT=warn |
CCF_JWT_PRIVATE_KEY | The path of the PEM file with the RSA private key that signs tokens. When both key paths are set, the API creates the key files if they don't exist and loads them. When either is unset, it generates a new key pair at each start, so tokens don't survive a restart. | string | none | CCF_JWT_PRIVATE_KEY=/etc/ccf/jwt/private.pem |
CCF_JWT_PUBLIC_KEY | The path of the PEM file with the RSA public key that verifies tokens. See CCF_JWT_PRIVATE_KEY. | string | none | CCF_JWT_PUBLIC_KEY=/etc/ccf/jwt/public.pem |
CCF_JWT_SECRET | A shared secret the API reads at startup and warns about when it's unset. Tokens are signed with the RSA keys, not with this secret. | string | change-me | CCF_JWT_SECRET=<a long random string> |
CCF_MANUAL_EVIDENCE_REQUIRE_SUBJECT | Requires evidence that users submit by hand to name a subject. (new in 0.21) | bool | false | CCF_MANUAL_EVIDENCE_REQUIRE_SUBJECT=true |
CCF_METRICS_ENABLED | Starts the Prometheus metrics server. | bool | true | CCF_METRICS_ENABLED=false |
CCF_METRICS_PORT | The address the metrics server listens on. | string | :9090 | CCF_METRICS_PORT=:9091 |
CCF_PLAYBACK_ENABLED | Serves POST /api/playback/evaluate, which runs a caller's Rego policy against a caller's input inside the API. | bool | true | CCF_PLAYBACK_ENABLED=false |
CCF_PLAYBACK_MAX_BYTES | The largest playback request body, in bytes. | int | 2097152 (2 MiB) | CCF_PLAYBACK_MAX_BYTES=4194304 |
CCF_PLAYBACK_MAX_CONCURRENT | How many playback evaluations run at once across all callers. Further requests get 429 Too Many Requests. | int | 4 | CCF_PLAYBACK_MAX_CONCURRENT=8 |
CCF_PLAYBACK_TIMEOUT | How long one playback evaluation may take. | duration | 5s | CCF_PLAYBACK_TIMEOUT=10s |
CCF_PPROF_ENABLED | Starts the Go pprof profiling server. Don't expose it publicly. | bool | false | CCF_PPROF_ENABLED=true |
CCF_PPROF_PORT | The address the pprof server listens on. A bare port such as 6060 is read as :6060. | string | :6060 | CCF_PPROF_PORT=127.0.0.1:6060 |
CCF_RISK_CONFIG | The path of the risk configuration file, which turns on and schedules the risk jobs such as review reminders. When the file is invalid, every risk job is off. | string | risk.yaml | CCF_RISK_CONFIG=/etc/ccf/risk.yaml |
CCF_SLACK_CONFIG | The path of the Slack configuration file. When the file can't be loaded, the Slack integration is off. | string | slack.yaml | CCF_SLACK_CONFIG=/etc/ccf/slack.yaml |
CCF_SSO_CONFIG | The path of the single sign-on (SSO) configuration file. When the file can't be loaded, SSO is off. | string | sso.yaml | CCF_SSO_CONFIG=/etc/ccf/sso.yaml |
CCF_STRICT_DISABLE_PUBLIC_AGENT_ENDPOINTS | Requires a token on agent heartbeats, evidence and playback. By default these endpoints also accept requests without one. | bool | false | CCF_STRICT_DISABLE_PUBLIC_AGENT_ENDPOINTS=true |
CCF_USE_DEV_LOGGER | Logs in a human-readable development format instead of JSON. | bool | false | CCF_USE_DEV_LOGGER=true |
CCF_WEB_BASE_URL | The address of the UI. The API uses it to build links in emails, such as password reset links. | string | http://localhost:8000 | CCF_WEB_BASE_URL=https://ccf.example.com |
CCF_WORKER_ENABLED | Starts the background worker that runs queued jobs such as email, digests and pruning. | bool | true | CCF_WORKER_ENABLED=false |
CCF_WORKER_USE_POLLING | Makes the worker poll the database for jobs instead of waiting on PostgreSQL LISTEN/NOTIFY. | bool | false | CCF_WORKER_USE_POLLING=true |
CCF_WORKFLOW_CONFIG | The path of the workflow configuration file. When the file can't be loaded, the workflow scheduler is off. | string | workflow.yaml | CCF_WORKFLOW_CONFIG=/etc/ccf/workflow.yaml |