Skip to content

Redis Setup

Configure Redis for Mantis cluster coordination, target affinity, and session management.

Redis provides essential services for multi-instance Mantis deployments:

FeatureComponentDescription
Instance RegistryThoraxTrack live Thorax instances
Target AffinityThoraxPrevent duplicate command dispatch
Cluster HealthThoraxHeartbeat coordination
Session ManagementMandibleTrack SSE subscriptions
Token RevocationMandibleJWT blocklist (fail-closed when Redis is down)
RequirementMinimumRecommended
Redis6.07.0+
Memory256 MB1+ GB
StorageOptionalSSD for persistence
Terminal window
# Install Redis
sudo apt update
sudo apt install redis-server -y
# Enable and start
sudo systemctl enable redis-server
sudo systemctl start redis-server
# Verify
redis-cli ping
Terminal window
# Install Redis
sudo dnf install redis -y
# Enable and start
sudo systemctl enable redis
sudo systemctl start redis
# Verify
redis-cli ping
docker-compose.yml
services:
redis:
image: redis:7-alpine
hostname: redis
command: redis-server --appendonly yes
volumes:
- redis_data:/data
ports:
- '6379:6379'
healthcheck:
test: ['CMD', 'redis-cli', 'ping']
interval: 10s
timeout: 5s
retries: 3
volumes:
redis_data:

Create /etc/redis/redis.conf:

# Network
bind 0.0.0.0
port 6379
protected-mode yes
# Security
requirepass your-secure-password
# Memory
maxmemory 256mb
maxmemory-policy allkeys-lru
# Persistence (optional for cluster coordination)
appendonly yes
appendfsync everysec
# Logging
loglevel notice
logfile /var/log/redis/redis-server.log

For cluster coordination (small footprint):

# Minimal memory for coordination only
maxmemory 256mb
maxmemory-policy allkeys-lru

For larger deployments with session state:

# More memory for sessions
maxmemory 1gb
maxmemory-policy volatile-lru
ModeUse CaseConfig
No persistenceEphemeral data onlyappendonly no, save ""
AOFCluster coordinationappendonly yes
RDBPoint-in-time backupssave 900 1
BothMaximum durabilityAOF + RDB

For Mantis cluster coordination:

# AOF persistence (recommended)
appendonly yes
appendfsync everysec
# Disable RDB snapshots
save ""
/etc/redis/redis.conf
requirepass your-secure-password
/etc/redis/redis.conf
user default off
user mantis on >secure-password ~mantis:* +@all

Or via ACL file:

/etc/redis/users.acl
user mantis on >secure-password ~mantis:* +@all -@dangerous
/etc/redis/redis.conf
tls-port 6379
port 0
tls-cert-file /etc/redis/ssl/redis.crt
tls-key-file /etc/redis/ssl/redis.key
tls-ca-cert-file /etc/redis/ssl/ca.crt
tls-auth-clients yes
# Bind to specific interfaces
bind 127.0.0.1 10.0.0.1
# Or use firewall rules
# ufw allow from 10.0.0.0/24 to any port 6379
thorax.toml
[cluster]
enabled = true
redis_url = "redis://:password@redis:6379"
namespace = "mantis"
heartbeat_interval_secs = 10
liveness_timeout_secs = 30
Terminal window
# Thorax
THORAX__CLUSTER__ENABLED=true
THORAX__CLUSTER__REDIS_URL="redis://:password@redis:6379"
THORAX__CLUSTER__NAMESPACE="mantis"
THORAX__CLUSTER__HEARTBEAT_INTERVAL_SECS=10
THORAX__CLUSTER__LIVENESS_TIMEOUT_SECS=30
# Mandible (SSE session/event fan-out)
SSE_REDIS_URL="redis://:password@redis:6379"
# Or the prefixed config-loader form:
# MANDIBLE__SSE__REDIS_URL="redis://:password@redis:6379"
redis://[username:password@]host[:port][/database]
# Examples
redis://localhost:6379
redis://:password@redis:6379
redis://user:password@redis:6379/0
rediss://redis:6379 # TLS
docker-compose.yml
services:
redis:
image: redis:7-alpine
hostname: redis
command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
volumes:
- redis_data:/data
networks:
- mantis
healthcheck:
test: ['CMD', 'redis-cli', '-a', '${REDIS_PASSWORD}', 'ping']
interval: 10s
timeout: 5s
retries: 3
thorax:
image: ghcr.io/mantisplatform/mantis-thorax:latest
environment:
THORAX__CLUSTER__ENABLED: 'true'
THORAX__CLUSTER__REDIS_URL: 'redis://:${REDIS_PASSWORD}@redis:6379'
depends_on:
redis:
condition: service_healthy
networks:
- mantis
volumes:
redis_data:
networks:
mantis:
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:7-alpine
command:
- redis-server
- --appendonly
- 'yes'
- --requirepass
- $(REDIS_PASSWORD)
ports:
- containerPort: 6379
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: redis-secret
key: password
volumeMounts:
- name: data
mountPath: /data
resources:
requests:
memory: '256Mi'
cpu: '100m'
limits:
memory: '512Mi'
cpu: '500m'
volumes:
- name: data
persistentVolumeClaim:
claimName: redis-pvc
---
apiVersion: v1
kind: Service
metadata:
name: redis
spec:
selector:
app: redis
ports:
- port: 6379
apiVersion: v1
kind: Secret
metadata:
name: redis-secret
type: Opaque
data:
password: <base64-encoded-password>
url: <base64-encoded-url> # redis://:password@redis:6379

For automatic failover:

docker-compose-sentinel.yml
services:
redis-master:
image: redis:7-alpine
command: redis-server --appendonly yes
redis-replica:
image: redis:7-alpine
command: redis-server --replicaof redis-master 6379
sentinel:
image: redis:7-alpine
command: redis-sentinel /etc/sentinel.conf
volumes:
- ./sentinel.conf:/etc/sentinel.conf

Sentinel configuration:

# sentinel.conf
sentinel monitor mymaster redis-master 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1

For horizontal scaling:

services:
redis-node-1:
image: redis:7-alpine
command: redis-server --cluster-enabled yes --cluster-config-file nodes.conf
redis-node-2:
image: redis:7-alpine
command: redis-server --cluster-enabled yes --cluster-config-file nodes.conf
redis-node-3:
image: redis:7-alpine
command: redis-server --cluster-enabled yes --cluster-config-file nodes.conf
Terminal window
# Connection info
redis-cli -a password INFO clients
# Memory usage
redis-cli -a password INFO memory
# Key statistics
redis-cli -a password INFO keyspace

All Thorax Redis keys are prefixed with the configured namespace (default: thorax). The examples below use mantis to match the namespace = "mantis" value in the Thorax Cluster Configuration example above — substitute your actual namespace if it differs.

Terminal window
# List all Thorax cluster keys
redis-cli -a password KEYS "mantis:*"
# Check instance registry
redis-cli -a password SMEMBERS "mantis:instances:index"
# View instance info
redis-cli -a password GET "mantis:instances:thorax-node-1"
# Check target affinity
redis-cli -a password KEYS "mantis:affinity:*"

Use Redis Exporter:

docker-compose.yml
services:
redis-exporter:
image: oliver006/redis_exporter:latest
environment:
REDIS_ADDR: 'redis://redis:6379'
REDIS_PASSWORD: '${REDIS_PASSWORD}'
ports:
- '9121:9121'
Terminal window
# Basic ping
redis-cli -h redis -p 6379 -a password ping
# With TLS
redis-cli --tls -h redis -p 6379 -a password ping

Replace mantis below with your configured namespace (default: thorax).

Terminal window
# After starting Thorax, check registration
redis-cli -a password SMEMBERS "mantis:instances:index"
# Check instance info
redis-cli -a password GET "mantis:instances:thorax-$(hostname)"

Thorax reports Redis status in health check:

The HTTP health endpoint is served on port 9090 (port 50051 is the gRPC port and is not curl-able as JSON):

Terminal window
curl -s http://localhost:9090/health | jq '.cluster'

Response:

{
"healthy": true,
"active_instances": 2,
"active_deployments": 5
}
Error: Connection refused (os error 111)

Solutions:

  1. Check Redis is running: systemctl status redis
  2. Verify bind address: redis-cli CONFIG GET bind
  3. Check firewall: ufw status
Error: NOAUTH Authentication required

Solutions:

  1. Verify password in URL: redis://:password@host:6379
  2. Check Redis password: redis-cli CONFIG GET requirepass
Error: OOM command not allowed when used memory > maxmemory

Solutions:

  1. Increase maxmemory: redis-cli CONFIG SET maxmemory 512mb
  2. Check memory policy: redis-cli CONFIG GET maxmemory-policy
  3. Clear old keys (substitute your namespace for mantis): redis-cli KEYS "mantis:*" | xargs redis-cli DEL

Replace mantis below with your configured namespace (default: thorax).

Terminal window
# Check TTL on instance key
redis-cli -a password TTL "mantis:instances:thorax-node-1"
# If TTL is -1 (no expiry), it may be a bug
# Manually set expiry
redis-cli -a password EXPIRE "mantis:instances:thorax-node-1" 30