Security
Who can reach an instance, and who can read its data.
Key words in capitals follow RFC 2119.
Unix socket
The recommended setup: TamarackDB runs on the same host as the application, on its unix socket (the default, see Configuration).
Nothing goes over the network, and the socket’s permissions decide who may connect.
A transaction often makes several reads before its one write, and the socket keeps each of those round trips short.
Connecting takes write permission on the socket. With the default
socketModeof"0600", only the server’s own user can connect.If the application runs as another user, set
socketMode = "0660"and add the application’s user to the server’s group. For a server running astamarackdb, and an application running aswww-data:sudo usermod -aG tamarackdb www-dataThe application picks up its new group once it restarts.
The server creates the socket under a umask of
0177, so it starts out as0600whatever the process’s umask, then sets it tosocketMode.
Why the umask. Under a looser umask, such as the common 002, the socket would start out open to the group, and a
connection could slip in before socketMode is applied.
Another host
The server speaks plain HTTP only, on the socket and over TCP alike. A client on another host, application or backup, MUST go through a reverse proxy that handles TLS.
Without TLS, bodies and the
authTokenitself travel in clear text over a network outside your control.Put the proxy in front of the socket. Caddy, for example, gets and renews its certificates by itself:
tamarackdb.example.com { reverse_proxy unix//run/tamarackdb/tamarackdb.sock }The proxy’s user MUST be allowed by
socketMode, like the application’s.Turn
enableAuthon: once the proxy is up, the API is reachable over the network, and the token is what keeps others out. The proxy passes theAuthorizationheader through unchanged.In Docker, the server listens over TCP: how to keep its port private is in Install.
Why a proxy, not TLS in the server. A server that loads its certificate once at startup would need a restart, cutting off any write in progress, each time a short-lived certificate is renewed; a proxy renews on its own. It also handles what surrounds TLS (protocol versions, client certificates, address allowlists) better than a store should, and keeps one path for every access from another host.
Bearer token
- When
enableAuthis on, every registered route needsAuthorization: Bearer <token>: every endpoint of the HTTP API,/health,/metrics,/debug, and, in development mode,POST /resetand the profiling endpoints. - A request with no valid token gets
401 Unauthorizedbefore it reaches any handler. - The token is one fixed value,
authToken. Rotating it means changing the configuration and restarting the server: there’s no window where two tokens both work. - The server MUST compare the token in constant time, never with a plain string comparison: one that stops at the first differing byte would let an attacker guess the token one byte at a time, by timing the responses.
enableAuthis off by default, for the recommended setup, where the socket’s permissions already decide who may connect. When it’s off, no request is checked at all.
Why one token. An instance has exactly one trusted caller: the application that owns it. If that application serves many tenants, keeping them apart is its own job, done with tenant metadata on events.
Files
The database file holds every event and projection in plain SQLite. Anyone who can read it bypasses enableAuth and
socketMode entirely.
tamarackdb-initandtamarackdb-backupcreate a missing data directory as0700, and a new database file as0600, whatever the umask. SQLite gives its WAL and shared-memory files the database file’s permissions.A directory or database file that already exists keeps its permissions: the server never changes them. Give a directory you create yourself
0700.Which user runs which command is in Install.
A
config.tomlthat holdsauthTokenMUST be readable by the server’s user only:chmod 600 /path/to/config.toml
Development mode
devMode exposes POST /reset, which deletes every event. It MUST stay off on a production instance (see
Development
mode).