Server (nardbd)
Serving databases over gRPC with mutual TLS — certificates, configuration, grants and the audit log.
nardbd serves one or more .ndbc databases over the network. Clients connect with gRPC. The connection is always mutual TLS (mTLS): the server verifies the client's certificate and the client verifies the server's.
Setup#
cd nardb
go build -o bin/nardbd ./cmd/nardbd
./bin/nardbd certs -dir ./certs -hosts db.example.com,10.0.0.5 -client app
./bin/nardbd example-config > nardbd.json # edit it
./bin/nardbd serve -config nardbd.jsoncerts creates a certificate authority (ca.crt, ca.key), a server certificate and the first client certificate. Key files are written so that only their owner can read them (0600). ca.key can sign new clients; keep it away from the server.
./bin/nardbd client-cert -dir ./certs -client accountingConfiguration#
{
"listen": "127.0.0.1:7070",
"tls_cert": "certs/server.crt",
"tls_key": "certs/server.key",
"client_ca": "certs/ca.crt",
"audit_log": "nardbd-audit.log",
"session_ttl": "8h",
"databases": [
{"name": "shop", "path": "data/shop.ndbc", "key": ""},
{"name": "archive", "path": "data/archive.ndbc", "key": "passphrase-env:NARDB_ARCHIVE_PASSPHRASE"}
]
}| Field | Note |
|---|---|
listen | Defaults to 127.0.0.1. For any other address the server prints a warning; put a firewall in front of it. |
tls_cert, tls_key, client_ca | Required. The server does not run without TLS or without client certificates. |
key | Empty: unencrypted, or the key is in the system keychain. passphrase-env:NAME: passphrase from an environment variable. passphrase-file:/path: passphrase from a file (readable by its owner only). |
Databases are created first with NarDB Shell or the Go API; the server does not create databases.
Users and grants#
A client authenticates as a user of the database, and every statement runs with that user's grants. Create users and grants in the shell:
>> create_user -n app
>> grant -u app -s members -p write
>> grant -u admin -s '*' -p admin
>> revoke -u app -s members
>> show_users| Permission | Allows |
|---|---|
read | selecting with from(...) |
write | read + insert_one, insert_many, update, delete |
admin | write + create_schema, alter_schema, drop_schema |
-s '*' covers every schema, including ones created later. A user without grants can do nothing remotely. Every statement in a script is checked before any of them runs.
Client (Go)#
import "nardb/client"
c, err := client.Dial(ctx, client.Config{
Addr: "db.example.com:7070",
CAFile: "certs/ca.crt",
CertFile: "certs/client-app.crt",
KeyFile: "certs/client-app.key",
})
s, err := c.Authenticate(ctx, "shop", "app", password)
res, err := s.Exec(ctx, `from('members').where({'email': $1}).fields('name');`, email)Values travel separately as $1, $2; they are never embedded in the query text. Large results stream in chunks of 500 rows. The contract is in nardb/proto/nardb/v1/nardb.proto; clients in other languages can be generated from it.
Security behaviour#
- Login errors do not say whether the database, the user or the password was wrong. A missing database and a missing user are rejected in the same time as a wrong password.
- Brute force: 5 failed logins within a minute from the same client (certificate + IP) lock that client for a minute.
- Sessions: the token is 32 random bytes; the server keeps only its hash. It lives for
session_ttl. - Connection limit: the database's
max_connectionssetting caps the number of open sessions. - Audit log (
audit_log): one JSON line per event. Each line holds the time, the event (auth_ok,auth_fail,auth_locked,exec,denied,logout), the client certificate's name, the address, the database, the user, the statement kinds and schemas, the rows affected and the duration. Query text and values are never logged.
{"time":"2026-10-30T14:39:38Z","event":"denied","client":"app","db":"shop","user":"app","statements":["drop_schema:products:admin"],"error":"nardb: permission denied: user 'app' needs admin on 'products' (line 1, col 1)"}Not yet#
- NarDB Shell connecting to a remote server (Connect Remote Server).
- Certificate revocation lists (CRL); to block a client for now, remove its grants or renew the certificates with a new CA.
- Distributing partitions to other nodes.