Skip to content

Products

Licensing

Available since: v3.3.0

SurrealDB Enterprise, including every SurrealDS node, needs a valid licence key to start. This page explains how to get a key, where to put it, and how a node behaves while it runs.

A licence key is a secret. Anyone who has it can start nodes against your licence, so store it as you store a database password.

SurrealDB issues each licence key. To request one, contact SurrealDB or email sales@surrealdb.com. To issue a key, SurrealDB needs this information:

InformationWhy it is needed
The number of nodes in the clusterThe licence limits how many nodes run at the same time.
The number of CPU cores on each nodeThe licence can limit the cores on one node and the cores across the cluster.
The term you needEach licence has an expiry date.

One licence covers one cluster. If you run a second cluster, such as a staging cluster beside production, request a second licence for it.

When the licence is issued, you receive a licence key as a single string. Keep it in your secret store and supply it to each node as the rest of this page describes.

Each node reads the key once when it starts, from SURREAL_LICENSE_KEY or from SURREAL_LICENSE_KEY_FILE. Set exactly one of these two variables.

VariableValue
SURREAL_LICENSE_KEYThe licence key.
SURREAL_LICENSE_KEY_FILEThe absolute path to a file that contains the key, such as a mounted secret.
SURREAL_LICENSE_STATE_PATHOptional. The absolute path of the attestation cache file. See Starting while the licence service is unreachable.

The node refuses to start if both SURREAL_LICENSE_KEY and SURREAL_LICENSE_KEY_FILE are set, if the key file path is relative, or if the key file is unreadable or empty. Spaces and line breaks around the key are ignored. There is no command-line flag for the licence key.

To change the key, update the variable or the file and restart the node. In a cluster, restart the nodes one at a time.

The Enterprise image is surrealdb/surrealdb-enterprise. Pass the key from your shell, so that it does not appear in the command line:

export SURREAL_LICENSE_KEY='<your-licence-key>'
docker run --rm -p 8000:8000 -e SURREAL_LICENSE_KEY surrealdb/surrealdb-enterprise:latest start --user root --pass secret

-e SURREAL_LICENSE_KEY without a value copies the variable from the shell that runs docker. See Run with Docker.

Write the key to a file that only the service account can read, and point SURREAL_LICENSE_KEY_FILE at it:

sudo mkdir -p /etc/surrealdb
printf '%s\n' '<your-licence-key>' | sudo tee /etc/surrealdb/license.key > /dev/null
sudo chmod 600 /etc/surrealdb/license.key

Then set the variable in the service definition that starts the node:

systemd unit (Linux)
[Service]
Environment=SURREAL_LICENSE_KEY_FILE=/etc/surrealdb/license.key
Environment=SURREAL_LICENSE_STATE_PATH=/var/lib/surrealdb/license-state.json
launchd property list (macOS)
<key>EnvironmentVariables</key>
<dict>
    <key>SURREAL_LICENSE_KEY_FILE</key>
    <string>/etc/surrealdb/license.key</string>
    <key>SURREAL_LICENSE_STATE_PATH</key>
    <string>/var/lib/surrealdb/license-state.json</string>
</dict>

The file must be readable by the user that the node runs as. Run SurrealDS on your own machines shows a complete service definition.

Store the key in a Kubernetes Secret in the namespace of the SurrealDS resource:

kubectl -n <namespace> create secret generic surrealdb-license --from-literal=key='<your-licence-key>'

Then pass it to the nodes through spec.env. The operator has no licence field of its own:

spec:
  env:
    - name: SURREAL_LICENSE_KEY
      valueFrom:
        secretKeyRef:
          name: surrealdb-license
          key: key
    - name: SURREAL_LICENSE_STATE_PATH
      value: /var/lib/shale/license-state.json

The operator does not mount extra volumes into the node pods, so use SURREAL_LICENSE_KEY with a secretKeyRef rather than SURREAL_LICENSE_KEY_FILE. /var/lib/shale is the node's persistent volume, so the attestation cache survives a pod restart there. A change to the Secret does not restart the nodes, so restart them after you rotate the key. See Deploy SurrealDS with the Kubernetes operator.

Each node checks its own licence, without asking the other nodes.

  • At startup, the node validates the key online against the licence service at api.keygen.sh, and checks the signature on the answer against a key built into the binary.

  • While it runs, the node validates again every 30 minutes, with up to 10% random variation, and sends a heartbeat every 15 minutes.

  • Each node counts as one machine against the licence's node limit. A SurrealDS node is identified by its scope and node number, so it keeps the same identity across restarts and machine moves. Any other node is identified by its host name.

Each node needs outbound HTTPS (TCP port 443) to api.keygen.sh. The node connects to it directly, not through a SurrealDB service, and verifies its certificate against the operating system's trusted certificate authorities.

There is no offline or air-gapped licence. A node that has never reached api.keygen.sh cannot start. To run where outbound internet access is not permitted, contact SurrealDB.

With SURREAL_LICENSE_STATE_PATH set, the node stores the last signed answer from the licence service at that path. If the licence service is unreachable at a later start, the node verifies the stored answer again and starts from it, as long as the answer is less than 24 hours old.

  • Put the file on persistent storage. A file in a container's writable layer is lost when the container is recreated.

  • Protect the file. It contains the licence key in plain text. The node creates it with mode 0600.

  • Use an absolute, writable path. A relative path, or a path that the node cannot write, stops the node from starting.

Without the variable there is no cache, and every start needs api.keygen.sh to be reachable. A cache stops being used when the licence key changes, so the first start after a key rotation also needs api.keygen.sh. A machine clock more than one hour behind the time on the stored answer also prevents its use.

Licence stateAt startupOn a running node
ValidStarts.Keeps serving.
No key configuredRefuses to start.-
ExpiredRefuses to start. There is no grace period after the expiry date.Keeps serving and logs a warning. The next start is refused.
Suspended, banned or not foundRefuses to start.After two checks two minutes apart confirm it, /ready returns 503. The process exits with status 3 no sooner than 24 hours later.
Over the node or core limitRefuses to start.Keeps serving and logs a warning, or stops as for a suspended licence if the limit applies to this node.
api.keygen.sh unreachableStarts if the cache holds a valid answer less than 24 hours old. Refuses otherwise.Keeps serving for 24 hours after the last verified answer. Then /ready returns 503, and the process exits with status 3 no sooner than three hours later.

A refused start exits with status 1. A key issued for a different environment is reported as not found.

The 24-hour offline allowance is measured from the time on the licence service's last signed answer, so a restart during an outage continues it and does not start a new one. If the licence is reinstated, or api.keygen.sh becomes reachable again, before the node exits, the node returns to service without a restart.

A 503 from /ready removes the node from a load balancer that checks readiness. Clients that connect to the node directly continue to be served until the process exits.

Note

An attestation cached by v3.3.0-beta.4 is not accepted by v3.3.0 or later, so the first start after that upgrade needs api.keygen.sh to be reachable.

Each node reports its licence state through the surrealdb_license_* gauges on /metrics. An anonymous scrape does not return them. See Licence metrics.

Before the node is ready, its HTTP listener is not open, so a refused start shows only in the exit status and the log. The log message names the cause, for example a missing key or an expired licence.

Was this page helpful?