ShrouDB

Keep customer data encrypted, even from your own database.

ShrouDB is a security server you run next to your application. Your code calls it to encrypt sensitive fields, store secrets, sign users in, and check permissions. Your database holds only ciphertext. ShrouDB holds the keys and logs every access.

app.ts
// Before: the SSN is stored in Postgres as plaintext
await sql`INSERT INTO customers (id, ssn) VALUES (${id}, ${ssn})`;

// After: Postgres only ever sees ciphertext. The key stays in ShrouDB.
const { ciphertext } = await shroudb.cipher.encrypt("customers", b64(ssn));
await sql`INSERT INTO customers (id, ssn) VALUES (${id}, ${ciphertext})`;

Built for teams that handle data they can't afford to leak.

If your product stores health records, financial details, identity documents, or other personal data, you're expected to encrypt it, control who can read it, and show an auditor that you did.

Teams usually piece that together from a key management service, a secrets manager, an auth provider, and logs from each of them, then write and maintain the code that connects them. Every piece has its own credentials, its own permission model, and its own way of failing.

ShrouDB provides those pieces as one server you host: one config file, one set of access tokens, and one audit log. You can turn on a single feature, such as field encryption, and add others when you need them.

How it works

ShrouDB runs as a single server called Moat. You start it, point your app at it, and decide what each part of your system is allowed to do.

Step 1

Run the server

One binary, or the shroudb/moat Docker image. It stores its data on local disk, encrypted under a master key you generate.

terminal
$ brew install shroudb/tap/shroudb-moat
$ export SHROUDB_MASTER_KEY=$(openssl rand -hex 32)
$ shroudb-moat --config moat.toml
Step 2

Call it from your code

SDKs for TypeScript, Python, Go, and Ruby. Anything else can use the HTTP API or the RESP3 wire protocol.

typescript
import { ShrouDB } from "@shroudb/sdk";

const shroudb = new ShrouDB({
  moat: "http://localhost:8200",
  token: process.env.SHROUDB_TOKEN,
});
Step 3

Give each service only what it needs

Each access token is limited to the engines and namespaces it needs, read-only where possible. Every call is recorded in the audit log.

moat.toml
[access.policies.web]
token  = "${WEB_APP_TOKEN}"
scopes = [
  "cipher:customers/*",   # use the customers keyring
  "keep:*/READ",          # read secrets, never change them
]

What it replaces

You don't have to switch everything at once. Most teams start with the one problem that's blocking them.

You need toUsually done withIn ShrouDB
Encrypt fields in your databaseAWS KMS or Vault Transit, plus code to call itCipher
Keep credentials out of config filesVault KV, a cloud secrets manager, or .env filesKeep
User accounts and sessionsAuth0, Cognito, or your own tablesSigil
Search encrypted columnsDecrypt everything to search, or leave the column unencryptedVeil
Prove who accessed whatLogs spread across each of the services aboveChronicle
TLS certificates for internal servicesstep-ca or hand-run OpenSSLForge

Why you can trust it with your keys

A security server should be held to a higher standard than the systems it protects. These are the rules ShrouDB is built to.

Nothing is written to disk unencrypted

There is no plaintext mode to forget to turn off. Every record is encrypted with AES-256-GCM before it reaches storage.

One master key to protect

Each engine and namespace gets its own key, derived from a single master key with HKDF. Keep the master key in your KMS or HSM and pass it in at startup.

Tokens carry only the access they need

Each access token is limited to specific engines and namespaces, with read, write, or admin access. Your web app can use one keyring and read secrets without being able to change them.

Fails closed

Requests without a valid token are rejected. If stored data fails an integrity check on startup, ShrouDB stops instead of serving it.

Plaintext doesn't linger

Keys and decrypted values are held in containers that wipe their memory when released. Core dumps are disabled, so a crash can't write keys to disk.

An audit log you can check

Audit events are hash-chained. Chronicle's VERIFY command reports whether any entry was changed or removed.

Read the full security model →

Where it runs

The API and SDKs are the same in both, so moving from one to the other means changing a URL and a token.

Self-hosted
ShrouDB Moat

Run it on your own servers or in your own cloud account, so keys and data never leave your network.

  • Single binary or Docker image
  • All engines in one process, or split out to separate processes as you grow
  • HTTP on port 8200, RESP3 on port 8201
  • TLS and OpenTelemetry export
Hosted
ShrouDB Cloud

We run the server for you. Start on the free tier and move to self-hosting later without changing your code.

  • Free tier for development and small projects
  • Upgrades, backups, and TLS handled for you
  • Usage-based pricing

Try it on your laptop.

The quickstart installs the server, encrypts a value, stores a secret, and reads back the audit log. It takes about five minutes.