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, and stored secrets such as the antivirus API key. Reading it is enough to forge a session for any user and bypass two-factor authentication.

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 thumbnail 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, so a defect or compromise in the application cannot rewrite history.

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.

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
  • DataProtection:KeyPath set, absolute, outside the content root, and backed up
  • DataProtection:CertificateThumbprint set if non-Windows, multi-instance, or portable recovery
  • AllowedHosts set to the real hostname
  • ASPNETCORE_ENVIRONMENT set to a non-Development value
  • Forwarded headers configured if behind a proxy
  • Antivirus:ScannerKind changed from the default test scanner
  • Email configured and test-send verified, if notifications are wanted
  • Bootstrap administrator seeded, then Bootstrap:AdminPassword removed from the environment
  • Backups covering the database, the storage root, and the key ring
  • A restore rehearsed - see Backup
Terminal window
curl https://your-host/api/v1/health

Then sign in, upload a document, and confirm it previews. That exercises configuration, the database, storage, the scanner, and the background jobs in one pass.

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.