Production Deployment Guide¶
This guide covers deploying MyPost to a production environment.
Deployment Options¶
| Method | Best For | Complexity |
|---|---|---|
| Docker Compose | Single server, small teams | ⭐ Low |
| Docker Swarm | Multi-node, HA | ⭐⭐ Medium |
| Kubernetes | Enterprise, auto-scaling | ⭐⭐⭐ High |
Docker Compose (Recommended)¶
Server Requirements¶
| Resource | Minimum | Recommended |
|---|---|---|
| CPU | 2 cores | 4+ cores |
| RAM | 4 GB | 8+ GB |
| Storage | 20 GB | 100+ GB SSD |
| OS | Ubuntu 22.04 | Any Linux with Docker |
Step 1: Prepare Server¶
# Update system
sudo apt update && sudo apt upgrade -y
# Install Docker
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
# Install Docker Compose v2
sudo apt install docker-compose-plugin
# Verify installation
docker --version
docker compose version
Step 2: Clone Repository¶
cd /opt
sudo mkdir mypost && sudo chown $USER:$USER mypost
git clone https://github.com/your-org/mypost.git /opt/mypost
cd /opt/mypost
Step 3: Configure Environment¶
# Copy template
cp .env.example .env
# Generate secrets
POSTGRES_PASSWORD=$(openssl rand -base64 24)
JWT_SECRET=$(openssl rand -base64 64)
ENCRYPTION_KEY=$(openssl rand -base64 32)
MINIO_ROOT_PASSWORD=$(openssl rand -base64 24)
# Update .env file
cat > .env << EOF
# Application
APP_URL=https://mypost.yourdomain.com
NODE_ENV=production
LOG_LEVEL=info
# Database
POSTGRES_PASSWORD=$POSTGRES_PASSWORD
DATABASE_URL=postgresql://mypost:\${POSTGRES_PASSWORD}@postgres:5432/mypost
# Security
JWT_SECRET=$JWT_SECRET
JWT_EXPIRES_IN=15m
REFRESH_TOKEN_EXPIRES_IN=7d
ENCRYPTION_KEY=$ENCRYPTION_KEY
# Redis
REDIS_URL=redis://redis:6379
# Object Storage
MINIO_ROOT_USER=minio
MINIO_ROOT_PASSWORD=$MINIO_ROOT_PASSWORD
S3_ENDPOINT=http://minio:9000
S3_BUCKET=mypost
S3_ACCESS_KEY=minio
S3_SECRET_KEY=$MINIO_ROOT_PASSWORD
# Backup (optional)
BACKUP_ENABLED=true
BACKUP_SCHEDULE=0 2 * * *
BACKUP_RETENTION_DAYS=30
EOF
Step 4: Configure Reverse Proxy¶
Option A: Traefik (Recommended)
Update compose.yaml labels for your domain:
Option B: Nginx Standalone
# /etc/nginx/sites-available/mypost
server {
listen 80;
server_name mypost.yourdomain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name mypost.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/mypost.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mypost.yourdomain.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8080;
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;
}
}
Step 5: Deploy¶
# Build and start
docker compose up -d --build
# Initialize database
docker compose exec api npm run db:push
# Verify health
curl https://mypost.yourdomain.com/api/v1/health
Step 6: SSL Certificate¶
With Traefik (automatic): Traefik handles Let's Encrypt certificates automatically.
With Certbot:
Environment Configuration¶
Required Variables¶
| Variable | Description | Example |
|---|---|---|
APP_URL |
Public URL | https://mypost.example.com |
POSTGRES_PASSWORD |
DB password | (generate) |
JWT_SECRET |
Token signing | (generate 64+ chars) |
ENCRYPTION_KEY |
Encryption key | (generate 32 bytes) |
Social Network OAuth¶
Configure these to enable social account connections:
# Facebook
FACEBOOK_APP_ID=your_app_id
FACEBOOK_APP_SECRET=your_app_secret
# Instagram (uses Facebook app)
INSTAGRAM_APP_ID=${FACEBOOK_APP_ID}
INSTAGRAM_APP_SECRET=${FACEBOOK_APP_SECRET}
# X (Twitter)
TWITTER_CLIENT_ID=your_client_id
TWITTER_CLIENT_SECRET=your_client_secret
# LinkedIn
LINKEDIN_CLIENT_ID=your_client_id
LINKEDIN_CLIENT_SECRET=your_client_secret
# TikTok
TIKTOK_CLIENT_KEY=your_client_key
TIKTOK_CLIENT_SECRET=your_client_secret
# YouTube (Google)
GOOGLE_CLIENT_ID=your_client_id
GOOGLE_CLIENT_SECRET=your_client_secret
OAuth Callback URLs (configure in each platform):
https://mypost.yourdomain.com/api/v1/oauth/facebook/callback
https://mypost.yourdomain.com/api/v1/oauth/instagram/callback
https://mypost.yourdomain.com/api/v1/oauth/twitter/callback
https://mypost.yourdomain.com/api/v1/oauth/linkedin/callback
https://mypost.yourdomain.com/api/v1/oauth/tiktok/callback
https://mypost.yourdomain.com/api/v1/oauth/youtube/callback
Database Configuration¶
PostgreSQL Tuning¶
For production workloads, tune PostgreSQL:
# Edit postgresql.conf or use environment variables
POSTGRES_SHARED_BUFFERS=256MB # 25% of RAM
POSTGRES_EFFECTIVE_CACHE_SIZE=768MB # 75% of RAM
POSTGRES_WORK_MEM=16MB
POSTGRES_MAX_CONNECTIONS=100
Connection Pooling¶
For high traffic, use PgBouncer:
# Add to compose.yaml
pgbouncer:
image: edoburu/pgbouncer
environment:
- DATABASE_URL=postgresql://mypost:${POSTGRES_PASSWORD}@postgres:5432/mypost
- POOL_MODE=transaction
- MAX_CLIENT_CONN=500
- DEFAULT_POOL_SIZE=25
Security Hardening¶
Rate Limiting¶
Already configured in the API. Adjust thresholds in .env:
RATE_LIMIT_GLOBAL=1000 # requests/second total
RATE_LIMIT_WORKSPACE=100 # per workspace/second
RATE_LIMIT_USER=10 # per user/second
Firewall Rules¶
# Allow only necessary ports
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
Database Security¶
- Change default passwords (done via .env)
- Restrict database network access
- Enable SSL for database connections
High Availability Setup¶
Multi-Node with Docker Swarm¶
# Initialize swarm
docker swarm init
# Deploy stack
docker stack deploy -c compose.yaml mypost
# Scale services
docker service scale mypost_api=3
docker service scale mypost_worker=2
Load Balancing¶
# In compose.yaml
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
Updating MyPost¶
Standard Update¶
cd /opt/mypost
# Pull latest changes
git pull origin main
# Rebuild and deploy
docker compose pull
docker compose up -d --build
# Run any new migrations
docker compose exec api npm run db:push
Blue-Green Deployment¶
For zero-downtime updates:
# 1. Create backup
docker compose exec postgres pg_dump -U mypost mypost > backup.sql
# 2. Start new version alongside current
docker compose -f compose.yaml -f compose.blue-green.yaml up -d
# 3. Test new version
curl https://mypost.yourdomain.com:8081/api/v1/health
# 4. Switch traffic
# (Update Traefik/Nginx to point to new version)
# 5. Remove old version
docker compose -f compose.yaml down
Rollback Procedure¶
If an update fails:
# 1. Stop current containers
docker compose down
# 2. Checkout previous version
git checkout HEAD~1
# 3. Restore database (if needed)
docker compose up -d postgres
docker compose exec -T postgres psql -U mypost mypost < backup.sql
# 4. Start previous version
docker compose up -d --build
Troubleshooting¶
Container Won't Start¶
Database Connection Errors¶
# Test connection
docker compose exec api npm run db:check
# Verify PostgreSQL is running
docker compose exec postgres pg_isready
Performance Issues¶
# Check resource usage
docker stats
# API metrics
curl https://mypost.yourdomain.com/api/v1/metrics
# Database slow queries
docker compose exec postgres psql -U mypost -c "SELECT * FROM pg_stat_activity;"
Next Steps¶
- Operations Guide — Backup, monitoring, maintenance
- API Reference — Integration documentation