ShrouDB
Deployment

Moat reference

Configuration, protocols, and access tokens for the ShrouDB server.

Moat runs every ShrouDB engine in one process. The engines share one encrypted storage layer and one set of access tokens. Any engine can instead run as a separate process, with Moat forwarding to it, so you can split out a busy engine later without changing client code.

Configuration

Moat reads a TOML file (default moat.toml, or --config, or MOAT_CONFIG). ${VAR} references are replaced with environment variables. Unknown keys are rejected at startup.

moat.toml
[server]
http_bind  = "0.0.0.0:8200"   # HTTP API
resp3_bind = "0.0.0.0:8201"   # RESP3 wire protocol
# otel_endpoint = "http://localhost:4317"

# [server.tls]
# cert = "/etc/moat/tls/cert.pem"
# key  = "/etc/moat/tls/key.pem"

[storage]
data_dir = "/data"
# wal_fsync_mode = "batched"   # batched | per_write | periodic | none

[engines.cipher]
enabled = true

[engines.cipher.keyrings.customers]
algorithm     = "aes-256-gcm"
rotation_days = 90

[engines.sigil]
enabled = true
access_ttl_secs  = 900
refresh_ttl_secs = 604800

[engines.keep]
enabled = true

[engines.chronicle]
enabled = true

[engines.forge]
enabled = false

# Run an engine as a separate process instead:
# [engines.veil]
# mode        = "remote"
# remote_addr = "veil.internal:6799"   # host:port, no scheme
# remote_token = "${VEIL_TOKEN}"

[access.policies.admin]
token  = "${MOAT_ADMIN_TOKEN}"
scopes = ["*:*/*"]

[access.policies.web]
token  = "${WEB_APP_TOKEN}"
scopes = ["cipher:customers/*", "keep:*/READ"]

Master key

Set SHROUDB_MASTER_KEY to 64 hex characters (32 bytes), or point SHROUDB_MASTER_KEY_FILEat a file containing it. Moat derives every engine's storage keys from it. Losing it means losing the data.

Access tokens

Each entry under [access.policies] is a token and a list of scopes. A scope has the form engine:namespace/access, where access is READ, WRITE, or *. Admin operations, such as creating a keyring, are checked as ADMIN on namespace _global, so they need a scope like cipher:*/*.

examples
*:*/*                  # everything (admin)
cipher:*/*             # all of Cipher
cipher:customers/*     # only the customers keyring
keep:*/READ            # read secrets, never write them
chronicle:*/READ       # query the audit log

If no tokens are configured, Moat rejects every request (unless you set require_auth = false under [access], which is meant for local testing only). A request that a token isn't allowed to make gets a DENIED error (HTTP 403).

HTTP API

CommandArgsDescription
GET/healthHealth check, no token needed
POST/v1/{engine}Run a command: {"args": ["COMMAND", ...]}
*/sigil/...Sigil REST endpoints for login, refresh, JWKS, users

Send Authorization: Bearer <token> and Content-Type: application/json.

RESP3 protocol

On port 8201, authenticate with AUTH <token>, then prefix each command with the engine name:

RESP3
AUTH <token>
CIPHER ENCRYPT customers <base64>
KEEP GET db/prod/url
CHRONICLE QUERY ENGINE cipher LIMIT 20
CommandArgsDescription
AUTH<token>Authenticate the connection
PINGLiveness check
HEALTHHealth of every engine

Shutdown

On SIGTERM or SIGINT, Moat stops accepting connections, finishes in-flight requests (up to 30 seconds), flushes the write-ahead log, and exits.

Related

  • Engines: commands and config for each one.
  • Security model: encryption, keys, and the production checklist.