Yolo changes to make this work
This commit is contained in:
parent
6f538e3e4d
commit
2ea0398f41
344
DEPLOYMENT-CADDY.md
Normal file
344
DEPLOYMENT-CADDY.md
Normal file
|
|
@ -0,0 +1,344 @@
|
|||
# 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)
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# Generate password hashes for Caddy
|
||||
./scripts/setup-caddy-auth.sh
|
||||
|
||||
# Or manually
|
||||
caddy hash-password
|
||||
# Copy the hash and update Caddyfile
|
||||
```
|
||||
|
||||
### 4. Configure Caddy
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# Edit Caddyfile
|
||||
sudo nano /etc/caddy/Caddyfile
|
||||
|
||||
# Validate configuration
|
||||
caddy validate --config /etc/caddy/Caddyfile
|
||||
|
||||
# Reload configuration (zero downtime)
|
||||
sudo systemctl reload caddy
|
||||
```
|
||||
|
||||
### Monitoring
|
||||
|
||||
```bash
|
||||
# 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:
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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:
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
```
|
||||
|
|
@ -45,8 +45,8 @@ Ensure these DNS records point to your server:
|
|||
### 1. Clone Repository
|
||||
|
||||
```bash
|
||||
cd /opt
|
||||
sudo git clone <repository-url> cmc-sales
|
||||
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
|
||||
```
|
||||
|
|
@ -58,7 +58,7 @@ cd cmc-sales
|
|||
cp .env.staging go-app/.env.staging
|
||||
cp .env.production go-app/.env.production
|
||||
|
||||
# Edit with actual passwords
|
||||
# Edit with actual passwords -- up to this.
|
||||
nano .env.staging
|
||||
nano .env.production
|
||||
|
||||
|
|
@ -94,7 +94,7 @@ go run cmd/auth/main.go
|
|||
docker compose -f docker-compose.proxy.yml up -d
|
||||
|
||||
# Setup SSL certificates using Lego
|
||||
./scripts/setup-lego-certs.sh admin@springupsoftware.com
|
||||
./scripts/setup-lego-certs.sh accounts@springupsoftware.com
|
||||
|
||||
# Verify certificates
|
||||
./scripts/lego-list-certs.sh
|
||||
|
|
@ -128,8 +128,14 @@ docker compose -f docker-compose.staging.yml up -d
|
|||
# Start production environment
|
||||
docker compose -f docker-compose.production.yml up -d
|
||||
|
||||
# Wait for services to be ready
|
||||
sleep 10
|
||||
|
||||
# Start reverse proxy (after both environments are running)
|
||||
docker compose -f docker-compose.proxy.yml up -d
|
||||
|
||||
# Or use the make command for full stack deployment
|
||||
make full-stack
|
||||
```
|
||||
|
||||
### Updating Applications
|
||||
|
|
|
|||
|
|
@ -43,4 +43,6 @@
|
|||
*
|
||||
*/
|
||||
//EOF
|
||||
|
||||
require_once(dirname(__FILE__) . '/php7_compat.php');
|
||||
?>
|
||||
96
app/config/php7_compat.php
Normal file
96
app/config/php7_compat.php
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
/**
|
||||
* PHP 7 Compatibility layer for CakePHP 1.2.5
|
||||
* Include this file in your bootstrap.php
|
||||
*/
|
||||
|
||||
// Fix for deprecated $HTTP_RAW_POST_DATA
|
||||
if (!isset($HTTP_RAW_POST_DATA)) {
|
||||
$HTTP_RAW_POST_DATA = file_get_contents('php://input');
|
||||
}
|
||||
|
||||
// Replace deprecated ereg functions
|
||||
if (!function_exists('ereg')) {
|
||||
function ereg($pattern, $string, &$regs = array()) {
|
||||
return preg_match('~' . $pattern . '~', $string, $regs);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('eregi')) {
|
||||
function eregi($pattern, $string, &$regs = array()) {
|
||||
return preg_match('~' . $pattern . '~i', $string, $regs);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('ereg_replace')) {
|
||||
function ereg_replace($pattern, $replacement, $string) {
|
||||
return preg_replace('~' . $pattern . '~', $replacement, $string);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('eregi_replace')) {
|
||||
function eregi_replace($pattern, $replacement, $string) {
|
||||
return preg_replace('~' . $pattern . '~i', $replacement, $string);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('split')) {
|
||||
function split($pattern, $string, $limit = -1) {
|
||||
return preg_split('~' . $pattern . '~', $string, $limit);
|
||||
}
|
||||
}
|
||||
|
||||
// Fix for mysql_* functions if needed
|
||||
if (!function_exists('mysql_connect')) {
|
||||
function mysql_connect($server, $username, $password, $new_link = false, $client_flags = 0) {
|
||||
return mysqli_connect($server, $username, $password);
|
||||
}
|
||||
|
||||
function mysql_select_db($database_name, $link_identifier = null) {
|
||||
return mysqli_select_db($link_identifier, $database_name);
|
||||
}
|
||||
|
||||
function mysql_query($query, $link_identifier = null) {
|
||||
return mysqli_query($link_identifier, $query);
|
||||
}
|
||||
|
||||
function mysql_fetch_array($result, $result_type = MYSQLI_BOTH) {
|
||||
return mysqli_fetch_array($result, $result_type);
|
||||
}
|
||||
|
||||
function mysql_fetch_assoc($result) {
|
||||
return mysqli_fetch_assoc($result);
|
||||
}
|
||||
|
||||
function mysql_fetch_row($result) {
|
||||
return mysqli_fetch_row($result);
|
||||
}
|
||||
|
||||
function mysql_num_rows($result) {
|
||||
return mysqli_num_rows($result);
|
||||
}
|
||||
|
||||
function mysql_affected_rows($link_identifier = null) {
|
||||
return mysqli_affected_rows($link_identifier);
|
||||
}
|
||||
|
||||
function mysql_insert_id($link_identifier = null) {
|
||||
return mysqli_insert_id($link_identifier);
|
||||
}
|
||||
|
||||
function mysql_close($link_identifier = null) {
|
||||
return mysqli_close($link_identifier);
|
||||
}
|
||||
|
||||
function mysql_error($link_identifier = null) {
|
||||
return mysqli_error($link_identifier);
|
||||
}
|
||||
|
||||
function mysql_errno($link_identifier = null) {
|
||||
return mysqli_errno($link_identifier);
|
||||
}
|
||||
|
||||
function mysql_real_escape_string($unescaped_string, $link_identifier = null) {
|
||||
return mysqli_real_escape_string($link_identifier, $unescaped_string);
|
||||
}
|
||||
}
|
||||
|
|
@ -12,8 +12,7 @@ services:
|
|||
volumes:
|
||||
- production_pdf_data:/var/www/cmc-sales/app/webroot/pdf
|
||||
- production_attachments_data:/var/www/cmc-sales/app/webroot/attachments_files
|
||||
networks:
|
||||
- cmc-production-network
|
||||
network_mode: bridge
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- APP_ENV=production
|
||||
|
|
@ -39,8 +38,7 @@ services:
|
|||
depends_on:
|
||||
- cmc-php-production
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- cmc-production-network
|
||||
network_mode: bridge
|
||||
environment:
|
||||
- NGINX_ENVSUBST_TEMPLATE_SUFFIX=.template
|
||||
|
||||
|
|
@ -57,8 +55,7 @@ services:
|
|||
volumes:
|
||||
- production_db_data:/var/lib/mysql
|
||||
- ./backups:/backups:ro # Backup restore directory
|
||||
networks:
|
||||
- cmc-production-network
|
||||
network_mode: bridge
|
||||
restart: unless-stopped
|
||||
# No external port exposure for security
|
||||
deploy:
|
||||
|
|
@ -90,8 +87,7 @@ services:
|
|||
volumes:
|
||||
- production_pdf_data:/root/webroot/pdf
|
||||
- ./credentials/production:/root/credentials:ro # Production Gmail credentials
|
||||
networks:
|
||||
- cmc-production-network
|
||||
network_mode: bridge
|
||||
restart: unless-stopped
|
||||
deploy:
|
||||
resources:
|
||||
|
|
@ -107,6 +103,3 @@ volumes:
|
|||
production_pdf_data:
|
||||
production_attachments_data:
|
||||
|
||||
networks:
|
||||
cmc-production-network:
|
||||
driver: bridge
|
||||
|
|
@ -13,8 +13,7 @@ services:
|
|||
volumes:
|
||||
- staging_pdf_data:/var/www/cmc-sales/app/webroot/pdf
|
||||
- staging_attachments_data:/var/www/cmc-sales/app/webroot/attachments_files
|
||||
networks:
|
||||
- cmc-staging-network
|
||||
network_mode: bridge
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- APP_ENV=staging
|
||||
|
|
@ -31,8 +30,7 @@ services:
|
|||
depends_on:
|
||||
- cmc-php-staging
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- cmc-staging-network
|
||||
network_mode: bridge
|
||||
environment:
|
||||
- NGINX_ENVSUBST_TEMPLATE_SUFFIX=.template
|
||||
|
||||
|
|
@ -46,8 +44,7 @@ services:
|
|||
MYSQL_PASSWORD: ${DB_PASSWORD_STAGING}
|
||||
volumes:
|
||||
- staging_db_data:/var/lib/mysql
|
||||
networks:
|
||||
- cmc-staging-network
|
||||
network_mode: bridge
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "3307:3306" # Different port for staging DB access
|
||||
|
|
@ -73,8 +70,7 @@ services:
|
|||
volumes:
|
||||
- staging_pdf_data:/root/webroot/pdf
|
||||
- ./credentials/staging:/root/credentials:ro # Staging Gmail credentials
|
||||
networks:
|
||||
- cmc-staging-network
|
||||
network_mode: bridge
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
|
|
@ -82,6 +78,3 @@ volumes:
|
|||
staging_pdf_data:
|
||||
staging_attachments_data:
|
||||
|
||||
networks:
|
||||
cmc-staging-network:
|
||||
driver: bridge
|
||||
Loading…
Reference in a new issue