# SurrealDB 2.3 Setup & Deployment Guide **Version**: 2.3 **Status**: Production Ready **Last Updated**: November 15, 2025 --- ## Overview This guide covers deploying and configuring SurrealDB 2.3 for the syntaxis project in three deployment contexts: 1. **Local Development** - Server mode for development/testing 2. **Docker Container** - Production containerized deployment 3. **Kubernetes** - Enterprise orchestration with HA/scaling --- ## Part 1: Local Development Setup ### 1.1 Install SurrealDB #### macOS (via Homebrew) ```bash brew install surrealdb # Verify installation surreal version # Output: surrealdb version X.X.X ``` #### Linux (via Cargo) ```bash cargo install surreal # Or download binary from https://github.com/surrealdb/surrealdb/releases ``` #### Windows (via Chocolatey) ```powershell choco install surrealdb ``` ### 1.2 Start SurrealDB Server (Local Development) #### Basic In-Memory Server ```bash # Start SurrealDB listening on localhost:8000 surreal start --bind 127.0.0.1:8000 memory # Surreal outputs: # 2025-11-15T10:00:00.000Z INFO surreal::cli: Starting SurrealDB server... # 2025-11-15T10:00:00.123Z INFO surreal::net: Database server now listening on 0.0.0.0:8000 ``` #### File-Based RocksDB Server ```bash # Persistent storage in local directory surreal start --bind 127.0.0.1:8000 file:///tmp/surrealdb.db # Or with expanded home path surreal start --bind 127.0.0.1:8000 file://~/.local/share/surrealdb/workspace.db ``` #### With Authentication ```bash # Start with credentials (recommended for production-like testing) surreal start \ --bind 127.0.0.1:8000 \ --username admin \ --password secure_password_123 \ file:///tmp/surrealdb.db ``` ### 1.3 Configure Application to Connect **Configuration File**: `configs/database.toml` ```toml # Database Configuration - syntaxis engine = "surrealdb" # or "sqlite" for testing # SQLite Configuration (Default for development) [sqlite] path = "~/.local/share/core/workspace.db" max_connections = 5 timeout_secs = 30 wal_mode = true pragma_synchronous = "NORMAL" pragma_cache_size = 2000 # SurrealDB Configuration (Optional - requires server running) [surrealdb] # Connection modes (choose one) # In-Memory (embedded, no server needed): url = "mem://" # File-based (embedded RocksDB, no server needed): # url = "file:///tmp/surrealdb.db" # Remote Server (requires surreal start): url = "ws://localhost:8000" # Optional: ws:// for WebSocket or http:// for HTTP # url = "http://localhost:8000" # Namespace and Database selection namespace = "syntaxis" database = "projects" # Authentication (if server started with --username/--password) # username = "admin" # password = "secure_password_123" # Connection pooling max_connections = 10 timeout_secs = 30 # TLS Configuration (for production) # tls_enabled = true # tls_ca_cert = "/path/to/ca.pem" # tls_client_cert = "/path/to/client.pem" # tls_client_key = "/path/to/client.key" ``` ### 1.4 Enable SurrealDB in Application **In Rust Code** (syntaxis-core): ```rust use workspace_core::persistence::{Database, SurrealDatabase}; #[tokio::main] async fn main() -> Result<()> { // Embedded mode (no server required) let db = SurrealDatabase::new_memory().await?; // or let db = SurrealDatabase::new_file("/tmp/surrealdb.db").await?; // Server mode (requires `surreal start` running) // let db = SurrealDatabase::new_server( // "ws://localhost:8000", // "syntaxis", // "projects", // None, // username // None, // password // ).await?; Ok(()) } ``` ### 1.5 Verify Connection ```bash # Test if server is running curl http://localhost:8000/health # Expected: {"status":"ok"} # Check with surreal CLI surreal sql --endpoint ws://localhost:8000 # Then at prompt: # > SELECT 1; ``` --- ## Part 2: Docker Container Deployment ### 2.1 Create Dockerfile **File**: `Dockerfile.surrealdb` ```dockerfile # Multi-stage build for minimal image size FROM surrealdb/surrealdb:latest AS surrealdb # Production runtime image FROM debian:bookworm-slim # Install minimal dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ curl \ && rm -rf /var/lib/apt/lists/* # Copy SurrealDB binary from builder COPY --from=surrealdb /usr/local/bin/surreal /usr/local/bin/surreal # Create data directory RUN mkdir -p /data && chmod 755 /data # Health check HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ CMD curl -f http://localhost:8000/health || exit 1 # Expose port EXPOSE 8000 # Labels for container metadata LABEL maintainer="syntaxis" LABEL version="2.3" LABEL description="SurrealDB 2.3 for syntaxis" # Run SurrealDB ENTRYPOINT ["surreal", "start"] CMD ["--bind", "0.0.0.0:8000", "file:///data/surrealdb.db"] # Volume for data persistence VOLUME ["/data"] ``` ### 2.2 Docker Compose Configuration **File**: `docker-compose.surrealdb.yml` ```yaml version: "3.9" services: surrealdb: # Option 1: Use official SurrealDB image image: surrealdb/surrealdb:latest # Option 2: Build from local Dockerfile # build: # context: . # dockerfile: Dockerfile.surrealdb container_name: workspace-surrealdb # Port mapping ports: - "8000:8000" # Volume for persistent data volumes: - surrealdb-data:/data # Environment variables environment: # SURREAL_LOG: debug # Enable debug logging TZ: UTC # Command override command: - start - --bind - "0.0.0.0:8000" - --username - "admin" - --password - "workspace_password_123" - file:///data/surrealdb.db # Resource limits deploy: resources: limits: cpus: "2" memory: 2G reservations: cpus: "1" memory: 1G # Restart policy restart: unless-stopped # Health check healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/health"] interval: 30s timeout: 10s retries: 3 start_period: 5s # Network networks: - workspace-net # Optional: Redis cache layer (for performance) redis: image: redis:7-alpine container_name: workspace-redis ports: - "6379:6379" volumes: - redis-data:/data restart: unless-stopped networks: - workspace-net volumes: surrealdb-data: driver: local redis-data: driver: local networks: workspace-net: driver: bridge ``` ### 2.3 Docker Compose Usage ```bash # Start SurrealDB docker-compose -f docker-compose.surrealdb.yml up -d # View logs docker-compose -f docker-compose.surrealdb.yml logs -f surrealdb # Connect to database docker-compose -f docker-compose.surrealdb.yml exec surrealdb \ surreal sql --endpoint ws://localhost:8000 \ --username admin \ --password workspace_password_123 # Stop services docker-compose -f docker-compose.surrealdb.yml down # Remove volumes (caution: deletes data) docker-compose -f docker-compose.surrealdb.yml down -v ``` ### 2.4 Multi-Environment Compose Override **File**: `docker-compose.override.yml` (local development) ```yaml version: "3.9" services: surrealdb: # Expose debug port ports: - "8000:8000" - "8001:8001" # Debug port # Use memory backend for faster development command: - start - --bind - "0.0.0.0:8000" - memory # Less resource restriction for dev deploy: resources: limits: cpus: "4" memory: 4G ``` **File**: `docker-compose.prod.yml` (production) ```yaml version: "3.9" services: surrealdb: image: surrealdb/surrealdb:2.3.0 # Pin version for prod # Stricter resource limits deploy: resources: limits: cpus: "1" memory: 1.5G reservations: cpus: "0.5" memory: 1G # Stricter restart policy restart: on-failure:5 ``` --- ## Part 3: Kubernetes Deployment ### 3.1 Kubernetes ConfigMap **File**: `k8s/surrealdb-config.yaml` ```yaml apiVersion: v1 kind: ConfigMap metadata: name: surrealdb-config namespace: workspace spec: database.toml: | engine = "surrealdb" [surrealdb] url = "ws://surrealdb:8000" namespace = "syntaxis" database = "projects" max_connections = 20 timeout_secs = 60 init-schema.sql: | -- SurrealDB schema initialization DEFINE TABLE projects SCHEMAFULL; DEFINE TABLE checklist_items SCHEMAFULL; DEFINE TABLE phase_transitions SCHEMAFULL; DEFINE TABLE security_assessments SCHEMAFULL; DEFINE TABLE phase_history SCHEMAFULL; DEFINE TABLE tool_configurations SCHEMAFULL; DEFINE TABLE tool_dependencies SCHEMAFULL; DEFINE TABLE security_assessment_details SCHEMAFULL; DEFINE TABLE team_members SCHEMAFULL; ``` ### 3.2 Kubernetes Secret **File**: `k8s/surrealdb-secret.yaml` ```yaml apiVersion: v1 kind: Secret metadata: name: surrealdb-credentials namespace: workspace type: Opaque stringData: username: "admin" password: "secure_kubernetes_password_here_at_least_32_chars_minimum" # Note: In production, use external secret management (Vault, AWS Secrets Manager, etc) ``` ### 3.3 SurrealDB StatefulSet **File**: `k8s/surrealdb-statefulset.yaml` ```yaml apiVersion: apps/v1 kind: StatefulSet metadata: name: surrealdb namespace: workspace labels: app: surrealdb version: "2.3" spec: serviceName: surrealdb replicas: 1 # For HA, scale to 3 with clustering (future) selector: matchLabels: app: surrealdb template: metadata: labels: app: surrealdb version: "2.3" spec: # Node affinity for stability affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 preference: matchExpressions: - key: node-type operator: In values: ["database"] # Security context securityContext: runAsNonRoot: true runAsUser: 999 fsGroup: 999 # Init containers for schema setup initContainers: - name: init-schema image: surrealdb/surrealdb:2.3 command: - /bin/sh - -c - | # Wait for SurrealDB to be ready surreal sql \ --endpoint ws://localhost:8000 \ --username admin \ --password $SURREALDB_PASSWORD \ < /config/init-schema.sql env: - name: SURREALDB_PASSWORD valueFrom: secretKeyRef: name: surrealdb-credentials key: password volumeMounts: - name: config mountPath: /config containers: - name: surrealdb image: surrealdb/surrealdb:2.3 imagePullPolicy: IfNotPresent # Resource requests and limits resources: requests: cpu: "500m" memory: "512Mi" limits: cpu: "2000m" memory: "2Gi" # Port exposure ports: - name: http containerPort: 8000 protocol: TCP # Environment variables env: - name: SURREALDB_USER valueFrom: secretKeyRef: name: surrealdb-credentials key: username - name: SURREALDB_PASS valueFrom: secretKeyRef: name: surrealdb-credentials key: password # Startup probe (for slow startup) startupProbe: httpGet: path: /health port: 8000 initialDelaySeconds: 5 periodSeconds: 10 timeoutSeconds: 5 successThreshold: 1 failureThreshold: 30 # Liveness probe livenessProbe: httpGet: path: /health port: 8000 initialDelaySeconds: 10 periodSeconds: 30 timeoutSeconds: 5 successThreshold: 1 failureThreshold: 3 # Readiness probe readinessProbe: httpGet: path: /health port: 8000 initialDelaySeconds: 5 periodSeconds: 10 timeoutSeconds: 5 successThreshold: 1 failureThreshold: 3 # Volume mounts volumeMounts: - name: config mountPath: /etc/surrealdb - name: data mountPath: /data # Security context for container securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: - ALL # Startup command args: - start - --bind - 0.0.0.0:8000 - --username - $(SURREALDB_USER) - --password - $(SURREALDB_PASS) - file:///data/surrealdb.db # Volumes volumes: - name: config configMap: name: surrealdb-config # Persistent volume claim volumeClaimTemplates: - metadata: name: data spec: accessModes: ["ReadWriteOnce"] storageClassName: standard # Change to appropriate storage class resources: requests: storage: 10Gi # Adjust based on data needs ``` ### 3.4 Kubernetes Service **File**: `k8s/surrealdb-service.yaml` ```yaml --- # Headless service for StatefulSet apiVersion: v1 kind: Service metadata: name: surrealdb namespace: workspace labels: app: surrealdb spec: clusterIP: None # Headless service selector: app: surrealdb ports: - name: http port: 8000 targetPort: 8000 protocol: TCP --- # Load balancer service for external access (optional) apiVersion: v1 kind: Service metadata: name: surrealdb-lb namespace: workspace labels: app: surrealdb spec: type: LoadBalancer selector: app: surrealdb ports: - name: http port: 8000 targetPort: 8000 protocol: TCP --- # ClusterIP for internal access apiVersion: v1 kind: Service metadata: name: surrealdb-internal namespace: workspace labels: app: surrealdb spec: type: ClusterIP selector: app: surrealdb ports: - name: http port: 8000 targetPort: 8000 protocol: TCP ``` ### 3.5 Kubernetes Deployment Script **File**: `k8s/deploy.sh` ```bash #!/bin/bash set -e NAMESPACE="workspace" CONTEXT="kubernetes-cluster" # Change to your context echo "📦 Deploying SurrealDB to Kubernetes..." # Switch context kubectl config use-context $CONTEXT echo "✓ Using context: $CONTEXT" # Create namespace if needed kubectl create namespace $NAMESPACE --dry-run=client -o yaml | kubectl apply -f - echo "✓ Namespace: $NAMESPACE" # Apply resources echo "📝 Applying ConfigMap..." kubectl apply -f k8s/surrealdb-config.yaml echo "🔐 Applying Secrets..." kubectl apply -f k8s/surrealdb-secret.yaml echo "📊 Applying StatefulSet..." kubectl apply -f k8s/surrealdb-statefulset.yaml echo "🌐 Applying Services..." kubectl apply -f k8s/surrealdb-service.yaml # Wait for rollout echo "⏳ Waiting for SurrealDB to be ready..." kubectl rollout status statefulset/surrealdb -n $NAMESPACE --timeout=5m # Verify echo "✓ Checking pod status..." kubectl get pods -n $NAMESPACE -l app=surrealdb echo "✓ Checking services..." kubectl get svc -n $NAMESPACE -l app=surrealdb echo "" echo "🎉 SurrealDB deployed successfully!" echo "" echo "Access information:" echo " Internal: ws://surrealdb:8000" echo " External: kubectl port-forward -n $NAMESPACE svc/surrealdb-lb 8000:8000" echo "" echo "To connect:" echo " kubectl -n $NAMESPACE exec -it surrealdb-0 -- surreal sql" ``` ### 3.6 Kubernetes Values for Helm (Optional) **File**: `k8s/helm-values.yaml` (if using Helm) ```yaml # SurrealDB Helm Chart Values # Install: helm install surrealdb surrealdb/surrealdb -f helm-values.yaml replicaCount: 1 image: repository: surrealdb/surrealdb pullPolicy: IfNotPresent tag: "2.3" imagePullSecrets: [] nameOverride: "" fullnameOverride: "" serviceAccount: create: true annotations: {} name: "surrealdb" podAnnotations: {} podSecurityContext: runAsNonRoot: true runAsUser: 999 fsGroup: 999 securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: - ALL service: type: ClusterIP port: 8000 resources: limits: cpu: 2000m memory: 2Gi requests: cpu: 500m memory: 512Mi persistence: enabled: true storageClassName: standard size: 10Gi path: /data auth: username: admin password: "secure_password_here" config: namespace: "syntaxis" database: "projects" logLevel: info ``` --- ## Part 4: Production Considerations ### 4.1 High Availability Setup ```yaml # For HA, scale replicas to 3 and configure clustering # k8s/surrealdb-statefulset.yaml (updated for HA) spec: replicas: 3 # Scale to 3 nodes # In container args, add clustering: args: - start - --bind - 0.0.0.0:8000 - --auth - enable - --log - debug - --clock - "2ms" # Clock precision for clustering # Enable clustering for multi-node setup # Note: Requires SurrealDB enterprise or cloud version ``` ### 4.2 Backup and Recovery ```bash # Backup SurrealDB data kubectl -n workspace exec surrealdb-0 -- \ tar czf /tmp/backup.tar.gz /data/ # Extract backup kubectl -n workspace cp surrealdb-0:/tmp/backup.tar.gz ./backup.tar.gz # Restore from backup kubectl -n workspace cp backup.tar.gz surrealdb-0:/tmp/ kubectl -n workspace exec surrealdb-0 -- \ tar xzf /tmp/backup.tar.gz -C / ``` ### 4.3 Monitoring and Logging ```yaml # Prometheus ServiceMonitor (if using Prometheus) apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: surrealdb namespace: workspace spec: selector: matchLabels: app: surrealdb endpoints: - port: http interval: 30s path: /metrics ``` ### 4.4 Network Security ```yaml # NetworkPolicy to restrict access apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: surrealdb-netpol namespace: workspace spec: podSelector: matchLabels: app: surrealdb policyTypes: - Ingress - Egress ingress: - from: - podSelector: matchLabels: app: workspace-app ports: - protocol: TCP port: 8000 egress: - to: - podSelector: {} ports: - protocol: TCP port: 53 # DNS ``` --- ## Part 5: Troubleshooting ### Issue: Connection Refused **Error**: `connection refused` when connecting to localhost:8000 **Solution**: ```bash # Check if SurrealDB is running ps aux | grep surreal # If not running, start it surreal start --bind 127.0.0.1:8000 memory # Test connection curl http://localhost:8000/health ``` ### Issue: Permission Denied in Docker **Error**: `permission denied` when accessing `/data` **Solution**: ```bash # Fix file permissions docker-compose exec surrealdb chmod 755 /data docker-compose exec surrealdb chown -R 999:999 /data ``` ### Issue: Kubernetes Pod CrashLoopBackOff **Error**: Pod keeps restarting **Solution**: ```bash # Check logs kubectl logs -n workspace surrealdb-0 --previous # Check events kubectl describe pod -n workspace surrealdb-0 # Common causes: # 1. Credentials incorrect in secret # 2. PVC not available # 3. Insufficient resources ``` ### Issue: Slow Queries **Solution**: ```bash # Enable query logging surreal start --log debug --bind 127.0.0.1:8000 file:///tmp/surrealdb.db # Check query performance in logs # Optimize indexes if needed ``` --- ## Summary ### Quick Start **Local Development**: ```bash # Terminal 1: Start SurrealDB surreal start --bind 127.0.0.1:8000 memory # Terminal 2: Run your application cargo run -p syntaxis-cli ``` **Docker Development**: ```bash docker-compose -f docker-compose.surrealdb.yml up -d # Update configs/database.toml to use: # url = "ws://localhost:8000" ``` **Kubernetes Production**: ```bash cd k8s ./deploy.sh # Access: kubectl port-forward -n workspace svc/surrealdb 8000:8000 ``` --- ## References - [SurrealDB Official Docs](https://surrealdb.com/docs) - [SurrealDB Docker Hub](https://hub.docker.com/r/surrealdb/surrealdb) - [Kubernetes Documentation](https://kubernetes.io/docs/) - [syntaxis PERSISTENCE_QUICK_START.md](PERSISTENCE_QUICK_START.md) - [SURREALDB_2_3_MIGRATION.md](SURREALDB_2_3_MIGRATION.md) --- **Last Updated**: November 15, 2025 **Version**: SurrealDB 2.3 **Status**: Production Ready