guide/deployment.md
Deployment Guide
This guide provides recommendations and strategies for deploying your Sockudo server to a production environment, covering everything from building and containerization to scaling and security best practices.
Building for Production
Always compile Sockudo in release mode for production deployments to ensure optimal performance and smaller binary size:
cargo build --release
The executable will be located at target/release/sockudo
.
Cross-Compilation
For different target architectures:
# Install target
rustup target add x86_64-unknown-linux-musl
# Build for musl (static linking)
cargo build --release --target x86_64-unknown-linux-musl
# For ARM64 (e.g., AWS Graviton)
rustup target add aarch64-unknown-linux-gnu
cargo build --release --target aarch64-unknown-linux-gnu
Docker Deployment
Production Dockerfile
Create an optimized Dockerfile for production:
# Multi-stage build for optimized production image
FROM rust:1.75-slim AS builder
# Install build dependencies
RUN apt-get update && apt-get install -y \
pkg-config \
libssl-dev \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /usr/src/sockudo
# Copy source code
COPY . .
# Build release binary
RUN cargo build --release
# Runtime stage
FROM debian:bullseye-slim
# Install runtime dependencies
RUN apt-get update && apt-get install -y \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*
# Create non-root user
RUN groupadd --system sockudo && \
useradd --system --no-log-init -g sockudo sockudo
# Create directories
RUN mkdir -p /app/config /app/ssl /app/logs && \
chown -R sockudo:sockudo /app
WORKDIR /app
# Copy binary from builder stage
COPY --from=builder /usr/src/sockudo/target/release/sockudo .
COPY --from=builder /usr/src/sockudo/config/config.json ./config/
# Set ownership and permissions
RUN chown sockudo:sockudo ./sockudo && \
chmod +x ./sockudo
# Switch to non-root user
USER sockudo
# Expose ports
EXPOSE 6001 9601
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
CMD curl -f http://localhost:6001/usage || exit 1
# Default command
CMD ["./sockudo", "--config=./config/config.json"]
Docker Compose for Production
version: '3.8'
services:
sockudo:
image: sockudo/sockudo:latest
restart: unless-stopped
ports:
- "6001:6001"
- "9601:9601"
environment:
- DEBUG=false
- ADAPTER_DRIVER=redis
- REDIS_URL=redis://redis:6379/0
- APP_MANAGER_DRIVER=mysql
- DATABASE_MYSQL_HOST=mysql
- DATABASE_MYSQL_USER=sockudo
- DATABASE_MYSQL_PASSWORD=${MYSQL_PASSWORD}
- DATABASE_MYSQL_DATABASE=sockudo
- CACHE_DRIVER=redis
- QUEUE_DRIVER=redis
- METRICS_ENABLED=true
- SSL_ENABLED=${SSL_ENABLED:-false}
volumes:
- ./config:/app/config:ro
- ./ssl:/app/ssl:ro
- sockudo_logs:/app/logs
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_healthy
networks:
- sockudo_network
deploy:
resources:
limits:
memory: 512M
cpus: '1.0'
reservations:
memory: 256M
cpus: '0.5'
redis:
image: redis:7-alpine
restart: unless-stopped
command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru
volumes:
- redis_data:/data
networks:
- sockudo_network
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 3
mysql:
image: mysql:8.0
restart: unless-stopped
environment:
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
- MYSQL_DATABASE=sockudo
- MYSQL_USER=sockudo
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
volumes:
- mysql_data:/var/lib/mysql
- ./mysql/init:/docker-entrypoint-initdb.d:ro
networks:
- sockudo_network
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 3
nginx:
image: nginx:alpine
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/ssl:/etc/nginx/ssl:ro
depends_on:
- sockudo
networks:
- sockudo_network
prometheus:
image: prom/prometheus:latest
restart: unless-stopped
ports:
- "9090:9090"
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/etc/prometheus/console_libraries'
- '--web.console.templates=/etc/prometheus/consoles'
- '--web.enable-lifecycle'
networks:
- sockudo_network
volumes:
redis_data:
mysql_data:
prometheus_data:
sockudo_logs:
networks:
sockudo_network:
driver: bridge
Environment Configuration
Create a .env
file for production:
# .env.production
MYSQL_ROOT_PASSWORD=secure_root_password_here
MYSQL_PASSWORD=secure_sockudo_password_here
SSL_ENABLED=true
# Redis Configuration
REDIS_PASSWORD=secure_redis_password
# Security
CORS_ORIGINS=https://yourdomain.com,https://app.yourdomain.com
CORS_CREDENTIALS=true
# Performance
DATABASE_CONNECTION_POOL_SIZE=15
REDIS_CONNECTION_POOL_SIZE=10
# Monitoring
METRICS_ENABLED=true
LOG_LEVEL=info
# Instance identification
INSTANCE_PROCESS_ID=sockudo-prod-01
Kubernetes Deployment
Basic Deployment
# sockudo-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: sockudo
labels:
app: sockudo
spec:
replicas: 3
selector:
matchLabels:
app: sockudo
template:
metadata:
labels:
app: sockudo
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9601"
prometheus.io/path: "/metrics"
spec:
containers:
- name: sockudo
image: sockudo/sockudo:latest
ports:
- containerPort: 6001
name: websocket
- containerPort: 9601
name: metrics
env:
- name: ADAPTER_DRIVER
value: "redis"
- name: REDIS_URL
value: "redis://redis-service:6379"
- name: APP_MANAGER_DRIVER
value: "mysql"
- name: DATABASE_MYSQL_HOST
value: "mysql-service"
- name: DATABASE_MYSQL_USER
value: "sockudo"
- name: DATABASE_MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: password
- name: INSTANCE_PROCESS_ID
valueFrom:
fieldRef:
fieldPath: metadata.name
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /usage
port: 6001
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /usage
port: 6001
initialDelaySeconds: 5
periodSeconds: 5
volumeMounts:
- name: config
mountPath: /app/config
readOnly: true
- name: ssl-certs
mountPath: /app/ssl
readOnly: true
volumes:
- name: config
configMap:
name: sockudo-config
- name: ssl-certs
secret:
secretName: sockudo-ssl
---
apiVersion: v1
kind: Service
metadata:
name: sockudo-service
spec:
selector:
app: sockudo
ports:
- name: websocket
port: 6001
targetPort: 6001
- name: metrics
port: 9601
targetPort: 9601
type: LoadBalancer
---
apiVersion: v1
kind: ConfigMap
metadata:
name: sockudo-config
data:
config.json: |
{
"debug": false,
"host": "0.0.0.0",
"port": 6001,
"metrics": {
"enabled": true,
"port": 9601
},
"ssl": {
"enabled": true,
"cert_path": "/app/ssl/tls.crt",
"key_path": "/app/ssl/tls.key"
}
}
---
apiVersion: v1
kind: Secret
metadata:
name: mysql-secret
type: Opaque
data:
password: <base64-encoded-password>
---
apiVersion: v1
kind: Secret
metadata:
name: sockudo-ssl
type: kubernetes.io/tls
data:
tls.crt: <base64-encoded-certificate>
tls.key: <base64-encoded-private-key>
Horizontal Pod Autoscaler
# sockudo-hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: sockudo-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: sockudo
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
- type: Pods
pods:
metric:
name: sockudo_active_connections
target:
type: AverageValue
averageValue: "1000"
Ingress Configuration
# sockudo-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: sockudo-ingress
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/proxy-read-timeout: "86400"
nginx.ingress.kubernetes.io/proxy-send-timeout: "86400"
nginx.ingress.kubernetes.io/websocket-services: "sockudo-service"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
tls:
- hosts:
- sockudo.yourdomain.com
secretName: sockudo-tls
rules:
- host: sockudo.yourdomain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: sockudo-service
port:
number: 6001
systemd Service Deployment
Service Configuration
Create /etc/systemd/system/sockudo.service
:
[Unit]
Description=Sockudo WebSocket Server
After=network.target
Wants=redis.service mysql.service
After=redis.service mysql.service
[Service]
Type=simple
User=sockudo
Group=sockudo
WorkingDirectory=/opt/sockudo
ExecStart=/opt/sockudo/sockudo --config=/opt/sockudo/config/config.json
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5s
StandardOutput=journal
StandardError=journal
SyslogIdentifier=sockudo
# Security settings
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/opt/sockudo/logs
ReadOnlyPaths=/opt/sockudo/config
# Resource limits
LimitNOFILE=65536
MemoryMax=1G
# Environment
Environment=RUST_LOG=info
EnvironmentFile=-/etc/sockudo/sockudo.env
[Install]
WantedBy=multi-user.target
Installation Script
#!/bin/bash
# install-sockudo.sh
set -e
SOCKUDO_USER="sockudo"
SOCKUDO_GROUP="sockudo"
SOCKUDO_HOME="/opt/sockudo"
BINARY_PATH="./target/release/sockudo"
CONFIG_PATH="./config/config.json"
echo "Installing Sockudo..."
# Create user and group
if ! id "$SOCKUDO_USER" &>/dev/null; then
sudo groupadd "$SOCKUDO_GROUP"
sudo useradd -r -g "$SOCKUDO_GROUP" -d "$SOCKUDO_HOME" -s /sbin/nologin "$SOCKUDO_USER"
echo "Created user $SOCKUDO_USER"
fi
# Create directories
sudo mkdir -p "$SOCKUDO_HOME"/{config,ssl,logs}
sudo chown -R "$SOCKUDO_USER:$SOCKUDO_GROUP" "$SOCKUDO_HOME"
# Install binary
sudo cp "$BINARY_PATH" "$SOCKUDO_HOME/"
sudo chown "$SOCKUDO_USER:$SOCKUDO_GROUP" "$SOCKUDO_HOME/sockudo"
sudo chmod +x "$SOCKUDO_HOME/sockudo"
# Install configuration
sudo cp "$CONFIG_PATH" "$SOCKUDO_HOME/config/"
sudo chown "$SOCKUDO_USER:$SOCKUDO_GROUP" "$SOCKUDO_HOME/config/config.json"
# Install systemd service
sudo cp sockudo.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable sockudo.service
echo "Installation complete!"
echo "Start the service with: sudo systemctl start sockudo"
echo "Check status with: sudo systemctl status sockudo"
Load Balancer Configuration
Nginx Load Balancer
# /etc/nginx/sites-available/sockudo
upstream sockudo_backend {
least_conn;
server sockudo-1.internal:6001 max_fails=3 fail_timeout=30s weight=1;
server sockudo-2.internal:6001 max_fails=3 fail_timeout=30s weight=1;
server sockudo-3.internal:6001 max_fails=3 fail_timeout=30s weight=1;
keepalive 32;
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
# Rate limiting
limit_req_zone $binary_remote_addr zone=sockudo_api:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=sockudo_ws:10m rate=5r/s;
server {
listen 80;
server_name sockudo.yourdomain.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name sockudo.yourdomain.com;
# SSL Configuration
ssl_certificate /etc/letsencrypt/live/sockudo.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sockudo.yourdomain.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# Security Headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options DENY always;
add_header X-Content-Type-Options nosniff always;
add_header X-XSS-Protection "1; mode=block" always;
# WebSocket and API endpoints
location / {
# Apply rate limiting based on path
if ($request_uri ~ "^/app/") {
limit_req zone=sockudo_ws burst=10 nodelay;
}
if ($request_uri ~ "^/apps/.*/events") {
limit_req zone=sockudo_api burst=20 nodelay;
}
proxy_pass http://sockudo_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
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;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
# WebSocket specific settings
proxy_connect_timeout 60s;
proxy_send_timeout 86400s;
proxy_read_timeout 86400s;
proxy_buffering off;
proxy_cache off;
# CORS headers
add_header Access-Control-Allow-Origin "*" always;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
add_header Access-Control-Allow-Headers "Authorization, Content-Type, X-Requested-With" always;
if ($request_method = OPTIONS) {
return 204;
}
}
# Health check endpoint (no rate limiting)
location = /health {
access_log off;
proxy_pass http://sockudo_backend/usage;
proxy_set_header Host $host;
}
# Metrics endpoint (restricted access)
location /metrics {
allow 10.0.0.0/8;
allow 172.16.0.0/12;
allow 192.168.0.0/16;
deny all;
proxy_pass http://sockudo_backend:9601/metrics;
proxy_set_header Host $host;
}
}
HAProxy Configuration
# /etc/haproxy/haproxy.cfg
global
log stdout local0
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
defaults
mode http
log global
option httplog
option dontlognull
option redispatch
timeout connect 5000
timeout client 86400000 # Long timeout for WebSockets
timeout server 86400000 # Long timeout for WebSockets
frontend sockudo_frontend
bind *:443 ssl crt /etc/ssl/certs/sockudo.pem
bind *:80
redirect scheme https if !{ ssl_fc }
# ACLs
acl is_websocket hdr_beg(Upgrade) -i websocket
acl is_api path_beg /apps/
acl is_health path /health /usage
# Route to backend
use_backend sockudo_backend
backend sockudo_backend
balance leastconn
option httpchk GET /usage
http-check expect status 200
# Servers
server sockudo1 sockudo-1.internal:6001 check inter 5s rise 2 fall 3 maxconn 1000
server sockudo2 sockudo-2.internal:6001 check inter 5s rise 2 fall 3 maxconn 1000
server sockudo3 sockudo-3.internal:6001 check inter 5s rise 2 fall 3 maxconn 1000
Security Best Practices
Network Security
# Firewall configuration (UFW example)
sudo ufw default deny incoming
sudo ufw default allow outgoing
# Allow SSH (adjust port as needed)
sudo ufw allow 22/tcp
# Allow HTTP/HTTPS for load balancer
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Allow Sockudo port only from load balancer
sudo ufw allow from 10.0.1.100 to any port 6001
# Allow metrics port only from monitoring server
sudo ufw allow from 10.0.1.200 to any port 9601
# Allow Redis/MySQL ports only from Sockudo servers
sudo ufw allow from 10.0.1.0/24 to any port 6379 # Redis
sudo ufw allow from 10.0.1.0/24 to any port 3306 # MySQL
sudo ufw enable
SSL/TLS Configuration
# Generate strong DH parameters
sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
# Set proper file permissions
sudo chmod 644 /etc/ssl/certs/sockudo.crt
sudo chmod 600 /etc/ssl/private/sockudo.key
sudo chown root:sockudo /etc/ssl/private/sockudo.key
Application Security
{
"cors": {
"credentials": true,
"origin": ["https://yourdomain.com"],
"methods": ["GET", "POST", "OPTIONS"],
"allowed_headers": ["Authorization", "Content-Type", "X-Requested-With"]
},
"rate_limiter": {
"enabled": true,
"driver": "redis",
"api_rate_limit": {
"max_requests": 100,
"window_seconds": 60,
"trust_hops": 1
},
"websocket_rate_limit": {
"max_requests": 20,
"window_seconds": 60
}
}
}
Secret Management
# Using HashiCorp Vault
vault kv put secret/sockudo \
mysql_password=secure_password \
redis_password=secure_redis_password \
app_secret=secure_app_secret
# Using AWS Secrets Manager
aws secretsmanager create-secret \
--name "sockudo/production" \
--description "Sockudo production secrets" \
--secret-string '{"mysql_password":"secure_password","redis_password":"secure_redis_password"}'
# Using Kubernetes secrets
kubectl create secret generic sockudo-secrets \
--from-literal=mysql-password=secure_password \
--from-literal=redis-password=secure_redis_password
Monitoring and Logging
Log Management
# Logrotate configuration
# /etc/logrotate.d/sockudo
/var/log/sockudo/*.log {
daily
missingok
rotate 52
compress
delaycompress
notifempty
create 644 sockudo sockudo
postrotate
systemctl reload sockudo
endscript
}
# Syslog configuration
# /etc/rsyslog.d/sockudo.conf
if $programname == 'sockudo' then /var/log/sockudo/sockudo.log
& stop
Centralized Logging with ELK
# filebeat.yml
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/sockudo/*.log
fields:
service: sockudo
environment: production
instance: ${HOSTNAME}
fields_under_root: true
multiline.pattern: '^[0-9]{4}-[0-9]{2}-[0-9]{2}'
multiline.negate: true
multiline.match: after
output.logstash:
hosts: ["logstash.internal:5044"]
processors:
- add_host_metadata:
when.not.contains.tags: forwarded
Monitoring Setup
# prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- "sockudo-alerts.yml"
scrape_configs:
- job_name: 'sockudo'
static_configs:
- targets:
- 'sockudo-1.internal:9601'
- 'sockudo-2.internal:9601'
- 'sockudo-3.internal:9601'
scrape_interval: 15s
metrics_path: /metrics
- job_name: 'node-exporter'
static_configs:
- targets:
- 'sockudo-1.internal:9100'
- 'sockudo-2.internal:9100'
- 'sockudo-3.internal:9100'
alerting:
alertmanagers:
- static_configs:
- targets:
- alertmanager.internal:9093
Backup and Disaster Recovery
Database Backup
#!/bin/bash
# backup-database.sh
BACKUP_DIR="/backup/sockudo"
DATE=$(date +%Y%m%d_%H%M%S)
MYSQL_HOST="mysql.internal"
MYSQL_USER="backup_user"
MYSQL_PASSWORD="backup_password"
DATABASE="sockudo"
# Create backup directory
mkdir -p "$BACKUP_DIR"
# MySQL backup
mysqldump -h "$MYSQL_HOST" -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" \
--single-transaction --routines --triggers "$DATABASE" | \
gzip > "$BACKUP_DIR/sockudo_${DATE}.sql.gz"
# Redis backup (if using Redis for app manager)
redis-cli --rdb "$BACKUP_DIR/redis_${DATE}.rdb"
# Cleanup old backups (keep 30 days)
find "$BACKUP_DIR" -type f -mtime +30 -delete
echo "Backup completed: $BACKUP_DIR/sockudo_${DATE}.sql.gz"
Configuration Backup
#!/bin/bash
# backup-config.sh
BACKUP_DIR="/backup/sockudo-config"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p "$BACKUP_DIR"
# Backup configuration
tar -czf "$BACKUP_DIR/config_${DATE}.tar.gz" \
/opt/sockudo/config/ \
/etc/systemd/system/sockudo.service \
/etc/nginx/sites-available/sockudo
# Backup SSL certificates
tar -czf "$BACKUP_DIR/ssl_${DATE}.tar.gz" \
/etc/ssl/certs/sockudo.* \
/etc/ssl/private/sockudo.*
echo "Configuration backup completed"
Disaster Recovery Plan
#!/bin/bash
# disaster-recovery.sh
# 1. Deploy new infrastructure
# 2. Restore configuration
cd /backup/sockudo-config
latest_config=$(ls -t config_*.tar.gz | head -1)
tar -xzf "$latest_config" -C /
# 3. Restore database
cd /backup/sockudo
latest_db=$(ls -t sockudo_*.sql.gz | head -1)
gunzip -c "$latest_db" | mysql -h mysql.internal -u sockudo -p sockudo
# 4. Start services
systemctl start sockudo
systemctl enable sockudo
# 5. Verify recovery
curl http://localhost:6001/usage
Performance Optimization
System Tuning
# /etc/sysctl.d/99-sockudo.conf
# Network optimizations
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 5000
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 60
net.ipv4.tcp_keepalive_probes = 10
# File descriptor limits
fs.file-max = 1000000
# Apply changes
sudo sysctl -p /etc/sysctl.d/99-sockudo.conf
# /etc/security/limits.d/sockudo.conf
sockudo soft nofile 65535
sockudo hard nofile 65535
sockudo soft nproc 32768
sockudo hard nproc 32768
Application Tuning
{
"websocket_max_payload_kb": 32,
"database_pooling": {
"enabled": true,
"min": 5,
"max": 20
},
"cache": {
"driver": "redis",
"redis": {
"prefix": "sockudo_cache:",
"url_override": "redis://redis-cache.internal:6379/1"
}
},
"queue": {
"driver": "redis",
"redis": {
"concurrency": 10,
"prefix": "sockudo_queue:",
"url_override": "redis://redis-queue.internal:6379/2"
}
}
}
Health Checks and Readiness
Application Health Check
#!/bin/bash
# health-check.sh
SOCKUDO_URL="http://localhost:6001"
TIMEOUT=10
# Check main service
if ! curl -f -m $TIMEOUT "$SOCKUDO_URL/usage" >/dev/null 2>&1; then
echo "CRITICAL: Sockudo service not responding"
exit 2
fi
# Check metrics endpoint
if ! curl -f -m $TIMEOUT "http://localhost:9601/metrics" >/dev/null 2>&1; then
echo "WARNING: Metrics endpoint not responding"
exit 1
fi
# Check Redis connectivity (if using Redis)
if ! redis-cli ping >/dev/null 2>&1; then
echo "WARNING: Redis not accessible"
exit 1
fi
# Check database connectivity (if using MySQL)
if ! mysqladmin ping -h mysql.internal >/dev/null 2>&1; then
echo "WARNING: MySQL not accessible"
exit 1
fi
echo "OK: All health checks passed"
exit 0
Kubernetes Readiness Probe
readinessProbe:
httpGet:
path: /usage
port: 6001
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
successThreshold: 1
failureThreshold: 3
livenessProbe:
httpGet:
path: /usage
port: 6001
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
Deployment Automation
CI/CD Pipeline (GitLab CI)
# .gitlab-ci.yml
stages:
- test
- build
- deploy
variables:
DOCKER_REGISTRY: registry.gitlab.com/yourgroup/sockudo
DOCKER_TAG: $CI_COMMIT_SHORT_SHA
test:
stage: test
image: rust:1.75
script:
- cargo test --release
only:
- main
- merge_requests
build:
stage: build
image: docker:latest
services:
- docker:dind
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build -t $DOCKER_REGISTRY:$DOCKER_TAG .
- docker push $DOCKER_REGISTRY:$DOCKER_TAG
- docker tag $DOCKER_REGISTRY:$DOCKER_TAG $DOCKER_REGISTRY:latest
- docker push $DOCKER_REGISTRY:latest
only:
- main
deploy_staging:
stage: deploy
image: alpine/k8s:latest
script:
- kubectl config use-context staging
- kubectl set image deployment/sockudo sockudo=$DOCKER_REGISTRY:$DOCKER_TAG
- kubectl rollout status deployment/sockudo
environment:
name: staging
url: https://sockudo-staging.yourdomain.com
only:
- main
deploy_production:
stage: deploy
image: alpine/k8s:latest
script:
- kubectl config use-context production
- kubectl set image deployment/sockudo sockudo=$DOCKER_REGISTRY:$DOCKER_TAG
- kubectl rollout status deployment/sockudo
environment:
name: production
url: https://sockudo.yourdomain.com
when: manual
only:
- main
Blue-Green Deployment
#!/bin/bash
# blue-green-deploy.sh
NEW_VERSION="$1"
CURRENT_COLOR=$(kubectl get service sockudo-service -o jsonpath='{.spec.selector.color}')
if [ "$CURRENT_COLOR" = "blue" ]; then
NEW_COLOR="green"
else
NEW_COLOR="blue"
fi
echo "Deploying version $NEW_VERSION to $NEW_COLOR environment"
# Update deployment
kubectl set image deployment/sockudo-$NEW_COLOR sockudo=sockudo/sockudo:$NEW_VERSION
# Wait for rollout
kubectl rollout status deployment/sockudo-$NEW_COLOR
# Run health checks
./health-check.sh http://sockudo-$NEW_COLOR.internal:6001
# Switch traffic
kubectl patch service sockudo-service -p '{"spec":{"selector":{"color":"'$NEW_COLOR'"}}}'
echo "Deployment complete. Traffic switched to $NEW_COLOR"
echo "Previous $CURRENT_COLOR environment is still running for rollback"
Troubleshooting Production Issues
Emergency Response
#!/bin/bash
# emergency-response.sh
case "$1" in
"high-load")
# Scale up quickly
kubectl scale deployment sockudo --replicas=10
;;
"memory-leak")
# Rolling restart
kubectl rollout restart deployment/sockudo
;;
"redis-down")
# Switch to local adapter temporarily
kubectl set env deployment/sockudo ADAPTER_DRIVER=local
;;
"rollback")
# Rollback to previous version
kubectl rollout undo deployment/sockudo
;;
*)
echo "Usage: $0 {high-load|memory-leak|redis-down|rollback}"
exit 1
;;
esac
Performance Monitoring
#!/bin/bash
# performance-monitor.sh
echo "=== Sockudo Performance Report ==="
echo "Date: $(date)"
echo
# Connection count
CONNECTIONS=$(curl -s http://localhost:9601/metrics | grep sockudo_active_connections | tail -1 | awk '{print $2}')
echo "Active Connections: $CONNECTIONS"
# Memory usage
MEMORY=$(ps -o rss= -p $(pgrep sockudo) | awk '{print $1/1024 " MB"}')
echo "Memory Usage: $MEMORY"
# CPU usage
CPU=$(ps -o %cpu= -p $(pgrep sockudo))
echo "CPU Usage: $CPU%"
# Network connections
NETWORK_CONN=$(netstat -an | grep :6001 | wc -l)
echo "Network Connections: $NETWORK_CONN"
# Redis info (if applicable)
if command -v redis-cli >/dev/null; then
REDIS_MEMORY=$(redis-cli info memory | grep used_memory_human | cut -d: -f2 | tr -d '\r')
echo "Redis Memory: $REDIS_MEMORY"
fi
echo "================================"
This comprehensive deployment guide covers all aspects of running Sockudo in production, from basic setup to advanced scaling and monitoring strategies. Adapt the configurations and scripts to match your specific infrastructure and requirements.