Spectron is designed for Kubernetes. The application tier stores no durable state in-process – memory lives in SurrealDB – so you can run multiple replicas behind a standard Service and scale with a HorizontalPodAutoscaler. SurrealDB is deployed separately as a StatefulSet or managed service.
Secrets
Create a Kubernetes Secret for API keys before deploying any other resources. Never embed secrets directly in manifest files.
apiVersion: v1
kind: Secret
metadata:
name: spectron-secrets
namespace: spectron
type: Opaque
stringData:
OPENAI_API_KEY: "sk-..."
SPECTRON_SURREALDB_PASS: "changeme"Apply it:
kubectl apply -f secret.yamlIn production, use an external secrets manager (AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault) with an operator such as the External Secrets Operator to populate the Secret from your secrets store.
SurrealDB StatefulSet
Deploy SurrealDB as a StatefulSet so that storage is tied to the pod identity. Set workingDir: /data to match the volume mount and SURREAL_PATH: rocksdb://surrealdb so database files land in /data/surrealdb on the persistent volume. RocksDB creates a directory there — not a single database file.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: surrealdb
namespace: spectron
spec:
serviceName: surrealdb
replicas: 1
selector:
matchLabels:
app: surrealdb
template:
metadata:
labels:
app: surrealdb
spec:
containers:
- name: surrealdb
image: surrealdb/surrealdb:latest
workingDir: /data
args:
- start
- --log
- info
- --user
- root
- --pass
- $(SURREALDB_PASS)
env:
- name: SURREALDB_PASS
valueFrom:
secretKeyRef:
name: spectron-secrets
key: SPECTRON_SURREALDB_PASS
- name: SURREAL_PATH
value: rocksdb://surrealdb
ports:
- containerPort: 8000
volumeMounts:
- name: data
mountPath: /data
readinessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 5
periodSeconds: 5
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 50Gi
---
apiVersion: v1
kind: Service
metadata:
name: surrealdb
namespace: spectron
spec:
selector:
app: surrealdb
ports:
- port: 8000
targetPort: 8000
clusterIP: None # headless service for StatefulSetIf SurrealDB fails with Failed to create RocksDB directory or a read-only filesystem error, check that workingDir matches mountPath and that the path slashes are correct — see Docker storage paths.
Spectron Deployment
Spectron uses a Deployment with RollingUpdate because replicas do not hold durable state locally.
apiVersion: apps/v1
kind: Deployment
metadata:
name: spectron
namespace: spectron
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: spectron
template:
metadata:
labels:
app: spectron
spec:
containers:
- name: spectron
image: ghcr.io/surrealdb/spectron:latest
ports:
- containerPort: 9090
env:
- name: SPECTRON_SURREALDB_URL
value: "ws://surrealdb.spectron.svc.cluster.local:8000"
- name: SPECTRON_OBJECT_STORE_URL
value: "s3://my-spectron-bucket/prod?region=eu-west-1"
- name: OPENAI_API_KEY
valueFrom:
secretKeyRef:
name: spectron-secrets
key: OPENAI_API_KEY
livenessProbe:
httpGet:
path: /health
port: 9090
initialDelaySeconds: 10
periodSeconds: 15
failureThreshold: 3
readinessProbe:
httpGet:
path: /health
port: 9090
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 2
resources:
requests:
cpu: "250m"
memory: "256Mi"
limits:
cpu: "1000m"
memory: "1Gi"
---
apiVersion: v1
kind: Service
metadata:
name: spectron
namespace: spectron
spec:
selector:
app: spectron
ports:
- port: 80
targetPort: 9090
type: ClusterIPExpose Spectron externally via an Ingress or LoadBalancer depending on your cluster setup. Ensure TLS termination at the ingress layer.
Horizontal Pod Autoscaler
Spectron scales well on CPU and memory. Configure an HPA to handle traffic spikes:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: spectron
namespace: spectron
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: spectron
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80Namespace
All resources above use the spectron namespace. Create it before applying the manifests:
kubectl create namespace spectronApplying all manifests
kubectl apply -f secret.yaml
kubectl apply -f surrealdb.yaml
kubectl apply -f spectron.yaml
kubectl apply -f hpa.yamlWait for the Spectron pods to reach Running state:
kubectl rollout status deployment/spectron -n spectronFirst-run initialisation
Run the spectron init command inside one of the running pods to create the admin management key:
kubectl exec -n spectron deploy/spectron -- spectron init --admin-keyCopy the printed secret. It is shown only once.
Upgrading
Update the image tag in your Deployment manifest and apply it. The rolling update strategy ensures zero-downtime upgrades. Pending per-Context schema migrations are applied asynchronously by the scheduler and workers — see Migrations and upgrades.
# Update the image tag (replace 0.2.0 with the target version)
kubectl set image deployment/spectron \
spectron=ghcr.io/surrealdb/spectron:0.2.0 -n spectron
kubectl rollout status deployment/spectron -n spectronNext steps
Storage and scaling – object store configuration and scaling advice
Authentication – creating and managing API keys
Observability – monitoring your deployment