Why SurrealDB?
Multi-model Flexibility
Documents, graphs, key-value, and tables
Real-time Queries
Built-in WebSocket support for live subscriptions
Advanced Permissions
Fine-grained, row-level security
ACID Compliance
Full transactional support across all models
Horizontal Scalability
Designed for distributed deployments
Modern Query Language
SurrealQL extends SQL with graph traversal
Recommended VPS Specifications
| Use Case | RAM | Storage | Notes |
|---|---|---|---|
| Development | 2GB | 20GB SSD | Small projects & testing |
| Production | 4GB+ | 50GB+ SSD | Production workloads |
Prerequisites
Before starting, ensure you have:
System Requirements
- • RamNode VPS with at least 2GB RAM
- • Ubuntu 22.04 LTS or newer
- • Root or sudo access
- • SSH client installed locally
Optional
- • Domain name for SSL configuration
- • Basic Linux command line familiarity
Method 1: Docker Deployment (Recommended)
Install Docker
# Update package index
sudo apt update
# Install required packages
sudo apt install -y apt-transport-https ca-certificates curl software-properties-common
# Add Docker's official GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# Add Docker repository
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Install Docker
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
# Add your user to docker group (optional)
sudo usermod -aG docker $USER
newgrp dockerCreate Directory Structure
sudo mkdir -p /opt/surrealdb/{data,logs,backups}
sudo chown -R $USER:$USER /opt/surrealdbCreate Docker Compose Configuration
nano /opt/surrealdb/docker-compose.ymlversion: '3.8'
services:
surrealdb:
image: surrealdb/surrealdb:latest
container_name: surrealdb
restart: unless-stopped
ports:
- "8000:8000"
volumes:
- ./data:/data
- ./logs:/logs
command: >
start
--log trace
--user root
--pass ${SURREAL_ROOT_PASSWORD}
file:/data/database.db
environment:
- SURREAL_ROOT_PASSWORD=${SURREAL_ROOT_PASSWORD}
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40sConfigure Environment Variables
nano /opt/surrealdb/.envSURREAL_ROOT_PASSWORD=your_secure_password_herechmod 600 /opt/surrealdb/.envLaunch SurrealDB
cd /opt/surrealdb
docker compose up -ddocker compose ps
docker compose logs -f surrealdb
# Test health endpoint
curl http://localhost:8000/health✓ You should see a JSON response indicating the server is healthy.
Method 2: Native Installation
Install SurrealDB Binary
# Download and install the latest version
curl -sSf https://install.surrealdb.com | sh
# Verify installation
surreal versionCreate System User and Directories
# Create a dedicated user for SurrealDB
sudo useradd -r -s /bin/false -d /var/lib/surrealdb surrealdb
# Create necessary directories
sudo mkdir -p /var/lib/surrealdb/{data,logs}
sudo mkdir -p /etc/surrealdb
sudo chown -R surrealdb:surrealdb /var/lib/surrealdbCreate Configuration File
sudo nano /etc/surrealdb/config.envSURREAL_USER=root
SURREAL_PASS=your_secure_password_here
SURREAL_PATH=file:/var/lib/surrealdb/data/database.db
SURREAL_LOG=info
SURREAL_BIND=127.0.0.1:8000sudo chmod 600 /etc/surrealdb/config.env
sudo chown surrealdb:surrealdb /etc/surrealdb/config.envCreate Systemd Service
sudo nano /etc/systemd/system/surrealdb.service[Unit]
Description=SurrealDB Database Server
After=network.target
Documentation=https://surrealdb.com/docs
[Service]
Type=simple
User=surrealdb
Group=surrealdb
EnvironmentFile=/etc/surrealdb/config.env
ExecStart=/usr/local/bin/surreal start \
--log ${SURREAL_LOG} \
--user ${SURREAL_USER} \
--pass ${SURREAL_PASS} \
--bind ${SURREAL_BIND} \
${SURREAL_PATH}
Restart=always
RestartSec=10
StandardOutput=append:/var/lib/surrealdb/logs/surrealdb.log
StandardError=append:/var/lib/surrealdb/logs/surrealdb-error.log
# Security hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/surrealdb
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reload
sudo systemctl enable surrealdb
sudo systemctl start surrealdb
sudo systemctl status surrealdbNginx Reverse Proxy (Production)
For production deployments, place SurrealDB behind Nginx with SSL/TLS encryption.
sudo apt update
sudo apt install -y nginx certbot python3-certbot-nginxsudo nano /etc/nginx/sites-available/surrealdbupstream surrealdb {
server 127.0.0.1:8000;
keepalive 64;
}
server {
listen 80;
server_name db.yourdomain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name db.yourdomain.com;
# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
# Logging
access_log /var/log/nginx/surrealdb-access.log;
error_log /var/log/nginx/surrealdb-error.log;
# Timeouts for long-running queries
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
location / {
proxy_pass http://surrealdb;
proxy_http_version 1.1;
# WebSocket support
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Standard proxy headers
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Disable buffering for real-time queries
proxy_buffering off;
}
}# Enable the site
sudo ln -s /etc/nginx/sites-available/surrealdb /etc/nginx/sites-enabled/
# Test configuration
sudo nginx -t
# Reload Nginx
sudo systemctl reload nginx
# Obtain SSL certificate
sudo certbot --nginx -d db.yourdomain.comFirewall Configuration
# Enable UFW if not already enabled
sudo ufw enable
# Allow SSH (important!)
sudo ufw allow 22/tcp
# Allow HTTP and HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# If not using Nginx reverse proxy, allow SurrealDB directly
# sudo ufw allow 8000/tcp
# Check status
sudo ufw statusConnecting to SurrealDB
Using the CLI
# Install CLI if not already installed
curl -sSf https://install.surrealdb.com | sh
# Local connection
surreal sql --endpoint http://localhost:8000 --username root --password your_password --namespace test --database test
# Remote connection with SSL
surreal sql --endpoint https://db.yourdomain.com --username root --password your_password --namespace test --database testUsing HTTP API
curl -X POST \
-H "Accept: application/json" \
-H "NS: test" \
-H "DB: test" \
-u "root:your_password" \
-d '{"name": "John Doe", "email": "john@example.com"}' \
http://localhost:8000/key/users/johnBasic Usage Examples
Creating a Schema
-- Define a person table with schema
DEFINE TABLE person SCHEMAFULL;
-- Define fields with types and constraints
DEFINE FIELD name ON TABLE person TYPE string;
DEFINE FIELD email ON TABLE person TYPE string
ASSERT string::is::email($value);
DEFINE FIELD age ON TABLE person TYPE int
ASSERT $value > 0 AND $value < 150;
DEFINE FIELD created_at ON TABLE person TYPE datetime
DEFAULT time::now();
-- Define an index
DEFINE INDEX idx_email ON TABLE person COLUMNS email UNIQUE;Inserting Data
-- Create a single record
CREATE person SET
name = "Jane Smith",
email = "jane@example.com",
age = 28;
-- Create multiple records
INSERT INTO person [
{ name: "Alice Johnson", email: "alice@example.com", age: 32 },
{ name: "Bob Wilson", email: "bob@example.com", age: 45 }
];Querying Data
-- Select all records
SELECT * FROM person;
-- Filter with WHERE
SELECT * FROM person WHERE age > 30;
-- Order and limit
SELECT * FROM person ORDER BY age DESC LIMIT 10;
-- Aggregate functions
SELECT count(), math::mean(age) as avg_age FROM person;Backup Strategies
Backup Script
#!/bin/bash
# Configuration
BACKUP_DIR="/opt/surrealdb/backups"
DATA_DIR="/var/lib/surrealdb/data" # Adjust based on your installation
RETENTION_DAYS=7
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
# Create backup directory if it doesn't exist
mkdir -p "$BACKUP_DIR"
# Create backup
echo "Creating backup: surrealdb_backup_$TIMESTAMP.tar.gz"
tar -czf "$BACKUP_DIR/surrealdb_backup_$TIMESTAMP.tar.gz" -C "$DATA_DIR" .
# Remove old backups
find "$BACKUP_DIR" -name "surrealdb_backup_*.tar.gz" -mtime +$RETENTION_DAYS -delete
echo "Backup completed successfully"# Make executable
sudo chmod +x /usr/local/bin/surrealdb-backup.sh
# Edit crontab for daily backup at 2 AM
crontab -e
# Add this line:
0 2 * * * /usr/local/bin/surrealdb-backup.sh >> /var/log/surrealdb-backup.log 2>&1Export/Import Using CLI
# Export database
surreal export \
--endpoint http://localhost:8000 \
--username root \
--password your_password \
--namespace test \
--database test \
/opt/surrealdb/backups/export_$(date +%Y%m%d).surql
# Import database
surreal import \
--endpoint http://localhost:8000 \
--username root \
--password your_password \
--namespace test \
--database test \
/opt/surrealdb/backups/export_20240101.surqlPerformance Tuning
Docker Resource Limits
deploy:
resources:
limits:
cpus: '2'
memory: 4G
reservations:
cpus: '1'
memory: 2GOptimization Tips
- Use TiKV for distributed deployments at scale
- Create indexes on frequently queried fields
- Monitor resource usage with htop and iotop
- Enable query caching (automatic in SurrealDB)
Security Hardening
Define Users with Specific Permissions
-- Define a user with specific permissions
DEFINE USER developer ON DATABASE PASSWORD 'strong_password_here'
ROLES EDITOR;
-- Define scoped authentication
DEFINE SCOPE user_scope SESSION 24h
SIGNIN (
SELECT * FROM user WHERE email = $email AND crypto::argon2::compare(password, $password)
)
SIGNUP (
CREATE user SET email = $email, password = crypto::argon2::generate($password)
);
-- Implement Row-Level Security
DEFINE TABLE article SCHEMALESS
PERMISSIONS
FOR select WHERE published = true OR author = $auth.id
FOR create, update WHERE $auth.id != NONE
FOR delete WHERE author = $auth.id;Security Best Practices
- Always use SSL/TLS encryption in production
- Use strong passwords and token-based authentication
- Implement row-level security for multi-tenant apps
- Keep SurrealDB updated regularly
- Use firewall rules to restrict access
Troubleshooting
Connection Issues
# Check if service is running
docker compose ps # For Docker
sudo systemctl status surrealdb # For native
# Check if port is listening
sudo netstat -tlnp | grep 8000
# Check firewall rules
sudo ufw status
# Test local connectivity
curl http://localhost:8000/healthPerformance Issues
-- Analyze query execution
EXPLAIN SELECT * FROM person WHERE age > 30;
-- Check if indexes exist
INFO FOR TABLE person;
-- Add appropriate indexes
DEFINE INDEX idx_age ON TABLE person COLUMNS age;Docker Container Crashes
# Check container logs for errors
docker compose logs surrealdb
# Verify resource availability
docker stats
# Check disk space
df -h
# Restart with fresh logs
docker compose down
docker compose up -dSetup Complete!
SurrealDB offers a powerful, modern approach to database management that combines the best features of multiple database paradigms. Whether you chose Docker or native installation, you now have a robust foundation for your applications.
Key Takeaways:
- Docker deployment offers the fastest path to production with easy updates
- Native installation provides more control and tighter system integration
- Always use SSL/TLS encryption and strong authentication in production
- Implement regular backup strategies appropriate for your use case
- Start with file-based backend for simplicity, migrate to TiKV for scale
