Skip to content

Products

/

SurrealDS

Node configuration

Available since: v4.0.0

This page is the reference for configuring a SurrealDS node that you run yourself. The Kubernetes operator writes this configuration for you. For a step-by-step setup, see Run SurrealDS on your own machines.

A node is a surreal start process whose datastore path starts with surrealds://:

surreal start --bind 0.0.0.0:8000 "surrealds://?config=/opt/surrealdb/etc/node.json"

The path has four forms:

PathWhat it opens
surrealds://?config=<file>A node described by a JSON configuration file. Use this form for a group.
surrealds://A node described by SURREALDS_* environment variables. SURREALDS_NODE or SURREALDS_CONFIG_FILE must be set.
surrealds://<directory>One node with no peers, that keeps its log in <directory>/log and its pages in <directory>/objects. It creates the database if the directory is empty.
surrealds://memoryOne node with no peers that keeps everything in memory. The data is lost when the process stops.

Put the path in quotes in a shell, because ? and & are special characters.

These options can follow the path, for example surrealds://?config=/opt/surrealdb/etc/node.json&versioned=true:

OptionDefaultMeaning
versionedfalseKeep a window of old versions, so that SELECT ... VERSION works. Without it, a statement that names a version is refused.
config-The configuration file.

With a configuration file or environment variables, the node takes the rest of its settings from there. Options for a single node with no peers, such as sync and create, have no effect on a node that uses a configuration file.

Configure a node with a JSON file, or with environment variables. Do not use both: a node that names a file refuses to start if a configuration variable is also set.

An empty variable is an error, and the node does not use the default for it.

A node of a three-node group needs at least this:

node.json for node 1
{
  "node": {
    "scope": 1,
    "node": 1,
    "zone": "zone-a",
    "storage": { "kind": "disk", "path": "/opt/surrealdb/data/log" },
    "class": { "barrier": true, "cross_zone": true },
    "create": true
  },
  "listen": "0.0.0.0:7400",
  "admin": "0.0.0.0:7401",
  "peers": [
    { "node": 2, "zone": "zone-b", "host": "10.0.0.12", "port": 7400, "server_name": "shale-2", "cert": "/opt/surrealdb/tls/node-2.crt", "admin": "10.0.0.12:7401" },
    { "node": 3, "zone": "zone-c", "host": "10.0.0.13", "port": 7400, "server_name": "shale-3", "cert": "/opt/surrealdb/tls/node-3.crt", "admin": "10.0.0.13:7401" }
  ],
  "tls": {
    "cert": "/opt/surrealdb/tls/node-1.crt",
    "key": "/opt/surrealdb/tls/node-1.key",
    "ca": "/opt/surrealdb/tls/ca.crt"
  },
  "object": {
    "kind": "s3",
    "bucket": "surrealds",
    "prefix": "production",
    "endpoint": "https://s3.example.com",
    "region": "us-east-1"
  }
}

The object store credentials are never in the file. Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY in the node's environment.

JSON fieldVariableDefaultMeaning
scopeSURREALDS_SCOPERequiredThe scope number. Use 1 on every node.
nodeSURREALDS_NODERequiredThis node's id: 1, 2, 3 and so on. Each node in a group has a different id, and an id never changes.
zoneSURREALDS_ZONERequiredThis node's zone label. See Zones.
storageSURREALDS_LOG_PATHRequired in a fileThe commit log: {"kind": "disk", "path": "<directory>"}. The variable takes the directory.
log_syncSURREALDS_LOG_SYNCfullThe barrier for each log write: full, datasync, fsync or none. See Commit log barrier.
classSURREALDS_CLASS_BARRIER and SURREALDS_CLASS_CROSS_ZONENot statedThe durability the group intends: {"barrier": true, "cross_zone": true} states a barriered log and a second copy in another zone. Set both variables or neither.
page_cacheSURREALDS_PAGE_CACHE_PATH and SURREALDS_PAGE_CACHE_BYTESIn memory, 512 MiBA cache of pages from the object store: {"storage": {"kind": "disk", "path": "<directory>"}, "max_bytes": <bytes>}. The directory must not be inside the log directory, or contain it.
object_syncSURREALDS_OBJECT_SYNC_MS{"interval_ms": 60000}How often the sequencer uploads to the object store. The Kubernetes operator uses 5000.
createSURREALDS_CREATEfalseWhether this node may create the database when the object store prefix is empty. Set it on node 1 only. Without it, a node waits for the database to exist.
JSON fieldVariableDefaultMeaning
listenSURREALDS_LISTENNoneThe UDP address for the peer connections, for example 0.0.0.0:7400.
adminSURREALDS_ADMINNoneThe TCP address of the admin endpoint, for example 0.0.0.0:7401. It cannot share an address and port with listen.
admin_tokenSURREALDS_ADMIN_TOKENNoneA bearer token that every admin request must send. Without it, the admin endpoint is open to anyone who can reach it.
peersSURREALDS_PEERSEmptyThe other nodes of the group. See Peers.
tlsSURREALDS_TLS_CERT, SURREALDS_TLS_KEY and SURREALDS_TLS_CANoneThis node's certificate, private key and certificate authority, as file paths. Set all three or none.
objectSURREALDS_OBJECT_*RequiredThe object store. See Object store.
zone_policySURREALDS_ZONE_POLICYmandate-twoWhat the group does without a node in a second zone. See Zone policy.
memory_bytesSURREALDS_MEMORY_BYTESThe process's memory limit, or the machine's total memoryThe memory the node sizes its caches and buffers from. SurrealDB runs in the same process, so you can give the node less than the machine has.

The other fields, such as the lease and timeout settings, have defaults that suit most groups. Do not change them unless SurrealDB support asks you to.

Every node lists every other node of the group. A node does not list itself, and each id appears once.

Peer fieldMeaning
nodeThe peer's node id.
zoneThe peer's zone label. It must match that peer's own zone.
hostThe peer's IP address or DNS name. A name is resolved again while the node runs.
portThe peer's UDP peer port.
server_nameThe name in the peer's certificate: shale-<id>.
certThe path to the peer's certificate file on this machine.
adminOptional. The peer's admin address as host:port.

With SURREALDS_PEERS, write each peer as node:zone:host:port:server_name:cert[:admin_port] and separate peers with commas. This form cannot hold an IPv6 address.

A node with peers must have TLS. It cannot be turned off.

  • All nodes of a group use certificates from one certificate authority.

  • The certificate of node <id> must carry the DNS name shale-<id>, and allow both server and client authentication.

  • The private key must be a PEM file in PKCS#8 format (-----BEGIN PRIVATE KEY-----).

  • Each node needs the certificate files of all its peers. A node trusts a peer by that peer's exact certificate, so a new certificate for a node changes its identity for the rest of the group.

The certificate script in Make the TLS certificates creates files in this format.

JSON fieldVariableMeaning
kindSURREALDS_OBJECT_KINDs3 or azure.
bucketSURREALDS_OBJECT_BUCKETThe S3 bucket. Required for s3.
prefixSURREALDS_OBJECT_PREFIXThe key prefix that holds this group's database. Required.
endpointSURREALDS_OBJECT_ENDPOINTThe store's URL. Leave it out for Amazon S3. With an endpoint, the node uses path-style requests, and http:// is allowed.
regionSURREALDS_OBJECT_REGIONThe region.
container, accountSURREALDS_OBJECT_CONTAINER, SURREALDS_OBJECT_ACCOUNTThe Azure container and storage account, for azure.

All nodes of a group must use the same store, bucket and prefix. A prefix holds one database: use a new prefix for a new group, and never point two groups at the same prefix.

The store must support conditional writes with the If-Match and If-None-Match request headers. Amazon S3, Cloudflare R2 and MinIO do. If the store does not compare If-Match correctly, the node's first write to the store fails. A store that compares unquoted If-Match values needs "unquoted_if_match": true.

ValueWithout a node in a second zone
mandate-twoThe group stops serving clients until a node in a second zone is running again. Every acknowledged write is on disks in two zones.
allow-oneWhen no node in another zone is available, the group continues with one copy of the log and accepts writes. It returns to two zones when a node in another zone is available again.

Under both values, the acking witness is never in the same zone as the sequencer. Give each node a different zone label only where the machines do not share a failure, such as one power supply or one network switch.

log_sync sets how each commit log write is made durable.

ValueMeaning
fullDefault. Flushes the file and the disk's write cache. On macOS this is F_FULLFSYNC.
datasyncFlushes the file data. On macOS this is also F_FULLFSYNC.
fsyncCalls fsync. On macOS, fsync does not flush the disk's write cache, so do not use this value on macOS.
noneNo flush. The node refuses this value unless accept_write_loss is true, and acknowledged writes can be lost.

The admin endpoint listens on the admin address.

RouteAnswers
GET /live200 while the node makes progress. 503 only when a restart is the only cure.
GET /ready200 when this node accepts client requests. Otherwise a non-200 status, with the reason in the body and in the X-Shale-Reason header.
GET /statusA JSON document that describes the node. role is sequencer, witness or recovering. owner names the group's sequencer, acker names its acking witness, and class.copies is two-zones when writes go to two zones.
GET /metricsNode metrics in Prometheus format.

Allow the admin port only from the other nodes and from your monitoring hosts, or set admin_token.

The SurrealDB server on port 8000 also answers GET /health, and its GET /ready includes the licence state.

PortProtocolUsed by
The listen port, for example 7400UDPThe other nodes.
The admin port, for example 7401TCPThe other nodes, and your monitoring.
The --bind port, 8000 by defaultTCPClients.

Was this page helpful?