Configuration¶
Cmsify loads the base appsettings.json for each application, then normal environment variables. In Development it also loads dotenv files: repository-level .env values load first, and app-level .env or .env.local files under src/Cmsify.Api and src/Cmsify.Admin override them. Copy the root .env.example for the standard local setup, or use the app-specific templates when running an app directly.
Optional SigNoz and GlitchTip telemetry¶
API and Admin can independently export structured logs, ASP.NET Core/outbound HTTP traces, and runtime metrics to an external SigNoz-compatible OTLP endpoint. Set OpenTelemetry__Enabled=true with a valid OpenTelemetry__OtlpEndpoint; logs, traces, metrics, protocol, headers, service metadata, and trace sampling are individually configurable. An invalid enabled endpoint emits a safe warning and leaves export disabled.
Set Sentry__Dsn to enable error reporting through a Sentry-compatible GlitchTip project. Events are error-level by default, PII collection is disabled, and GlitchTip trace sampling defaults to 0.0 but remains configurable. Keep DSNs and OTLP headers in deployment secrets; the production Compose template maps independent API_* and ADMIN_* values into each host. Cmsify does not provision telemetry services locally.
Environment-variable names replace : with __. Comma-separated values are accepted for Cors__AllowedOrigins and Media__AllowedMimeTypes; use indexed names such as TrustedProxy__TrustedProxies__0 for configuration arrays. Commented indexed values in the templates are optional examples, not active configuration.
Shared hosting¶
| Setting | Default/example | Description |
|---|---|---|
ASPNETCORE_ENVIRONMENT |
Development |
Selects the ASP.NET Core environment; dotenv files load only in Development. |
AllowedHosts |
* |
Host-header allow-list for the API or Admin host. Restrict this in production when appropriate. |
API: connectivity, diagnostics, and ingress¶
| Setting | Default/example | Description |
|---|---|---|
ConnectionStrings__Cmsify |
local PostgreSQL connection string | Required PostgreSQL connection for the API. Treat its password as a secret. |
Cors__AllowedOrigins |
http://localhost:5001,https://localhost:7002 |
Browser origins permitted to call the API. Use explicit HTTPS origins in production. |
Api__SwaggerEnabled |
false |
Enables Swagger outside Development. |
Api__HealthDashboardEnabled |
false |
Enables the internal /health/dashboard HTML operator view. Restrict this endpoint at the reverse proxy; it is not a public status page. |
Serilog__MinimumLevel__Default |
Information |
Default API log level. |
Serilog__MinimumLevel__Override__Microsoft.AspNetCore |
Warning |
Log level for ASP.NET Core framework events. |
Serilog__File__Enabled |
false |
Enables the rolling API log file sink. |
Serilog__File__Path |
empty | Rolling file path when file logging is enabled. |
Serilog__File__RetainedFileCountLimit |
14 |
Number of rolled log files to retain. |
SecurityHeaders__PathOverrides__0__PathPrefix |
/swagger |
Path prefix for the first security-header override. Add further overrides with the next numeric index. |
SecurityHeaders__PathOverrides__0__ReferrerPolicy |
no-referrer |
Referrer policy for that path override. |
TrustedProxy__RequireTrustedProxiesInProduction |
true |
Requires explicit trusted proxy configuration in production before forwarded headers are accepted. |
TrustedProxy__TrustedProxies__0 |
optional IP address | First trusted reverse-proxy address; add indexes for additional proxies. |
TrustedProxy__TrustedNetworks__0 |
optional CIDR network | First trusted reverse-proxy network; add indexes for additional networks. |
RateLimit__PerActor__PermitPerMinute |
600 |
Per authenticated actor/anonymous actor request limit per minute. |
RateLimit__PerIp__PermitPerMinute |
60 |
Per-client-IP request limit per minute. |
API: authentication and first-run data¶
| Setting | Default/example | Description |
|---|---|---|
Auth__BcryptCost |
12 |
BCrypt work factor for passwords and API client tokens. Higher values increase CPU cost. |
Auth__SessionAbsoluteExpiryHours |
8 |
Maximum API local-session lifetime when sliding expiry is disabled. |
Auth__SessionSlidingExpiryMinutes |
480 |
Renewed API local-session lifetime; set to 0 to use only the absolute expiry. |
Auth__SessionTouchIntervalSeconds |
300 |
Minimum interval between persistence updates for an active user session. |
Auth__ApiClientTouchIntervalSeconds |
300 |
Minimum interval between persistence updates for an active API client. |
Auth__Oidc__Enabled |
false |
Enables API JWT bearer authentication and the Admin OIDC sign-in option. |
Auth__Oidc__Authority |
empty | OIDC issuer/authority used to validate JWT bearer tokens. Required when OIDC is enabled. |
Auth__Oidc__Audience |
cmsify |
Expected JWT audience. |
Auth__Oidc__Audiences__0 |
cmsify |
First accepted JWT audience for the reusable API bearer registration; set this for every accepted audience. |
Auth__Oidc__ClientId |
empty | Admin OIDC client ID. Required for the interactive Admin sign-in option. |
Auth__Oidc__ClientSecret |
empty | Admin OIDC client secret. Store only in a secret manager or environment configuration. |
Auth__Oidc__RequireHttpsMetadata |
production default | Require HTTPS OIDC discovery metadata; keep enabled outside controlled development. |
Auth__Oidc__ClaimsMapping__Role |
cmsify_role |
Claim name mapped to the Cmsify role. |
Auth__Oidc__ClaimsMapping__WorkspaceId |
cmsify_workspace |
Claim name mapped to the optional workspace ID. |
Seed__DefaultWorkspace__Name |
Default |
Name used only when creating the first workspace. |
Seed__DefaultWorkspace__Slug |
default |
Slug used only when creating the first workspace. |
Seed__Admin__Email |
admin@localhost |
Email for the first admin user. |
Seed__Admin__DisplayName |
Cmsify Admin |
Display name for the first admin user. |
Seed__Admin__Password |
replace before use | Plaintext password for the first admin; use this or PasswordHash, never commit either. |
Seed__Admin__PasswordHash |
empty | Precomputed BCrypt hash alternative to Password for the first admin. |
Secrets__ActiveKeyId |
development locally |
ID of the sole key used for new signing-secret writes. Production requires it to name a configured key. |
Secrets__EncryptionKeys__<keyId> |
development fixture locally | Canonical Base64 for exactly 32 bytes. Retain entries for every v2 ciphertext that may still exist; use a secret manager in production. |
Secrets__EncryptionKey |
migration input only | Legacy v1 read key. Configure only while existing v1 ciphertext remains; it is never used for new writes. |
Secrets__Rotation__Enabled |
false |
Enables the opt-in, bounded PostgreSQL signing-secret re-encryption worker. Start disabled and enable only for an observed window. |
Secrets__Rotation__BatchSize |
100 |
Maximum endpoint rows claimed per key-rotation cycle (1–500). |
Secrets__Rotation__DelaySeconds |
5 |
Delay between key-rotation cycles (1–3600 seconds). |
API: media and background processing¶
| Setting | Default/example | Description |
|---|---|---|
Storage__Provider |
local |
Media storage provider: local or s3. |
Storage__Local__BasePath |
.local/storage |
Local media root directory. |
Storage__Local__RootPath |
.local/storage |
Backward-compatible local media root fallback; normally keep it equal to BasePath. |
Storage__S3__BucketName |
empty | S3-compatible bucket; required when Storage__Provider=s3. |
Storage__S3__Region |
us-east-1 |
S3 region. |
Storage__S3__AccessKey |
empty | S3 access key; treat as a secret. |
Storage__S3__SecretKey |
empty | S3 secret key; treat as a secret. |
Storage__S3__ServiceUrl |
empty | Optional S3-compatible endpoint URL. |
Storage__S3__ForcePathStyle |
automatic | Uses path-style addressing when ServiceUrl is set unless explicitly false; otherwise uses the provider default. |
Media__MaxFileSizeMb |
50 |
Maximum uploaded media-file size in MiB. |
Media__AllowedMimeTypes |
documented default list | Comma-separated MIME types or prefixes allowed for uploads. |
Media__Operations__ReconciliationIntervalSeconds |
300 |
Delay between bounded reconciliation cycles. |
Media__Operations__LeaseDurationSeconds |
300 |
Fenced deletion/checkpoint claim lease. Expired claims can be recovered by another replica. |
Media__Operations__BatchSize |
100 |
Maximum deletion, stale-upload, verification, or listing work per operation (1–1,000). |
Media__Operations__RetryBaseSeconds |
30 |
First failed-deletion retry delay. |
Media__Operations__RetryCapSeconds |
3600 |
Maximum exponential retry delay. |
Media__Operations__RetentionDays |
30 |
Recovery window before a user-deleted blob becomes eligible for purge. |
Media__Operations__OrphanGraceHours |
24 |
Minimum object age before an unowned managed-prefix object can be queued for deletion. |
Media__Operations__AbandonedUploadMinutes |
30 |
Age at which an incomplete database-first upload becomes failed cleanup work. |
Media__Operations__ManagedPrefixes__0/1 |
cmsify/media/, default/ |
Fixed prefixes eligible for orphan scans; foreign prefixes are rejected by validation. |
Webhook__OutboxPollIntervalSeconds |
30 |
Durable outbox polling interval (1–3600 seconds). |
Webhook__OutboxLeaseDurationSeconds |
300 |
Outbox claim lease (1–1800 seconds). |
Webhook__OutboxBatchSize |
100 |
Maximum outbox rows claimed per cycle (1–500). |
Webhook__RetryIntervalSeconds |
30 |
Interval for polling webhook deliveries due for retry. |
Webhook__DeliveryLeaseDurationSeconds |
300 |
Delivery claim lease (1–1800 seconds). |
Webhook__DeliveryBatchSize |
100 |
Maximum due delivery rows claimed per cycle (1–500). |
Webhook__MaxAttempts |
10 |
Maximum webhook delivery attempts before failure. |
Webhook__RequestTimeoutSeconds |
15 |
Outbound webhook HTTP timeout (1–120 seconds). |
Webhook__AllowHttp |
false |
Allows non-TLS webhook endpoints. Keep false; opt in only for controlled development. Webhook egress remains direct-only and does not provide a proxy mode. |
Webhook__RetentionDays |
30 |
Retention for processed outbox rows and successful delivery logs; retry and dead-letter diagnostics are retained. |
Webhook__CleanupBatchSize |
100 |
Per-table retention deletion limit per cleanup cycle (1–500). |
Webhook__CleanupIntervalSeconds |
3600 |
Durable-worker cleanup cadence (1–86400 seconds). |
Scheduler__PublishingIntervalSeconds |
60 |
Interval for processing scheduled content publication. |
Scheduler__PublishingLeaseDurationSeconds |
300 |
Durable scheduled-publication lease (1–1800 seconds). |
Scheduler__PublishingBatchSize |
100 |
Maximum due scheduled rows claimed per cycle (1–500). |
Admin¶
| Setting | Default/example | Description |
|---|---|---|
Admin__ApiBaseUrl |
https://localhost:61241 |
Required base URL used by the server-rendered Admin app to call the API. |
Admin__OidcProviderName |
Authentik |
Provider name displayed on the Admin OIDC sign-in option. |
Admin__Auth__Session__SlidingWindowMinutes |
60 |
Sliding Admin cookie lifetime. Keep it no longer than the API session lifetime. |
Admin__Auth__Session__MaxLifetimeHours |
24 |
Absolute Admin cookie lifetime. |
Admin__DataProtection__KeysPath |
.local/keys/admin |
Directory used to persist Admin Data Protection keys. Persist this path across production restarts. |
Auth__Oidc__TokenCache__Redis__Enabled |
false |
Use the distributed OIDC token cache for multi-instance Admin deployments. |
Auth__Oidc__TokenCache__Redis__ConnectionString |
empty | Redis connection string required when the distributed token cache is enabled. |