From dc2b67d300f16c29e22ea87ce54806046086d73e Mon Sep 17 00:00:00 2001 From: Karl Cordes Date: Thu, 7 Aug 2025 21:53:30 +1000 Subject: [PATCH] Add docker-compose.caddy and Makefile --- Makefile | 190 ++++++++++++++++++++++++++++ docker-compose.caddy-production.yml | 85 +++++++++++++ docker-compose.caddy-staging.yml | 61 +++++++++ 3 files changed, 336 insertions(+) create mode 100644 Makefile create mode 100644 docker-compose.caddy-production.yml create mode 100644 docker-compose.caddy-staging.yml diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..573ff7b2 --- /dev/null +++ b/Makefile @@ -0,0 +1,190 @@ +# CMC Sales Deployment Makefile for Caddy setup + +.PHONY: help staging production backup-staging backup-production restart-staging restart-production status logs clean caddy-reload caddy-logs + +# Default target +help: + @echo "CMC Sales Deployment Commands (Caddy version)" + @echo "" + @echo "Environments:" + @echo " staging Start staging environment" + @echo " staging-down Stop staging environment" + @echo " staging-logs Show staging logs" + @echo " restart-staging Rebuild and restart staging" + @echo "" + @echo " production Start production environment" + @echo " production-down Stop production environment" + @echo " production-logs Show production logs" + @echo " restart-production Rebuild and restart production" + @echo "" + @echo "Database:" + @echo " backup-staging Backup staging database" + @echo " backup-production Backup production database" + @echo "" + @echo "Caddy:" + @echo " caddy-status Show Caddy service status" + @echo " caddy-reload Reload Caddy configuration" + @echo " caddy-logs Show Caddy logs" + @echo " caddy-validate Validate Caddyfile" + @echo "" + @echo "Utility:" + @echo " status Show all container status" + @echo " clean Stop and remove all containers" + @echo " setup-auth Setup basic authentication" + +# Staging environment +staging: + @echo "Starting staging environment..." + docker compose -f docker-compose.caddy-staging.yml up -d + @echo "Staging environment started" + @echo "Access at: https://staging.cmc.springupsoftware.com" + +staging-down: + docker compose -f docker-compose.caddy-staging.yml down + +staging-logs: + docker compose -f docker-compose.caddy-staging.yml logs -f + +restart-staging: + @echo "Restarting staging environment..." + 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 + @echo "Staging environment restarted" + +# Production environment +production: + @echo "Starting production environment..." + docker compose -f docker-compose.caddy-production.yml up -d + @echo "Production environment started" + @echo "Access at: https://cmc.springupsoftware.com" + +production-down: + @echo "WARNING: This will stop the production environment!" + @read -p "Are you sure? (yes/no): " confirm && [ "$$confirm" = "yes" ] + docker compose -f docker-compose.caddy-production.yml down + +production-logs: + docker compose -f docker-compose.caddy-production.yml logs -f + +restart-production: + @echo "WARNING: This will restart the production environment!" + @read -p "Are you sure? (yes/no): " confirm && [ "$$confirm" = "yes" ] + 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 + @echo "Production environment restarted" + +# Database backups +backup-staging: + @echo "Creating staging database backup..." + ./scripts/backup-db.sh staging + +backup-production: + @echo "Creating production database backup..." + ./scripts/backup-db.sh production + +# Caddy management +caddy-status: + @echo "=== Caddy Status ===" + sudo systemctl status caddy --no-pager + +caddy-reload: + @echo "Reloading Caddy configuration..." + sudo systemctl reload caddy + @echo "Caddy reloaded successfully" + +caddy-logs: + @echo "=== Caddy Logs ===" + sudo journalctl -u caddy -f + +caddy-validate: + @echo "Validating Caddyfile..." + caddy validate --config Caddyfile + @echo "Caddyfile is valid" + +# Setup authentication +setup-auth: + @echo "Setting up basic authentication..." + ./scripts/setup-caddy-auth.sh + +# System status +status: + @echo "=== Container Status ===" + docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" + @echo "" + @echo "=== Caddy Status ===" + sudo systemctl is-active caddy || true + @echo "" + @echo "=== Port Usage ===" + sudo netstat -tlnp | grep -E ":(80|443|8091|8092|8093|8094|3306|3307) " || true + +# Logs +logs: + @echo "Which logs? [staging/production/caddy]" + @read env; \ + case $$env in \ + staging) docker compose -f docker-compose.caddy-staging.yml logs -f ;; \ + production) docker compose -f docker-compose.caddy-production.yml logs -f ;; \ + caddy) sudo journalctl -u caddy -f ;; \ + *) echo "Invalid option" ;; \ + esac + +# Cleanup +clean: + @echo "WARNING: This will stop and remove ALL CMC containers!" + @read -p "Are you sure? (yes/no): " confirm && [ "$$confirm" = "yes" ] + docker compose -f docker-compose.caddy-staging.yml down --volumes --remove-orphans + docker compose -f docker-compose.caddy-production.yml down --volumes --remove-orphans + docker system prune -f + @echo "Cleanup completed" + +# Health checks +health: + @echo "=== Health Checks ===" + @echo "Staging:" + @curl -s -o /dev/null -w " HTTPS %{http_code}: https://staging.cmc.springupsoftware.com/health\n" https://staging.cmc.springupsoftware.com/health -u admin:password || echo " Staging not accessible (update with correct auth)" + @curl -s -o /dev/null -w " Internal %{http_code}: http://localhost:8092/api/v1/health\n" http://localhost:8092/api/v1/health || echo " Staging Go not accessible" + @echo "Production:" + @curl -s -o /dev/null -w " HTTPS %{http_code}: https://cmc.springupsoftware.com/health\n" https://cmc.springupsoftware.com/health -u admin:password || echo " Production not accessible (update with correct auth)" + @curl -s -o /dev/null -w " Internal %{http_code}: http://localhost:8094/api/v1/health\n" http://localhost:8094/api/v1/health || echo " Production Go not accessible" + +# Deploy to staging +deploy-staging: + @echo "Deploying to staging..." + git pull origin main + $(MAKE) restart-staging + @echo "Staging deployment complete" + +# Deploy to production +deploy-production: + @echo "WARNING: This will deploy to PRODUCTION!" + @echo "Make sure you have tested thoroughly in staging first." + @read -p "Are you sure you want to deploy to production? (yes/no): " confirm && [ "$$confirm" = "yes" ] + git pull origin main + $(MAKE) backup-production + $(MAKE) restart-production + @echo "Production deployment complete" + +# First-time setup +initial-setup: + @echo "Running initial setup..." + @echo "1. Installing Caddy..." + sudo ./scripts/install-caddy.sh + @echo "" + @echo "2. Setting up authentication..." + ./scripts/setup-caddy-auth.sh + @echo "" + @echo "3. Copying Caddyfile..." + sudo cp Caddyfile /etc/caddy/Caddyfile + @echo "" + @echo "4. Starting Caddy..." + sudo systemctl start caddy + @echo "" + @echo "5. Starting containers..." + $(MAKE) staging + $(MAKE) production + @echo "" + @echo "Initial setup complete!" + @echo "Access staging at: https://staging.cmc.springupsoftware.com" + @echo "Access production at: https://cmc.springupsoftware.com" \ No newline at end of file diff --git a/docker-compose.caddy-production.yml b/docker-compose.caddy-production.yml new file mode 100644 index 00000000..882d517a --- /dev/null +++ b/docker-compose.caddy-production.yml @@ -0,0 +1,85 @@ +version: '3.8' + +services: + cmc-php-production: + build: + context: . + dockerfile: Dockerfile + platform: linux/amd64 + container_name: cmc-php-production + depends_on: + - db-production + ports: + - "127.0.0.1:8093:80" # Only accessible from localhost + volumes: + - production_pdf_data:/var/www/cmc-sales/app/webroot/pdf + - production_attachments_data:/var/www/cmc-sales/app/webroot/attachments_files + restart: unless-stopped + environment: + - APP_ENV=production + deploy: + resources: + limits: + cpus: '2.0' + memory: 2G + reservations: + cpus: '0.5' + memory: 512M + + db-production: + image: mariadb:latest + container_name: cmc-db-production + environment: + MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD_PRODUCTION} + MYSQL_DATABASE: cmc + MYSQL_USER: cmc + MYSQL_PASSWORD: ${DB_PASSWORD_PRODUCTION} + volumes: + - production_db_data:/var/lib/mysql + - ./backups:/backups:ro + restart: unless-stopped + # No external port exposure for security + deploy: + resources: + limits: + cpus: '2.0' + memory: 4G + reservations: + cpus: '0.5' + memory: 1G + + cmc-go-production: + build: + context: . + dockerfile: Dockerfile.go.production + container_name: cmc-go-production + environment: + DB_HOST: db-production + DB_PORT: 3306 + DB_USER: cmc + DB_PASSWORD: ${DB_PASSWORD_PRODUCTION} + DB_NAME: cmc + PORT: 8080 + APP_ENV: production + depends_on: + db-production: + condition: service_started + ports: + - "127.0.0.1:8094:8080" # Only accessible from localhost + volumes: + - production_pdf_data:/root/webroot/pdf + - ./credentials/production:/root/credentials:ro + restart: unless-stopped + deploy: + resources: + limits: + cpus: '2.0' + memory: 2G + reservations: + cpus: '0.5' + memory: 512M + +volumes: + production_db_data: + production_pdf_data: + production_attachments_data: \ No newline at end of file diff --git a/docker-compose.caddy-staging.yml b/docker-compose.caddy-staging.yml new file mode 100644 index 00000000..2a4856d2 --- /dev/null +++ b/docker-compose.caddy-staging.yml @@ -0,0 +1,61 @@ +version: '3.8' + +services: + cmc-php-staging: + build: + context: . + dockerfile: Dockerfile + platform: linux/amd64 + container_name: cmc-php-staging + depends_on: + - db-staging + ports: + - "127.0.0.1:8091:80" # Only accessible from localhost + volumes: + - staging_pdf_data:/var/www/cmc-sales/app/webroot/pdf + - staging_attachments_data:/var/www/cmc-sales/app/webroot/attachments_files + restart: unless-stopped + environment: + - APP_ENV=staging + + db-staging: + image: mariadb:latest + container_name: cmc-db-staging + environment: + MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD_STAGING} + MYSQL_DATABASE: cmc_staging + MYSQL_USER: cmc_staging + MYSQL_PASSWORD: ${DB_PASSWORD_STAGING} + volumes: + - staging_db_data:/var/lib/mysql + restart: unless-stopped + ports: + - "127.0.0.1:3307:3306" # Only accessible from localhost + + cmc-go-staging: + build: + context: . + dockerfile: Dockerfile.go.staging + container_name: cmc-go-staging + environment: + DB_HOST: db-staging + DB_PORT: 3306 + DB_USER: cmc_staging + DB_PASSWORD: ${DB_PASSWORD_STAGING} + DB_NAME: cmc_staging + PORT: 8080 + APP_ENV: staging + depends_on: + db-staging: + condition: service_started + ports: + - "127.0.0.1:8092:8080" # Only accessible from localhost + volumes: + - staging_pdf_data:/root/webroot/pdf + - ./credentials/staging:/root/credentials:ro + restart: unless-stopped + +volumes: + staging_db_data: + staging_pdf_data: + staging_attachments_data: \ No newline at end of file