--- title: "Cómo instalar SurrealDB en Ubuntu 24.04 con systemd" description: "Instala SurrealDB en Ubuntu 24.04 como servicio systemd con RocksDB, crea usuarios, modela tablas y relaciones de grafo con SurrealQL y consulta la API HTTP." category: "Bases de Datos Especializadas" language: es source: https://cubepath.com/es/docs/bases-de-datos-especializadas/instalacion-de-surrealdb-base-de-datos-multimodelo updated: 2026-09-25 --- # Cómo instalar SurrealDB en Ubuntu 24.04 con systemd 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. - `curl` instalado (`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: ```bash 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`: ```bash sudo sh install-surreal.sh ``` Comprueba la versión instalada: ```bash surreal version ``` ```output 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: ```bash 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`: ```bash sudo nano /etc/surrealdb.env ``` ```ini 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: ```bash sudo chmod 600 /etc/surrealdb.env ``` > Nota: las credenciales de `SURREAL_USER` y `SURREAL_PASS` solo 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 usa `ALTER USER` o `DEFINE USER OVERWRITE` desde SurrealQL. ## Paso 4: Crear el servicio systemd Crea la unidad del servicio: ```bash sudo nano /etc/systemd/system/surrealdb.service ``` ```ini [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: ```bash sudo systemctl daemon-reload sudo systemctl enable --now surrealdb sudo systemctl status surrealdb --no-pager ``` ```output ● 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: ```bash curl -i http://127.0.0.1:8000/health ``` ```output 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): ```bash 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`. > Consejo: si no quieres que la contraseña quede en el historial de la shell, exporta antes `SURREAL_PASS` en 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: ```sql 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 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ú: ```sql 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: ```sql SELECT nombre, precio FROM producto WHERE precio < 50; ``` ```output [ { nombre: 'Ratón inalámbrico', precio: 29.5f } ] ``` Comprueba que la validación funciona intentando guardar un precio negativo: ```sql CREATE producto:erroneo SET nombre = 'Prueba', precio = -1; ``` ```output '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: ```sql 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. ```sql SELECT nombre, ->compro->producto.nombre AS compras FROM cliente:ana; ``` ```output [ { compras: [ 'Ratón inalámbrico', 'Teclado mecánico' ], nombre: 'Ana' } ] ``` ```sql SELECT nombre, <-compro<-cliente.nombre AS compradores FROM producto:teclado; ``` ```output [ { 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: ```sql 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: ```bash surreal sql -e http://127.0.0.1:8000 -u app -p app_strong_password --auth-level database --ns tienda --db principal ``` ```sql SELECT * FROM cliente; ``` ```output [[{ 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: ```bash 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 ``` ```output [{"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`): ```bash 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`: ```bash 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: ```bash 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 usuarios `ON DATABASE` añade `--auth-level database` en `surreal sql`, o las cabeceras `surreal-auth-ns` y `surreal-auth-db` en 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 con `ALTER USER root ON ROOT PASSWORD 'nueva_password';` conectado como root. - **`Permission denied` al arrancar**: el directorio de datos debe pertenecer a `surrealdb`. Revisa con `ls -ld /var/lib/surrealdb` y corrige con `sudo 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.