cmc-sales/DEPLOYMENT-CADDY.md
2025-08-08 11:24:48 +10:00

8 KiB

CMC Sales Deployment Guide with Caddy

Overview

This guide covers deploying the CMC Sales application to a Debian 12 VM using Caddy as the reverse proxy with automatic HTTPS.

Architecture

  • Production: https://cmc.springupsoftware.com
  • Staging: https://staging.cmc.springupsoftware.com
  • Reverse Proxy: Caddy (running on host)
  • Applications: Docker containers
    • CakePHP legacy app
    • Go modern app
    • MariaDB database
  • SSL: Automatic via Caddy (Let's Encrypt)
  • Authentication: Basic auth configured in Caddy

Prerequisites

1. Server Setup (Debian 12)

# Update system
sudo apt update && sudo apt upgrade -y

# Install Docker
sudo apt install -y docker.io docker-compose-plugin
sudo systemctl enable docker
sudo systemctl start docker

# Add user to docker group
sudo usermod -aG docker $USER
# Log out and back in

# Create directories
sudo mkdir -p /var/backups/cmc-sales
sudo chown $USER:$USER /var/backups/cmc-sales

2. Install Caddy

# Run the installation script
sudo ./scripts/install-caddy.sh

# Or manually install
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy

3. DNS Configuration

Ensure DNS records point to your server:

  • cmc.springupsoftware.com → Server IP
  • staging.cmc.springupsoftware.com → Server IP

Initial Deployment

1. Clone Repository

cd /home/cmc
git clone git@code.springupsoftware.com:cmc/cmc-sales.git cmc-sales
sudo chown -R $USER:$USER cmc-sales
cd cmc-sales

2. Environment Configuration

# Copy environment files
cp .env.staging go-app/.env.staging
cp .env.production go-app/.env.production

# Edit with actual passwords
nano .env.staging
nano .env.production

# Create credential directories
mkdir -p credentials/staging credentials/production

3. Setup Basic Authentication

# Generate password hashes for Caddy
./scripts/setup-caddy-auth.sh

# Or manually
caddy hash-password
# Copy the hash and update Caddyfile

4. Configure Caddy

# Copy Caddyfile
sudo cp Caddyfile /etc/caddy/Caddyfile

# Edit to update passwords and email
sudo nano /etc/caddy/Caddyfile

# Validate configuration
caddy validate --config /etc/caddy/Caddyfile

# Start Caddy
sudo systemctl start caddy
sudo systemctl status caddy

5. Gmail OAuth Setup

Same as before - set up OAuth credentials for each environment:

  • Staging: credentials/staging/credentials.json
  • Production: credentials/production/credentials.json

6. Database Initialization

# Start database containers
docker compose -f docker-compose.caddy-staging.yml up -d db-staging
docker compose -f docker-compose.caddy-production.yml up -d db-production

# Wait for databases
sleep 30

# Restore production database (if you have a backup)
./scripts/restore-db.sh production /path/to/backup.sql.gz

Deployment Commands

Starting Services

# Start staging environment
docker compose -f docker-compose.caddy-staging.yml up -d

# Start production environment  
docker compose -f docker-compose.caddy-production.yml up -d

# Reload Caddy configuration
sudo systemctl reload caddy

Updating Applications

# Pull latest code
git pull origin main

# Update staging
docker compose -f docker-compose.caddy-staging.yml down
docker compose -f docker-compose.caddy-staging.yml build --no-cache
docker compose -f docker-compose.caddy-staging.yml up -d

# Test staging, then update production
docker compose -f docker-compose.caddy-production.yml down
docker compose -f docker-compose.caddy-production.yml build --no-cache
docker compose -f docker-compose.caddy-production.yml up -d

Caddy Management

Configuration

# Edit Caddyfile
sudo nano /etc/caddy/Caddyfile

# Validate configuration
caddy validate --config /etc/caddy/Caddyfile

# Reload configuration (zero downtime)
sudo systemctl reload caddy

Monitoring

# Check Caddy status
sudo systemctl status caddy

# View Caddy logs
sudo journalctl -u caddy -f

# View access logs
sudo tail -f /var/log/caddy/cmc-production.log
sudo tail -f /var/log/caddy/cmc-staging.log

SSL Certificates

Caddy handles SSL automatically! To check certificates:

# List certificates
sudo ls -la /var/lib/caddy/.local/share/caddy/certificates/

# Force certificate renewal (rarely needed)
sudo systemctl stop caddy
sudo rm -rf /var/lib/caddy/.local/share/caddy/certificates/*
sudo systemctl start caddy

Container Port Mapping

Service Container Port Host Port Access
cmc-php-staging 80 8091 localhost only
cmc-go-staging 8080 8092 localhost only
cmc-db-staging 3306 3307 localhost only
cmc-php-production 80 8093 localhost only
cmc-go-production 8080 8094 localhost only
cmc-db-production 3306 - internal only

Monitoring and Maintenance

Health Checks

# Check all containers
docker ps

# Check application health
curl -I https://cmc.springupsoftware.com
curl -I https://staging.cmc.springupsoftware.com

# Internal health checks (from server)
curl http://localhost:8094/api/v1/health  # Production Go
curl http://localhost:8092/api/v1/health  # Staging Go

Database Backups

Same backup scripts work:

# Manual backup
./scripts/backup-db.sh production
./scripts/backup-db.sh staging

# Automated backups
sudo crontab -e
# Add:
# 0 2 * * * /home/cmc/cmc-sales/scripts/backup-db.sh production
# 0 3 * * * /home/cmc/cmc-sales/scripts/backup-db.sh staging

Security Benefits with Caddy

  1. Automatic HTTPS: No manual certificate management
  2. Modern TLS: Always up-to-date TLS configuration
  3. OCSP Stapling: Enabled by default
  4. Security Headers: Easy to configure
  5. Rate Limiting: Built-in support

Troubleshooting

Caddy Issues

# Check Caddy configuration
caddy validate --config /etc/caddy/Caddyfile

# Check Caddy service
sudo systemctl status caddy
sudo journalctl -u caddy -n 100

# Test reverse proxy
curl -v http://localhost:8094/api/v1/health

Container Issues

# Check container logs
docker compose -f docker-compose.caddy-production.yml logs -f

# Restart specific service
docker compose -f docker-compose.caddy-production.yml restart cmc-go-production

SSL Issues

# Caddy automatically handles SSL, but if issues arise:
# 1. Check DNS is resolving correctly
dig cmc.springupsoftware.com

# 2. Check Caddy can reach Let's Encrypt
sudo journalctl -u caddy | grep -i acme

# 3. Ensure ports 80 and 443 are open
sudo ufw status

Advantages of Caddy Setup

  1. Simpler Configuration: Caddyfile is more readable than nginx
  2. Automatic HTTPS: No certbot or lego needed
  3. Zero-Downtime Reloads: Config changes without dropping connections
  4. Better Performance: More efficient than nginx for this use case
  5. Native Rate Limiting: Built-in without additional modules
  6. Automatic Certificate Renewal: No cron jobs needed

Migration from Nginx

If migrating from the nginx setup:

  1. Stop nginx containers: docker compose -f docker-compose.proxy.yml down
  2. Install and configure Caddy
  3. Start new containers with caddy compose files
  4. Update DNS if needed
  5. Monitor logs during transition

File Structure

/home/cmc/cmc-sales/
├── docker-compose.caddy-staging.yml
├── docker-compose.caddy-production.yml
├── Caddyfile
├── credentials/
│   ├── staging/
│   └── production/
├── scripts/
│   ├── backup-db.sh
│   ├── restore-db.sh
│   ├── install-caddy.sh
│   └── setup-caddy-auth.sh
└── .env files

/etc/caddy/
└── Caddyfile (deployed config)

/var/log/caddy/
├── cmc-production.log
└── cmc-staging.log