Skip to main content

Deployment

Production deployment guide for AsaHome Cloud.

Prerequisites

  • Docker and Docker Compose installed
  • Domain name with DNS configured
  • SSL certificate (or use Let's Encrypt)
  • Server with at least 2GB RAM

Production Deployment Steps

1. Clone and Configure

# Clone the repository
git clone <repository-url>
cd asahome-cloud

# Run setup
make setup

# Configure production environment
cp .env .env.production

2. Configure Environment Variables

Edit .env.production with production values:

# Application
NODE_ENV=production
PORT=3000

# Database - Use strong credentials
DB_HOST=postgres
DB_PORT=5432
DB_USERNAME=asahome_user
DB_PASSWORD=<generate-strong-password>
DB_DATABASE=asahome_cloud
DB_SYNCHRONIZE=false
DB_LOGGING=false

# JWT - Generate secure secrets
JWT_SECRET=<generate-with-openssl-rand-base64-32>
JWT_EXPIRES_IN=15m
JWT_REFRESH_EXPIRES_IN=30d

# CORS - Restrict to your domains
CORS_ORIGINS=https://app.asahome.io,https://admin.asahome.io

# Rate Limiting
THROTTLE_TTL=60
THROTTLE_LIMIT=100

# Internal API Keys
INTERNAL_API_KEYS=<laravel-api-key>

Generate secure secrets:

# JWT Secret
openssl rand -base64 32

# Database Password
openssl rand -base64 24

# Internal API Key
openssl rand -base64 32

3. Configure SSL/TLS

Option A: Your Own Certificates

Place your SSL certificates in the nginx/ssl/ directory:

mkdir -p nginx/ssl
# Copy your certificates
cp /path/to/cert.pem nginx/ssl/
cp /path/to/key.pem nginx/ssl/

Use Certbot with Docker:

# Install certbot
docker run -it --rm \
-v /etc/letsencrypt:/etc/letsencrypt \
-v /var/lib/letsencrypt:/var/lib/letsencrypt \
-p 80:80 \
certbot/certbot certonly \
--standalone \
-d cloud.asahome.io

# Link certificates
ln -s /etc/letsencrypt/live/cloud.asahome.io/fullchain.pem nginx/ssl/cert.pem
ln -s /etc/letsencrypt/live/cloud.asahome.io/privkey.pem nginx/ssl/key.pem

4. Configure Nginx

Update nginx/conf.d/default.conf for production:

upstream backend {
server app:3000;
keepalive 32;
}

# Redirect HTTP to HTTPS
server {
listen 80;
server_name cloud.asahome.io;
return 301 https://$server_name$request_uri;
}

server {
listen 443 ssl http2;
server_name cloud.asahome.io;

# SSL Configuration
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;

# Security Headers
add_header Strict-Transport-Security "max-age=63072000" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;

# Rate Limiting
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;

# API Proxy
location /api {
limit_req zone=api burst=20 nodelay;

proxy_pass http://backend;
proxy_http_version 1.1;
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_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}

# WebSocket Proxy
location /tunnel {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
}
}

5. Build and Deploy

# Build production images
make prod-build

# Start services
make prod-up

# Run database migrations
docker-compose exec app npm run migration:run

# Verify deployment
make health

6. Verify Deployment

# Check all services are running
docker-compose ps

# Check API health
curl https://cloud.asahome.io/api/v1/health

# Check logs
make logs

Docker Compose Production

Create docker-compose.prod.yml:

version: '3.8'

services:
app:
build:
context: .
dockerfile: Dockerfile
target: production
restart: always
environment:
- NODE_ENV=production
env_file:
- .env.production
depends_on:
postgres:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/api/v1/health"]
interval: 30s
timeout: 10s
retries: 3

postgres:
image: postgres:16-alpine
restart: always
environment:
POSTGRES_USER: ${DB_USERNAME}
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: ${DB_DATABASE}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USERNAME}"]
interval: 10s
timeout: 5s
retries: 5

nginx:
image: nginx:alpine
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d:ro
- ./nginx/ssl:/etc/nginx/ssl:ro
depends_on:
- app

volumes:
postgres_data:

Health Monitoring

Health Check Endpoint

curl https://cloud.asahome.io/api/v1/health

Response:

{
"status": "ok",
"timestamp": "2024-01-15T10:30:00.000Z",
"service": "asahome-cloud",
"version": "1.0.0"
}

Container Health

# Check container status
docker-compose ps

# View resource usage
docker stats

# Check container health
docker inspect --format='{{json .State.Health}}' asahome-cloud-app-1

Log Monitoring

# All logs
docker-compose logs -f

# Application logs only
docker-compose logs -f app

# Last 100 lines
docker-compose logs --tail=100 app

Backup and Recovery

Database Backup

# Create backup
docker-compose exec postgres pg_dump -U ${DB_USERNAME} ${DB_DATABASE} > backup.sql

# Automated daily backup
0 2 * * * docker-compose exec -T postgres pg_dump -U asahome_user asahome_cloud > /backups/asahome_$(date +\%Y\%m\%d).sql

Database Restore

# Restore from backup
docker-compose exec -T postgres psql -U ${DB_USERNAME} ${DB_DATABASE} < backup.sql

Scaling

Horizontal Scaling

For high availability, run multiple app instances behind a load balancer:

# docker-compose.prod.yml
services:
app:
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure

Database Read Replicas

For read-heavy workloads, add PostgreSQL read replicas:

services:
postgres-replica:
image: postgres:16-alpine
environment:
POSTGRES_USER: ${DB_USERNAME}
POSTGRES_PASSWORD: ${DB_PASSWORD}
command: |
postgres
-c wal_level=replica
-c hot_standby=on

Security Checklist

Before going live:

  • Changed all default passwords
  • Generated strong JWT_SECRET
  • Configured CORS_ORIGINS for your domains only
  • SSL certificate installed and verified
  • Firewall rules configured
  • Database not exposed to public internet
  • Rate limiting configured
  • Monitoring and alerting set up
  • Backup strategy in place
  • Log aggregation configured

Rollback

If deployment fails:

# Stop current deployment
docker-compose down

# Restore previous image
docker-compose pull app:previous

# Start with previous version
docker-compose up -d

# Restore database if needed
docker-compose exec -T postgres psql -U ${DB_USERNAME} ${DB_DATABASE} < backup.sql