Multi-Model Database

    Deploying SurrealDB on RamNode VPS

    SurrealDB is a next-generation multi-model database combining relational, document, and graph databases with real-time queries and advanced security—all built in Rust for performance.

    Ubuntu 22.04 LTS
    Docker or Native
    ⏱️ 20-30 minutes

    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 CaseRAMStorageNotes
    Development2GB20GB SSDSmall projects & testing
    Production4GB+50GB+ SSDProduction 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)

    2

    Install Docker

    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 docker
    3

    Create Directory Structure

    Create Directories
    sudo mkdir -p /opt/surrealdb/{data,logs,backups}
    sudo chown -R $USER:$USER /opt/surrealdb
    4

    Create Docker Compose Configuration

    Create docker-compose.yml
    nano /opt/surrealdb/docker-compose.yml
    docker-compose.yml
    version: '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: 40s
    5

    Configure Environment Variables

    Create .env file
    nano /opt/surrealdb/.env
    .env
    SURREAL_ROOT_PASSWORD=your_secure_password_here
    Secure the environment file
    chmod 600 /opt/surrealdb/.env
    6

    Launch SurrealDB

    Start SurrealDB
    cd /opt/surrealdb
    docker compose up -d
    Verify Deployment
    docker 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

    7

    Install SurrealDB Binary

    Install SurrealDB
    # Download and install the latest version
    curl -sSf https://install.surrealdb.com | sh
    
    # Verify installation
    surreal version
    8

    Create System User and Directories

    Setup User & 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/surrealdb
    9

    Create Configuration File

    Create config.env
    sudo nano /etc/surrealdb/config.env
    config.env
    SURREAL_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:8000
    Secure Configuration
    sudo chmod 600 /etc/surrealdb/config.env
    sudo chown surrealdb:surrealdb /etc/surrealdb/config.env
    10

    Create Systemd Service

    Create Service File
    sudo nano /etc/systemd/system/surrealdb.service
    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.target
    Enable and Start Service
    sudo systemctl daemon-reload
    sudo systemctl enable surrealdb
    sudo systemctl start surrealdb
    sudo systemctl status surrealdb
    11

    Nginx Reverse Proxy (Production)

    For production deployments, place SurrealDB behind Nginx with SSL/TLS encryption.

    Install Nginx & Certbot
    sudo apt update
    sudo apt install -y nginx certbot python3-certbot-nginx
    Create Nginx Configuration
    sudo nano /etc/nginx/sites-available/surrealdb
    surrealdb nginx config
    upstream 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 & Get SSL Certificate
    # 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.com
    12

    Firewall Configuration

    Configure UFW
    # 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 status
    13

    Connecting to SurrealDB

    Using the CLI

    Install CLI & Connect
    # 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 test

    Using HTTP API

    Create a Record via 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/john
    14

    Basic Usage Examples

    Creating a Schema

    SurrealQL 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

    Insert Records
    -- 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

    Query Examples
    -- 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;
    15

    Backup Strategies

    Backup Script

    surrealdb-backup.sh
    #!/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"
    Setup Automated Backups
    # 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>&1

    Export/Import Using CLI

    Export & Import
    # 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.surql
    16

    Performance Tuning

    Docker Resource Limits

    docker-compose.yml (add to service)
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 4G
        reservations:
          cpus: '1'
          memory: 2G
    Optimization 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)
    17

    Security Hardening

    Define Users with Specific Permissions

    User & Permission Setup
    -- 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
    18

    Troubleshooting

    Connection Issues

    Diagnose Connection
    # 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/health

    Performance Issues

    Analyze Query Performance
    -- 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

    Debug Container
    # 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 -d

    Setup 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