Skip to content

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

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:

labels:
  - traefik.http.routers.mypost.rule=Host(`mypost.yourdomain.com`)

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:

sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d mypost.yourdomain.com


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

# Check logs
docker compose logs api
docker compose logs postgres

# Check resources
docker stats

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