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/
Option B: Let's Encrypt (Recommended)
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