94 lines
2.3 KiB
Markdown

# Production Deployment Guide
This guide describes how to deploy the Customer Portal in production with Docker Compose, Nginx reverse proxy, and automatic TLS renewal via Certbot.
## Prerequisites
- Domain name pointed to your server (A/AAAA records)
- Docker and Docker Compose installed
- Open ports 80 and 443
## Environment configuration
- Copy `.env.production.example` to `.env` at the repository root:
```bash
cp .env.production.example .env
```
- Fill in all required values, especially:
- DATABASE_URL (matches docker-compose Postgres credentials)
- REDIS_URL (usually redis://cache:6379)
- JWT_SECRET (strong, random)
- CORS_ORIGIN (e.g., https://yourdomain.com)
- BFF_PORT (e.g., 4000)
- NEXT_PUBLIC_API_BASE (e.g., https://yourdomain.com)
- Salesforce/WHMCS credentials and key path
## First-time TLS certificate
Run certbot once to issue a certificate (HTTP challenge):
```bash
docker compose -f docker/prod/docker-compose.yml run --rm \
-p 80:80 \
-e "CERTBOT_DOMAIN=yourdomain.com" \
-e "CERTBOT_EMAIL=you@example.com" \
certbot certonly --webroot -w /var/www/certbot \
-d yourdomain.com --agree-tos --no-eff-email
```
- Certificates will be stored under the `letsencrypt` volume mounted at `/etc/letsencrypt`.
- Nginx is configured to use `/etc/letsencrypt/live/portal` by default. You can update the path or create a symlink to match your issued cert name.
## Deploy
```bash
pnpm prod:deploy
```
This will:
- Build images
- Start database and cache, wait for health
- Run migrations
- Start proxy, frontend, backend
## Health checks
- Proxy/Frontend: https://yourdomain.com/healthz
- Backend: proxied at https://yourdomain.com/api/health (and container-local http://backend:4000/health)
## Renewals
- A certbot sidecar runs and renews every ~12 hours. On renew, it reloads Nginx.
## Notes on security
- HSTS, modern TLS ciphers, and security headers are enabled in Nginx
- Backend disables x-powered-by and supports trust proxy
- Avoid exposing container ports directly; use the proxy service
- Keep `.env` outside of version control
## Updates
```bash
pnpm prod:update
```
This rebuilds and recreates `frontend` and `backend` without downtime.
## Troubleshooting
- Check logs:
```bash
pnpm prod:logs
```
- Validate Nginx config inside container:
```bash
docker exec -it portal-proxy nginx -t
```