Skip to content

Deployment

Development runs on defaults that are deliberately unsuitable for a real deployment. This page covers what changes.

Terminal window
dotnet publish src/Docsentry.Web/Docsentry.Web.csproj -c Release -o /path/to/output

Set ASPNETCORE_ENVIRONMENT to your environment name. Anything other than Development turns on the strict checks described below, which is the point.

Three fail loudly at startup. One fails quietly, and is the harder afternoon.

Must authenticate as a member of DocsentryAppRole - not the deployment or schema-owner principal. A startup probe verifies this and refuses to continue if the application is running with more privilege than it should have.

Required outside Development. An absolute path, outside the content root. The host refuses to start without it.

The key ring protects every authentication cookie, the “remember this machine” two-factor cookie, stored secrets such as the antivirus API key, and the keys that encrypt every stored document. Reading it is enough to forge a session for any user. Losing it without a backup means losing every encrypted document.

It is deliberately absent from appsettings.json rather than present-but-empty, because a value in that file would override one supplied by the hosting environment.

Optional, but required in three cases: a non-Windows host, a multi-instance deployment, and any deployment whose recovery plan involves different hardware.

Omitted, the key ring is protected with Windows DPAPI, which is machine-scoped - a DPAPI-protected key ring cannot be restored onto a different machine. Set a thumbprint from the CurrentUser or LocalMachine My store to encrypt with an X.509 certificate instead.

Ships as the placeholder docsentry.example.com.

Deploy the schema before starting the application - see Database deployment.

Two distinct database identities are required:

Principal Does Must not
Deployment Creates the database, applies the Identity migration and DMS scripts, writes schema versions. Be used by the running application.
Application Data reads and writes under deployed grants. Member of DocsentryAppRole. Create databases, alter schema, or apply schema versions.

Governance surfaces such as the audit log and workflow history are append-only for the application principal, and the audit log is additionally sealed and verified, so a defect or compromise in the application cannot rewrite history unnoticed.

Enable Transparent Data Encryption on the database and encrypt its backups. Document contents are encrypted by the application, but the database holds metadata, extracted OCR text and the audit trail.

Populate Security:ForwardedHeaders:KnownProxies or KnownNetworks with your proxy, and set ForwardLimit to the number of proxies in the chain.

Handling is fail-closed: with neither configured, forwarded headers are not trusted at all. That is the safe default - it stops a spoofed client address slipping past address-based rate limiting - but the cost of leaving it unconfigured is that every request appears to originate from the proxy, which makes per-address rate limiting meter your proxy rather than your users.

Terminate TLS at the proxy or at the application, and confirm Security:Hsts matches your intent before enabling preload - preload is difficult to reverse.

If you use the optional content host, the proxy must forward both hostnames to the application and preserve the requested host, AllowedHosts must list both, and the proxy’s access log should drop the ct query parameter. See Security hardening.

Install what you need, and know what you are giving up otherwise:

Component Without it
LibreOffice Office documents get no preview.
Tesseract Document contents are not indexed.
A real antivirus scanner Change Antivirus:ScannerKind from its default. The default recognises only a test string.
SQL Server Full-Text Search Search falls back to a scan, which is slow at scale.

See Installation.

  • Schema deployed; 900_schema_contract.sql passes
  • ConnectionStrings:DefaultConnection uses the least-privilege application principal, supplied from the environment or a secret store
  • DataProtection:KeyPath set, absolute, outside the content root, on an encrypted volume, and backed up
  • DataProtection:CertificateThumbprint set if non-Windows, multi-instance, or portable recovery
  • AllowedHosts set to the real hostname (both hostnames if a content host is used)
  • ASPNETCORE_ENVIRONMENT set to a non-Development value
  • Forwarded headers configured if behind a proxy
  • Transparent Data Encryption enabled, and database backups encrypted
  • Storage root and log directory on encrypted volumes; Storage:WorkingCopyPath on local disk, outside backups
  • Antivirus:ScannerKind changed from the default test scanner
  • BreachedPasswords:Source set to OfflineFile with a current corpus
  • Email configured, PublicSite:BaseUrl set, and a test email received - invitations depend on it
  • Bootstrap administrator seeded and enrolled in two-factor, then Bootstrap:AdminPassword removed from the environment
  • Audit seal log events routed to an external log collector
  • Backups covering the database, the storage root, and the key ring
  • A restore rehearsed - see Backup and restore
Terminal window
curl https://your-host/api/v1/health

Then sign in, upload a document, and confirm it previews. That exercises configuration, the database, encrypted storage, the scanner, and the background jobs in one pass. Finally, open Audit integrity under Administration and run a verification; it should report Healthy.

Multiple instances against one database work, with two requirements: the key ring must be shared and certificate-protected rather than DPAPI-protected, and the storage root must be shared storage that every instance can reach.