Skip to content
StarLive demo →
ReferenceChecked against main · 31 Oct 202611 min read

Configuration

Every configuration key the AppointMe .NET 10 API reads, with its type, default, and where it's set locally (appsettings, Aspire) and on Azure (appsettings.Devtest.json, Key Vault references).

Files
appsettings.json + appsettings.<Env>.json
Env var form
ConnectionStrings__AppointMeSql
Azure secrets
Key Vault references, set by Bicep
Validation
Options are validated at startup

This page lists every key the API reads at commit 2ccbe87, found by searching src/ for options classes, BindConfiguration, GetConnectionString and IConfiguration reads. Each table gives the default from appsettings.json (or from code when the file doesn’t set it), the local value and the deployed devtest value. A dash means the key isn’t set there. Keys are alphabetical within each table.

The standard ASP.NET Core order applies. Later sources win, and on Azure every secret arrives as an environment variable that App Service resolves from Key Vault.

Order Source Notes
1 src/AppointMe.Api/appsettings.json Defaults for every environment
2 appsettings.<Environment>.json Development, Devtest or Codegen
3 Environment variables __ replaces :. Aspire, the Dockerfile and App Service app settings all arrive this way.
4 Command-line arguments

The API project has no UserSecretsId, so user secrets aren’t loaded. On Azure, a Key Vault reference such as @Microsoft.KeyVault(SecretUri=…) is resolved by App Service before the API sees it, using the Web App’s managed identity.

ASPNETCORE_ENVIRONMENT Selected by What changes in code
Codegen Code, when the entry assembly is GetDocument.Insider (build-time OpenAPI) or the arguments contain codegen Placeholder values from appsettings.Codegen.json. Hangfire isn’t registered, migrations don’t run, and Wolverine runs as an in-memory mediator with the durability agent off.
Development Properties/launchSettings.json, so dotnet run and Aspire MapOpenApi() is mapped, HSTS is off, and Wolverine generates handler code at runtime (TypeLoadMode.Dynamic)
Devtest Bicep: ASPNETCORE_ENVIRONMENT app setting HSTS is on. Wolverine loads pre-generated handlers (TypeLoadMode.Static), which the Docker build writes with codegen write.

One SQL database holds everything. The other two connection strings are optional.

Key Type Default Dev Devtest What it does
ConnectionStrings:AppointMeMessaging string "" — — The Azure Service Bus connection. Read only when Wolverine:Transport is AzureServiceBus.
ConnectionStrings:AppointMeSql string None (required) appsettings.Development.json: Server=localhost,60740;Database=AppointMe;…. Aspire injects its own for the AppointMeSql database resource. Key Vault reference AppointMeSql Every module’s EF Core DbContext and Dapper reads, Wolverine’s message store (schema wolverine) and Hangfire storage (schema hangfire). When it’s missing, startup fails with Connection string 'AppointMeSql' not found.
ConnectionStrings:DataProtectionStorage string "" — Key Vault reference DataProtectionStorage An Azure Storage connection string. When it’s set, the Data Protection key ring is stored in blob data-protection-keys/keys.xml. When it’s empty, the default local key ring is used.

Authentication:Provider chooses Keycloak or Entra External ID. Only the chosen provider’s sections are bound, and every key in them is required and validated at startup.

Key Type Default Dev Devtest What it does
Authentication:Provider string: Keycloak or EntraExternalId Keycloak (file and code) — (default) EntraExternalId Chooses the OIDC and JWT settings, the demo-login authenticator and the IIdentityProvider. Any other value throws at startup.
Authentication:RequireHttpsMetadata bool true (code) false true Whether the OIDC and JWT handlers require HTTPS to fetch discovery metadata and keys. Codegen also sets false.
Authentication:SuperAdmins string[] [] ["demo@appointme.dev"] ["demo@appointme.dev"] Emails, matched case-insensitively, that pass the HangfireDashboard policy for /admin/jobs. They also get IsSuperAdmin in GET /api/v1/me.

Bound when Authentication:Provider is Keycloak. KeycloakOptions marks every property [Required].

Key Type Default Dev Devtest What it does
Authentication:Keycloak:ApiAudience string — appointme-api — The audience the JWT bearer handler expects
Authentication:Keycloak:Authority string — https://localhost:8082/realms/appointme. Aspire overrides it with Keycloak’s endpoint plus /realms/appointme. — The OIDC authority. The demo login posts to <Authority>/protocol/openid-connect/token.
Authentication:Keycloak:FrontendClientId string — appointme-frontend — The OIDC client for browser sign-in and the demo password grant
Authentication:Keycloak:FrontendClientSecret string — A local-only value in appsettings.Development.json — That client’s secret

Bound when Authentication:Provider is EntraExternalId. EntraExternalIdOptions marks every property [Required], so the empty defaults fail validation until you fill them in.

Key Type Default Dev Devtest What it does
Authentication:EntraExternalId:ApiAudience string "" — api://<client-id> The audience the JWT bearer handler expects
Authentication:EntraExternalId:Authority string "" — https://<tenant>.ciamlogin.com/<tenant-id>/v2.0 The OIDC authority. The demo login derives the native-auth base …/oauth2/v2.0/ from it.
Authentication:EntraExternalId:ClientId string "" — The app registration’s client ID The OIDC client, and the client for native-auth demo login
Authentication:EntraExternalId:ClientSecret string "" — Key Vault reference EntraExternalIdClientSecret The OIDC client secret

Bound by the Identity module when Authentication:Provider is Keycloak. KeycloakAdminOptions marks every property [Required]. It’s used to create users with the VERIFY_EMAIL and UPDATE_PASSWORD actions, and to resend the verification email.

Key Type Default Dev Devtest What it does
KeycloakAdmin:BaseUrl string — https://localhost:8082. Aspire overrides it with Keycloak’s endpoint. — The Keycloak base URL for the admin API
KeycloakAdmin:ClientId string — appointme-api — The client for the client-credentials flow, also used for the verify-email redirect
KeycloakAdmin:ClientSecret string — A local-only value in appsettings.Development.json — That client’s secret
KeycloakAdmin:Realm string — appointme — The realm users are created in

Bound by the Identity module when Authentication:Provider is EntraExternalId. EntraIdentityOptions marks every property [Required]. It builds a Microsoft Graph client with ClientSecretCredential that sends invitations and looks users up by email.

Key Type Default Dev Devtest What it does
EntraIdentity:ClientId string "" — The same client ID as above The app that calls Graph
EntraIdentity:ClientSecret string "" — Key Vault reference EntraExternalIdClientSecret, the same secret Its secret
EntraIdentity:TenantId string "" — The External ID tenant ID The tenant the credential signs in to

Entra External ID shows where each value comes from in the portal.

Demo:Enabled turns on the public demo login, the demo-data seeding and two daily jobs. Frontend:BaseUrl is where every sign-in and invitation flow sends the user back.

Key Type Default Dev Devtest What it does
Demo:Enabled bool false true true Lets GET /api/v1/login/demo sign in (it returns 404 when off). DemoSeedingSaga seeds each new company with 150 customers, 3 appointments each. Registers the crm:top-up-demo-customers and booking:top-up-demo-appointments jobs, daily at 03:00 UTC.
Demo:User:Email string — demo@appointme.dev demo@appointme.dev The demo user, which must already exist in the identity provider. If Demo:User is missing, the demo login returns 404.
Demo:User:Name string, optional — John Doe John Doe The display name used when the token has no name claim. Falls back to Demo User.
Demo:User:Password string — AppointMe1 AppointMe1 The demo user’s password, sent to Keycloak’s password grant or Entra’s native-auth API
Frontend:BaseUrl absolute URI, required https://localhost:5173 — (default) https://app.appointme.dev Where users land after sign-in, sign-out and demo login. The invitation link is <BaseUrl>/auth/login. Validated with [Required, Url] at startup.

Turning Demo:Enabled off doesn’t remove recurring jobs that are already registered. Production checklist covers that.

Messaging, jobs, Data Protection and telemetry

Section titled “Messaging, jobs, Data Protection and telemetry”

Wolverine has one key. Hangfire and Data Protection reuse connection strings, and OpenTelemetry reads only the standard OTEL_* variables.

Key Type Default Dev Devtest What it does
APPLICATIONINSIGHTS_CONNECTION_STRING env var — — Bicep: the App Insights connection string Set on the Web App, but nothing in the API reads it
OTEL_EXPORTER_OTLP_ENDPOINT env var The OTLP exporter’s own default Aspire points it at its dashboard Bicep: https://<location>.in.applicationinsights.azure.com/v2/track Where the OTLP exporter sends traces and metrics
Wolverine:Transport string: SqlDurable or AzureServiceBus SqlDurable (file and code) — (default) SqlDurable SqlDurable uses durable local queues on the SQL outbox. AzureServiceBus adds a Service Bus broker that auto-provisions its queues, and needs ConnectionStrings:AppointMeMessaging. Any other value throws at startup.

These have no keys of their own:

Feature Reads Fixed in code
Data Protection ConnectionStrings:DataProtectionStorage Application name appointme, container data-protection-keys, blob keys.xml
Hangfire ConnectionStrings:AppointMeSql Schema hangfire, created if missing. Dashboard at /admin/jobs, gated by Authentication:SuperAdmins. Not registered in Codegen.
OpenTelemetry OTEL_* environment variables Service AppointMe.Api, version 1.0.0. Traces: ASP.NET Core, HttpClient, SqlClient and Wolverine. Metrics: ASP.NET Core, HttpClient and Wolverine*. No logs.
Wolverine ConnectionStrings:AppointMeSql, Wolverine:Transport MessageStorageSchemaName = "wolverine" (the wolverine_* tables are still created in dbo at this commit), durable local queues, auto-applied transactions, ValidationException moved to the error queue

These are read by ASP.NET Core, the container or App Service itself, not by AppointMe code. You set them per environment, and several come from the Dockerfile or the Bicep.

Key Dev Devtest What it does
AllowedHosts * * ASP.NET Core host filtering. * accepts any Host header.
ASPNETCORE_ENVIRONMENT Development (launch profile) Devtest (Bicep) Picks appsettings.<Environment>.json and the code paths in the first section
ASPNETCORE_FORWARDEDHEADERS_ENABLED — true (Bicep) Turns on ASP.NET Core’s forwarded-headers handling for the App Service front end. Program.cs also calls UseForwardedHeaders().
ASPNETCORE_URLS The https launch profile, which Aspire uses: https://localhost:7233;http://localhost:5179. A plain dotnet run takes the first profile, http: http://localhost:5179. http://+:8080 (Dockerfile) Where Kestrel listens
DOCKER_REGISTRY_SERVER_URL — https://<acr>.azurecr.io (Bicep) Read by App Service: the registry it pulls the image from
Logging:LogLevel:Default Information Information Minimum log level
Logging:LogLevel:Microsoft.AspNetCore Warning Warning Quietens framework request logs
Logging:LogLevel:Microsoft.EntityFrameworkCore — Warning Set in appsettings.Devtest.json only
WEBSITES_ENABLE_APP_SERVICE_STORAGE — false (Bicep) Read by App Service: no persistent /home mount in the container
WEBSITES_PORT — 8080 (Bicep) Read by App Service: the container port to route to

Build-time values that end up in the image or the SPA:

Key Where Default What it does
APP_VERSION Docker build arg local Becomes VITE_APP_VERSION, the version in the SPA footer. CI passes the tag, or main-<short sha>.
BUILD_CONFIGURATION Docker build arg Release The configuration for codegen write and dotnet publish
VITE_API_PROXY_TARGET src/AppointMe.Frontend/.env.development https://localhost:7233 Where the Vite dev server proxies /api, /signin-oidc and /admin outside Aspire. Under Aspire, services__appointme-api__https__0 takes precedence.

These look like settings but are constants. Change them in code if you need to.

Setting Value Where
Antiforgery Cookie appointme.csrf. The SPA reads the XSRF-TOKEN cookie and sends it back as X-XSRF-TOKEN. Antiforgery/
Auth cookie appointme.auth: HttpOnly, SameSite Lax, always Secure, 7 days, sliding Authentication/AuthenticationExtensions.cs
CSP Sent as Content-Security-Policy-Report-Only SecurityHeaders/SecurityHeadersMiddleware.cs
Demo top-up schedule 0 3 * * * (daily, 03:00 UTC) The two *JobRegistrar.cs files
Forwarded host header X-Original-Host, with every proxy trusted Program.cs
HSTS 365 days, IncludeSubDomains, outside Development Program.cs
OIDC Code flow, scopes openid profile email, callback /signin-oidc, pushed authorization disabled, only the id_token kept Authentication/AuthenticationExtensions.cs
Startup migrations Every module’s DbContext migrates on startup, except in Codegen AppointMe.Shared/Database/Migrations
Tenant header X-Company-Id Program.cs, see Multi-tenancy

Paths in this table are relative to src/AppointMe.Api/ unless they start with another project.