Documentation
Harden a self-hosted install
A checklist for running Docustay on your own servers when the documents are sensitive, including health information. What to switch on, what to keep private, and what to check.
Run Docustay on your own servers and you choose every provider that touches your documents. This page is the checklist for an install that holds sensitive documents, such as health information. Work through it top to bottom after installing and before the first real document.
Docustay is built to follow the HIPAA Security Rule's safeguards: encryption, two-step sign-in, audit logs and access controls. Whether your install meets the rule depends on your servers, your providers and your policies too. This page is not legal advice.
1. Turn on the workspace's health rules
In Settings → Security, turn on This workspace handles health information. It changes these at once, for everyone in the workspace:
| What | With health information on |
|---|---|
| Two-step sign-in | Required for everyone (an owner turns this on in Workspace → Security) |
| Idle sign-out | After 15 minutes without activity, or sooner if you set it in Settings → Security |
| AI drafting | Off, and it cannot be turned on |
| Emails | Never name the document: they say "the document" |
| Signed copies | Sent as a download link (7 days unless you set longer), never as an attachment |
| Access log | Every view, download and export by your team, in Settings → Security, with a CSV |
2. Keep the inside private
- Only the web container listens. In the bundled
docker-compose.ymlonlywebpublishes a port. The database, the file store and the PDF converter talk on Compose's private network. Do not addports:todb,storageorgotenberg. - Put HTTPS in front. Use a reverse proxy with TLS (reverse proxy guide). Set
KEYSTONE_PUBLIC_URLto thehttps://address andKEYSTONE_TRUSTED_PROXY_HOPSto the number of proxies in front. Docustay sends HSTS on every HTTPS answer. - Firewall the host. Allow 443 (and 80 for the certificate check) in; nothing else from outside.
3. Encrypt what is stored
- Disks. Put the Docker volumes (
dbdata,filedata,appdata) on an encrypted disk: LUKS on Linux, or your cloud provider's encrypted volumes. - Secrets.
init.shwritesKEYSTONE_MASTER_KEY, which seals stored secrets (two-step secrets, SMTP passwords, webhook secrets). Keep.envreadable only by the account that runs Docker (chmod 600 .env). - Backups. Encrypt each backup before it leaves the machine (for example
ageorgpg), and keep the key apart from the backup. See Back up and restore.
# encrypt last night's backup folder for one recipient key, then copy only the .age file off the machine
d=$(ls -d backup-* | tail -1)
tar czf - "$d" | age -r "$(cat ~/.docustay-backup.pub)" > "$d.tgz.age"
4. Choose providers that sign a Business Associate Agreement
Everything that sends, stores or reads your documents needs one when the documents hold health information.
- Email. Set
RESEND_API_KEYonly if your Resend plan covers you, or use your own SMTP server in Settings → Email with a provider that signs a BAA. With health information on, emails never carry the document's name or the PDF. - Sign-in. The built-in sign-in (
KEYSTONE_LOCAL_AUTH) keeps identities in your own database. Or connect your own OpenID Connect provider (DOCUSTAY_OIDC_ISSUER, see single sign-on). - AI. Leave
ANTHROPIC_API_KEYempty. Health information keeps AI off in that workspace anyway. - Payments. Never put health details in a payment description or metadata.
- Hosting. Your server or cloud provider holds the disks: it needs a BAA too.
5. Sign-in and sessions
- Owners and admins need two-step sign-in in every workspace. Health information makes it everyone.
- Turn on passkeys (
KEYSTONE_PASSKEYS=1andKEYSTONE_PASSKEY_ORIGINS) so people can use a device instead of a code. - Settings → Security lists where each person is signed in and ends any session.
- When someone leaves, remove them from the team the same day: their sessions end at once.
6. Logs and monitoring
- Server and worker logs leave out email addresses and credentials. Keep that on (it is unless
KEYSTONE_LOG_REDACTION=off). - Send logs to a store you control, kept as long as your policy says.
- Set
KEYSTONE_ALERT_EMAILso a failing backup or a paused sender reaches someone. DOCUSTAY_TELEMETRY=offstops the one anonymous daily usage ping (it never carries document content).
7. Keep it current
- Upgrade when a release comes out (upgrade guide). Release notes say when a fix is about security.
- Run
docker compose pulland rebuild at least monthly, so the operating system packages in each image stay patched. - Report a problem to security@docustay.app.
8. Check it
Before the first real document:
- Open
https://your-address/and confirm the padlock, thencurl -sI https://your-address/ | grep -i strict-transportshows HSTS. - From outside the host, confirm the database port (5432) and the file store port (8333) do not answer.
# run from another machine: each line must say "closed" (nc exits non-zero when nothing answers)
for p in 5432 8333 3000; do nc -z -w 3 your-address "$p" && echo "$p OPEN: close it" || echo "$p closed"; done
- Sign in as an owner without two-step: Docustay sends you to set it up.
- Leave a session idle past the limit: the next click asks you to sign in again.
- Send a test document to yourself: the email does not name it and has no attachment.
- Open a document, then check Settings → Security → Access log shows it.
- Restore last night's backup onto a spare machine and open a signed PDF. Write down how long it took.