Skip to content

Deployment

Production deployment guide for the AT Protocol MCP Server.

Overview

This guide covers deploying the AT Protocol MCP Server in production environments. For detailed deployment instructions, see DEPLOYMENT.md in the repository root.

Quick Start

The fastest way to deploy:

bash
# Clone repository
git clone https://github.com/cameronrye/atproto-mcp.git
cd atproto-mcp

# Configure environment
cp .env.example .env
nano .env  # Add your credentials

# Deploy
docker-compose up -d

# Verify
curl http://localhost:3000/health

Deployment Options

1. Docker Compose

Best for: Small to medium deployments, development teams

yaml
version: '3.8'

services:
  atproto-mcp:
    image: atproto-mcp:latest
    ports:
      - "3000:3000"
    environment:
      - ATPROTO_IDENTIFIER=${ATPROTO_IDENTIFIER}
      - ATPROTO_PASSWORD=${ATPROTO_PASSWORD}
      - NODE_ENV=production
      - LOG_LEVEL=info
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3

2. Kubernetes

Best for: Large-scale deployments, enterprise

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: atproto-mcp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: atproto-mcp
  template:
    metadata:
      labels:
        app: atproto-mcp
    spec:
      containers:
      - name: atproto-mcp
        image: atproto-mcp:latest
        ports:
        - containerPort: 3000
        env:
        - name: ATPROTO_IDENTIFIER
          valueFrom:
            secretKeyRef:
              name: atproto-secrets
              key: identifier
        - name: ATPROTO_PASSWORD
          valueFrom:
            secretKeyRef:
              name: atproto-secrets
              key: password
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /health
            port: 3000
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /health
            port: 3000
          initialDelaySeconds: 5
          periodSeconds: 5

3. Cloud Platforms

AWS ECS

bash
# Create task definition
aws ecs register-task-definition --cli-input-json file://task-definition.json

# Create service
aws ecs create-service \
  --cluster atproto-cluster \
  --service-name atproto-mcp \
  --task-definition atproto-mcp:1 \
  --desired-count 2

Google Cloud Run

bash
# Build and push image
gcloud builds submit --tag gcr.io/PROJECT_ID/atproto-mcp

# Deploy
gcloud run deploy atproto-mcp \
  --image gcr.io/PROJECT_ID/atproto-mcp \
  --platform managed \
  --region us-central1 \
  --set-env-vars ATPROTO_IDENTIFIER=...,ATPROTO_PASSWORD=...

Azure Container Instances

bash
# Create container
az container create \
  --resource-group atproto-rg \
  --name atproto-mcp \
  --image atproto-mcp:latest \
  --dns-name-label atproto-mcp \
  --ports 3000 \
  --environment-variables \
    ATPROTO_IDENTIFIER=... \
    ATPROTO_PASSWORD=...

4. Traditional Server

Best for: Dedicated servers, VPS

bash
# Install Node.js 20+
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs

# Install PM2
sudo npm install -g pm2

# Clone and setup
git clone https://github.com/cameronrye/atproto-mcp.git
cd atproto-mcp
npm install
npm run build

# Configure environment
cp .env.example .env
nano .env

# Start with PM2
pm2 start dist/index.js --name atproto-mcp
pm2 save
pm2 startup

Configuration

Environment Variables

Required:

bash
ATPROTO_IDENTIFIER=your-handle.bsky.social
ATPROTO_PASSWORD=your-app-password

Recommended:

bash
NODE_ENV=production
LOG_LEVEL=info
CACHE_ENABLED=true
METRICS_ENABLED=true
HEALTH_CHECK_ENABLED=true

Security:

bash
CORS_ORIGINS=https://yourdomain.com
TRUSTED_PROXIES=10.0.0.0/8
SECURITY_SECRET_KEY=$(openssl rand -hex 32)

Secrets Management

AWS Secrets Manager

bash
# Store secrets
aws secretsmanager create-secret \
  --name atproto-mcp-credentials \
  --secret-string '{"identifier":"...","password":"..."}'

# Retrieve in application
aws secretsmanager get-secret-value \
  --secret-id atproto-mcp-credentials

HashiCorp Vault

bash
# Store secrets
vault kv put secret/atproto-mcp \
  identifier="..." \
  password="..."

# Retrieve in application
vault kv get secret/atproto-mcp

Kubernetes Secrets

bash
# Create secret
kubectl create secret generic atproto-secrets \
  --from-literal=identifier=... \
  --from-literal=password=...

# Use in deployment (see Kubernetes example above)

Monitoring

Health Checks

bash
# HTTP health check
curl http://localhost:3000/health

# Expected response
{
  "status": "healthy",
  "timestamp": "2024-01-01T12:00:00.000Z",
  "version": "0.1.0"
}

Prometheus Metrics

bash
# Metrics endpoint
curl http://localhost:9090/metrics

# Key metrics
# - atproto_requests_total
# - atproto_request_duration_seconds
# - atproto_errors_total
# - atproto_rate_limit_hits_total

Grafana Dashboards

Access Grafana at http://localhost:3001:

  • Default credentials: admin/admin (change immediately!)
  • Pre-configured dashboards for:
    • Request rates and latency
    • Error rates
    • Authentication status
    • Resource usage

Logging

bash
# View logs (Docker)
docker logs -f atproto-mcp

# View logs (PM2)
pm2 logs atproto-mcp

# View logs (Kubernetes)
kubectl logs -f deployment/atproto-mcp

Security

Pre-Deployment Checklist

  • [ ] Change default passwords (Grafana, Redis, etc.)
  • [ ] Configure specific CORS origins (not *)
  • [ ] Use app passwords, not main account passwords
  • [ ] Set strong SECURITY_SECRET_KEY
  • [ ] Enable HTTPS in production
  • [ ] Configure TRUSTED_PROXIES if behind proxy
  • [ ] Enable rate limiting
  • [ ] Restrict access to internal services
  • [ ] Set up firewall rules
  • [ ] Enable audit logging

HTTPS Configuration

Using nginx

nginx
server {
    listen 443 ssl http2;
    server_name atproto-mcp.yourdomain.com;

    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;

    location / {
        proxy_pass http://localhost:3000;
        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;
    }
}

Using Traefik

yaml
http:
  routers:
    atproto-mcp:
      rule: "Host(`atproto-mcp.yourdomain.com`)"
      service: atproto-mcp
      tls:
        certResolver: letsencrypt
  services:
    atproto-mcp:
      loadBalancer:
        servers:
          - url: "http://localhost:3000"

Scaling

Horizontal Scaling

bash
# Docker Compose
docker-compose up -d --scale atproto-mcp=3

# Kubernetes
kubectl scale deployment atproto-mcp --replicas=5

# PM2
pm2 scale atproto-mcp 4

Load Balancing

nginx

nginx
upstream atproto_backend {
    least_conn;
    server localhost:3000;
    server localhost:3001;
    server localhost:3002;
}

server {
    location / {
        proxy_pass http://atproto_backend;
    }
}

Resource Allocation

Minimum:

  • CPU: 0.25 cores
  • Memory: 256 MB
  • Storage: 1 GB

Recommended:

  • CPU: 0.5 cores
  • Memory: 512 MB
  • Storage: 5 GB

High Load:

  • CPU: 1-2 cores
  • Memory: 1-2 GB
  • Storage: 10 GB

Backup & Recovery

Data to Backup

  • Configuration files (.env, config/)
  • Logs (if needed for compliance)
  • Credentials and secrets
  • Custom configurations

Backup Script

bash
#!/bin/bash
BACKUP_DIR="/backups/atproto-mcp"
DATE=$(date +%Y%m%d_%H%M%S)

# Create backup directory
mkdir -p "$BACKUP_DIR/$DATE"

# Backup configuration
cp .env "$BACKUP_DIR/$DATE/"
cp -r config "$BACKUP_DIR/$DATE/"

# Backup logs (optional)
cp -r logs "$BACKUP_DIR/$DATE/"

# Create archive
tar -czf "$BACKUP_DIR/atproto-mcp-$DATE.tar.gz" "$BACKUP_DIR/$DATE"

# Clean up old backups (keep last 7 days)
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +7 -delete

Recovery Procedure

bash
# 1. Extract backup
tar -xzf atproto-mcp-YYYYMMDD_HHMMSS.tar.gz

# 2. Restore configuration
cp backup/.env .
cp -r backup/config .

# 3. Restart service
docker-compose restart
# or
pm2 restart atproto-mcp

Maintenance

Updates

bash
# Docker
docker pull atproto-mcp:latest
docker-compose up -d

# PM2
git pull origin main
npm install
npm run build
pm2 restart atproto-mcp

# Kubernetes
kubectl set image deployment/atproto-mcp \
  atproto-mcp=atproto-mcp:latest

Health Monitoring

Set up automated health checks:

bash
# Cron job for health check
*/5 * * * * curl -f http://localhost:3000/health || systemctl restart atproto-mcp

Troubleshooting

See Troubleshooting Guide for common deployment issues.

Next Steps


Previous: Troubleshooting ← | Next: API Reference

Released under the MIT License.