SurrealDB es una base de datos multimodelo: guarda documentos JSON, permite relaciones de grafo entre registros y se consulta con SurrealQL, un lenguaje parecido a SQL. Un único binario expone una API HTTP y WebSocket en el puerto 8000. En este tutorial instalarás SurrealDB en Ubuntu 24.04, lo ejecutarás como servicio systemd con almacenamiento persistente en RocksDB, crearás un usuario para tu aplicación y probarás consultas de documentos y de grafo.
Requisitos previos
- Un servidor con Ubuntu 24.04 LTS (x86_64 o arm64), por ejemplo un VPS de CubePath.
- Un usuario no root con privilegios
sudo. - Al menos 1 GB de RAM y unos GB libres en disco para los datos.
curlinstalado (sudo apt install curl).
Paso 1: Instalar el binario de SurrealDB
SurrealDB publica un script de instalación que detecta la arquitectura, descarga la última versión estable desde download.surrealdb.com y copia el binario surreal en /usr/local/bin. Descárgalo primero para poder revisarlo antes de ejecutarlo:
curl -sSf https://install.surrealdb.com -o install-surreal.sh
less install-surreal.sh
Ejecútalo con sudo para que pueda escribir en /usr/local/bin:
sudo sh install-surreal.sh
Comprueba la versión instalada:
surreal version
3.3.0 for linux on x86_64
Tu número de versión puede ser más reciente. Si en lugar de /usr/local/bin el script instaló el binario en ~/.surrealdb/surreal, muévelo con sudo mv ~/.surrealdb/surreal /usr/local/bin/.
Paso 2: Crear el usuario del sistema y el directorio de datos
El servicio no debe ejecutarse como root. Crea un usuario de sistema sin shell y el directorio donde RocksDB guardará los datos:
sudo useradd --system --home-dir /var/lib/surrealdb --shell /usr/sbin/nologin surrealdb
sudo install -d -o surrealdb -g surrealdb -m 0750 /var/lib/surrealdb
Paso 3: Guardar las credenciales del usuario root
Al arrancar por primera vez, surreal start crea el usuario root de la base de datos a partir de las variables SURREAL_USER y SURREAL_PASS. Guárdalas en un archivo que solo pueda leer root, en lugar de ponerlas en la línea de comandos donde las vería cualquiera con ps:
sudo nano /etc/surrealdb.env
SURREAL_USER=root
SURREAL_PASS=your_strong_password
SURREAL_BIND=127.0.0.1:8000
SURREAL_PATH=rocksdb:/var/lib/surrealdb/data
SURREAL_LOG=info
Sustituye your_strong_password por una contraseña larga y aleatoria. SURREAL_BIND hace que el servidor escuche solo en localhost; lo abrirás al exterior más adelante si lo necesitas. Protege el archivo:
sudo chmod 600 /etc/surrealdb.env
Notalas credenciales de
SURREAL_USERySURREAL_PASSsolo se usan para crear el root inicial si todavía no existe ninguno. Cambiarlas después en este archivo no cambia la contraseña; para eso usaALTER USERoDEFINE USER OVERWRITEdesde SurrealQL.
Paso 4: Crear el servicio systemd
Crea la unidad del servicio:
sudo nano /etc/systemd/system/surrealdb.service
[Unit]
Description=SurrealDB
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=surrealdb
Group=surrealdb
EnvironmentFile=/etc/surrealdb.env
ExecStart=/usr/local/bin/surreal start
Restart=on-failure
LimitNOFILE=65536
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/var/lib/surrealdb
[Install]
WantedBy=multi-user.target
surreal start lee la ruta de datos, la dirección de escucha y las credenciales de las variables de entorno del archivo anterior. Recarga systemd y arranca el servicio:
sudo systemctl daemon-reload
sudo systemctl enable --now surrealdb
sudo systemctl status surrealdb --no-pager
● surrealdb.service - SurrealDB
Loaded: loaded (/etc/systemd/system/surrealdb.service; enabled; preset: enabled)
Active: active (running) since Fri 2026-09-25 10:12:03 UTC; 4s ago
Comprueba que responde al endpoint de salud:
curl -i http://127.0.0.1:8000/health
HTTP/1.1 200 OK
surreal-version: surrealdb/3.3.0
server: SurrealDB
Si el servicio no arranca, revisa el registro con sudo journalctl -u surrealdb -n 50.
Paso 5: Conectarte con el cliente SQL
SurrealDB organiza los datos en espacios de nombres (namespaces) que contienen bases de datos, y estas contienen tablas. El cliente surreal sql abre una consola interactiva; indica el namespace y la base de datos con --ns y --db (se crean automáticamente al usarlos):
surreal sql -e http://127.0.0.1:8000 -u root -p your_strong_password --ns tienda --db principal --pretty
Verás un prompt como tienda/principal>. Todas las consultas de los pasos siguientes se escriben aquí. Para salir, pulsa Ctrl+C.
Consejosi no quieres que la contraseña quede en el historial de la shell, exporta antes
SURREAL_PASSen la sesión y omite-p; el cliente también lee esa variable.
Paso 6: Definir tablas y crear documentos
Por defecto las tablas son sin esquema (schemaless) y aceptan cualquier campo. Para datos de aplicación suele convenir un esquema estricto con tipos y validaciones. Define una tabla producto con tres campos y un índice único:
DEFINE TABLE producto SCHEMAFULL;
DEFINE FIELD nombre ON producto TYPE string;
DEFINE FIELD precio ON producto TYPE number ASSERT $value >= 0;
DEFINE FIELD etiquetas ON producto TYPE array<string> DEFAULT [];
DEFINE INDEX producto_nombre ON producto FIELDS nombre UNIQUE;
Crea algunos registros. En SurrealDB cada registro tiene un identificador tabla:id, que puedes elegir tú:
CREATE producto:teclado SET nombre = 'Teclado mecánico', precio = 89.9, etiquetas = ['periféricos'];
CREATE producto:raton SET nombre = 'Ratón inalámbrico', precio = 29.5;
CREATE cliente:ana CONTENT { nombre: 'Ana', ciudad: 'Barcelona' };
La tabla cliente no tiene esquema definido, así que acepta el documento tal cual. Consulta los productos baratos:
SELECT nombre, precio FROM producto WHERE precio < 50;
[
{
nombre: 'Ratón inalámbrico',
precio: 29.5f
}
]
Comprueba que la validación funciona intentando guardar un precio negativo:
CREATE producto:erroneo SET nombre = 'Prueba', precio = -1;
'Found -1 for field `precio`, with record `producto:erroneo`, but field must conform to: $value >= 0'
Paso 7: Relacionar registros como un grafo
RELATE crea una arista entre dos registros y la guarda en su propia tabla (aquí compro), que puede tener campos como cualquier otro registro:
RELATE cliente:ana->compro->producto:teclado SET fecha = time::now(), cantidad = 1;
RELATE cliente:ana->compro->producto:raton SET fecha = time::now(), cantidad = 2;
Recorre el grafo con flechas: ->compro->producto sigue las aristas salientes y <-compro<-cliente las entrantes.
SELECT nombre, ->compro->producto.nombre AS compras FROM cliente:ana;
[
{
compras: [
'Ratón inalámbrico',
'Teclado mecánico'
],
nombre: 'Ana'
}
]
SELECT nombre, <-compro<-cliente.nombre AS compradores FROM producto:teclado;
[
{
compradores: [
'Ana'
],
nombre: 'Teclado mecánico'
}
]
Esta es la principal diferencia frente a una base de datos relacional: no necesitas tablas intermedias ni JOIN para seguir relaciones de varios saltos.
Paso 8: Crear un usuario para la aplicación
Tu aplicación no debe usar el root. Crea un usuario limitado a la base de datos principal con el rol EDITOR, que puede leer y escribir datos pero no gestionar usuarios:
DEFINE USER app ON DATABASE PASSWORD 'app_strong_password' ROLES EDITOR;
Los roles disponibles son OWNER, EDITOR y VIEWER. Sal de la consola y conéctate como el nuevo usuario; --auth-level database indica dónde está definido:
surreal sql -e http://127.0.0.1:8000 -u app -p app_strong_password --auth-level database --ns tienda --db principal
SELECT * FROM cliente;
[[{ ciudad: 'Barcelona', id: cliente:ana, nombre: 'Ana' }]]
Paso 9: Consultar la API HTTP
Además de los SDK oficiales (JavaScript, Python, Go, Rust, Java, .NET...), cualquier cliente HTTP puede enviar SurrealQL al endpoint /sql. Las cabeceras surreal-ns y surreal-db eligen el destino, y surreal-auth-ns y surreal-auth-db indican dónde está definido el usuario:
curl -s -X POST -u app:app_strong_password \
-H "surreal-auth-ns: tienda" -H "surreal-auth-db: principal" \
-H "surreal-ns: tienda" -H "surreal-db: principal" \
-H "Accept: application/json" \
-d "SELECT nombre, precio FROM producto ORDER BY precio;" \
http://127.0.0.1:8000/sql
[{"result":[{"nombre":"Ratón inalámbrico","precio":29.5},{"nombre":"Teclado mecánico","precio":89.9}],"status":"OK","time":"725.083µs","type":null}]
Para aplicaciones con sesión es preferible obtener un token JWT con POST /signin y enviarlo como Authorization: Bearer, o usar directamente un SDK por WebSocket, que además permite consultas en tiempo real con LIVE SELECT.
Paso 10: Exponer SurrealDB de forma segura
Mientras solo lo use una aplicación en el mismo servidor, deja SURREAL_BIND=127.0.0.1:8000. Si otras máquinas necesitan conectarse, cambia la dirección a 0.0.0.0:8000 en /etc/surrealdb.env, reinicia el servicio y abre el puerto solo a la IP de confianza (your_app_ip):
sudo systemctl restart surrealdb
sudo ufw allow from your_app_ip to any port 8000 proto tcp
Para tráfico que cruce Internet, pon delante un proxy inverso con TLS (Nginx o Caddy) o usa las opciones --web-crt y --web-key de surreal start para servir HTTPS directamente.
Paso 11: Hacer copias de seguridad
surreal export vuelca una base de datos completa (definiciones y datos) a un archivo SurrealQL, que puedes restaurar con surreal import:
surreal export -e http://127.0.0.1:8000 -u root -p your_strong_password --namespace tienda --database principal tienda-$(date +%F).surql
Para restaurar en una base de datos vacía:
surreal import -e http://127.0.0.1:8000 -u root -p your_strong_password --namespace tienda --database principal tienda-2026-09-25.surql
Programa el export con cron o un temporizador systemd y copia los archivos fuera del servidor.
Solución de problemas
There was a problem with authentication: el usuario está definido en otro nivel. Para usuariosON DATABASEañade--auth-level databaseensurreal sql, o las cabecerassurreal-auth-nsysurreal-auth-dben HTTP.- El root no acepta la nueva contraseña del archivo
.env: el root solo se crea en el primer arranque. Cámbiala desde SurrealQL conALTER USER root ON ROOT PASSWORD 'nueva_password';conectado como root. Permission deniedal arrancar: el directorio de datos debe pertenecer asurrealdb. Revisa conls -ld /var/lib/surrealdby corrige consudo chown -R surrealdb:surrealdb /var/lib/surrealdb.
Conclusión
Tienes SurrealDB funcionando como servicio en Ubuntu 24.04, con datos persistentes en RocksDB, un usuario de aplicación con permisos limitados y consultas de documentos y de grafo probadas desde la consola y la API HTTP. Como siguientes pasos, conecta tu aplicación con el SDK oficial de tu lenguaje, define permisos por tabla con DEFINE TABLE ... PERMISSIONS y automatiza los exports diarios.
