Production checklist
Go through this list before the first real user signs in. Each line links to where it is explained.
Secrets and keys
Section titled “Secrets and keys”-
Beacon:EncryptionKeycomes from a secret store or environment variable, never a file in source control; its backup is stored separately from database backups. → Configuration - You know how to rotate it: move the old key to
Beacon:PreviousEncryptionKeys:0, set the new one, setBeacon:Mcp:CallerHashKeyto the old key first if you want MCP caller hashes to stay comparable, run the re-encryption job, then remove the old key. SetBeacon:Audit:IntegrityKeybefore the first rotation: while it is unset, security audit events are signed under a key derived from the caller hash key or the encryption key, and verify as unknown key once that secret leaves the configuration. → Keys and rotation -
Beacon:DataProtection:ApplicationNameis set (one value per environment), and the key ring is encrypted at rest (ProtectKeysWithCertificate/ProtectKeysWithAzureKeyVault), otherwise the host does not start outsideDevelopment. → Host wiring - OIDC client secrets, LLM API keys and SMTP passwords come from the secret store.
-
Beacon:UserManagement:SetupTokenis set for multi-instance first runs, and removed afterwards.
Reverse proxy
Section titled “Reverse proxy”- TLS terminates at the proxy, and the host runs
UseForwardedHeaderswith only your proxies listed, first in the pipeline. The login throttle (10 attempts / 60 s per IP) and the cookie’s Secure flag depend on it.
var forwarded = new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto };forwarded.KnownProxies.Clear();forwarded.KnownNetworks.Clear();forwarded.KnownProxies.Add(IPAddress.Parse("10.0.0.5"));app.UseForwardedHeaders(forwarded);-
Beacon:PublicBaseUrlis the public origin (e.g.https://beacon.example.com), so MCP discovery documents do not echo the client’sHostheader. → MCP & AI clients -
options.BaseUrl(or Admin settings → Base URL) is the public UI URL including/beacon, so notification links work. - HTTPS redirection applies to
/beacon/mcptoo, because API keys travel in headers. - Proxy and Kestrel timeouts allow long requests (AI documentation,
ask): the reference host uses 5 minutes.
Sign-in and access
Section titled “Sign-in and access”- Authorization is on (
options.Authorization.Enabled = true). - SSO admission is narrow:
AllowedTenants,BlockGuests(default on),RequiredGroupsorRequiredRoles;RequireMfaif your provider issuesamr/acr. → Sign-in & identity - Local passwords off once SSO works, with one break-glass account in a vault; alert on event 7119
BreakGlassSignIn. -
Beacon:Authorization:RequireProjectMembership: true; projects planned; data sources linked only where needed. → Access control - Few Admins; duties given as functional permissions;
SeparationOfDutieson if your auditors expect it. - Approval workflow on with at least two Approvers,
RequireApprovedVersionToRunfor regulated data. → Approvals - API keys: decide
Beacon:ApiKeys:MaxLifetimeDaysandMaxOwnerInactivityDays.
Data and SQL
Section titled “Data and SQL”- Every data source uses a read-only login, including PostgreSQL and MySQL. → Connectors
- Deployment locks reviewed:
Beacon:Mcp:ForceReadOnlyandForcePiiDetectionstaytrue; considerForbidRowDataToLlmandForceNoContentRetention. → Access control -
Beacon:Query:MaxExecutionRows(default 100,000) andStatementTimeoutSeconds(default 120) fit your workloads. -
Beacon:Mcp:Ceilings:MaxRowLimitset if project admins must not raise the MCP row limit. -
Beacon:Migrations:Enabledstaysfalseunless you need data migration. It is the only write path. - Notification destinations restricted as needed:
Beacon:Notifications:AllowedHosts:*,DisabledTypes; private networks stay unreachable unless listed inAllowedPrivateNetworks. → Notifications
Audit and observability
Section titled “Audit and observability”-
Beacon:Mcp:Audit:RetentionDaysset to your retention policy and the purge job scheduled;Audit:Required: trueif a tool result must never be returned without its audit row. → MCP observability & audit - Security log events (structured log events 7101 to 7123: membership, roles, sessions, break-glass, access refused, row data to LLM) are shipped to your log pipeline and alerted on. The log events themselves are not stored in Beacon’s database; the actions most of them report are also recorded in the security audit trail. → Security model
- Security audit trail:
Beacon:Audit:IntegrityKeyset from a secret store (before you change the encryption key or the caller hash key), the verification job (ISecurityAuditVerificationService.VerifyNewEventsAsync, hourly) and the retention purge (ISecurityAuditRetentionService.PurgeExpiredAsync) scheduled,Beacon:Audit:RetentionDaysset to your retention policy (at least 365; events are kept forever while it is unset), theBeacon.Auditevents 9104 to 9110 shipped to your SIEM, and alerts on any increment ofbeacon.security_audit.write_failuresandbeacon.security_audit.verification_failures. → Security audit trail - To make the trail append-only at the database as well, Beacon’s connection uses a role that cannot update or delete
security_audit_eventsrows other than through the purge, or triggers do the same. → What the trail does and does not prove - Where MCP audit content is retained, the SQL of every statement a call ran is stored with it: reviewed against your privacy policy;
Beacon:Mcp:Audit:RequireContentpins retention on if the evidence must be kept. → MCP observability & audit - Structured JSON console logs (
Logging:Console:FormatterName=json,IncludeScopes=true) if your platform correlates by trace id. - OpenTelemetry: add
AddBeaconInstrumentation()to your tracer and meter providers; you choose the exporter. Keep notification HTTP calls out of traces (their URLs carry secrets).NotificationRequests.IsNotificationRequestidentifies them. - Health check
GET /beacon/api/health(anonymous, checks the database within 5 s) wired to your load balancer. On a brand-new deployment with user management on, it redirects to/beacon/setupuntil the first administrator exists. Complete setup before the probe goes live.
Scaling
Section titled “Scaling”- Several instances: shared Data Protection key ring (Beacon’s database does this), a SignalR backplane (
ConfigureSignalR), session affinity for/beacon/mcp(legacy MCP clients hold anMcp-Session-Idin memory), and a job runner that fires each recurring job once. - Migrations run once per deployment, not from every replica at the same time. → Metadata database
- Database pool sized for job workers plus web traffic.
Upgrades
Section titled “Upgrades”- All
Moberg.Beacon.*packages on the same version. - Read the release notes of every version you upgrade to: a release can change defaults, and the notes say what to do.
- Back up the metadata database before migrating; migrations are append-only and run forward.
- After upgrading every instance, run one-off jobs the release notes name (for example recipient-secret encryption).