413 lines
9.7 KiB
Markdown

# Multi-Provider Web App Workspace
This workspace demonstrates a production-ready web application deployment spanning three cloud providers:
- **DigitalOcean**: Web servers and load balancing (NYC region)
- **AWS**: Managed PostgreSQL database with high availability (US-East region)
- **Hetzner**: Backup storage and disaster recovery (Germany region)
## Why Three Providers?
This architecture optimizes cost, performance, and reliability:
- **DigitalOcean** (~$77/month): Cost-effective compute with simple management
- **AWS RDS** (~$75/month): Managed database with automatic failover
- **Hetzner** (~$13/month): Affordable backup storage
- **Total**: ~$165/month (vs $300+ for equivalent all-cloud setup)
## Architecture Overview
```bash
┌─────────────────────────────────────────────┐
│ Client Requests │
└──────────────┬──────────────────────────────┘
│ HTTPS/HTTP
┌───────▼─────────┐
│ DigitalOcean LB │
└───────┬─────────┘
┌────────┼────────┐
│ │ │
┌─▼──┐ ┌─▼──┐ ┌─▼──┐
│Web │ │Web │ │Web │ (DigitalOcean Droplets)
1 │ │ 2 │ │ 3
└──┬─┘ └──┬─┘ └──┬─┘
│ │ │
└───────┼───────┘
│ VPN Tunnel
┌───────▼────────────┐
│ AWS RDS (PG)(us-east-1)
│ Multi-AZ Cluster │
└────────┬───────────┘
│ Replication
┌──────▼──────────┐
│ Hetzner Volume │ (nbg1 - Germany)
│ Backups │
└─────────────────┘
```
## Prerequisites
### 1. Cloud Accounts
- **DigitalOcean**: Account with API token
- **AWS**: Account with access keys
- **Hetzner**: Account with API token
### 2. Environment Variables
Set these before deployment:
```javascript
export DIGITALOCEAN_TOKEN="dop_v1_abc123def456ghi789jkl012mno"
export AWS_ACCESS_KEY_ID="AKIA1234567890ABCDEF"
export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG+j/zI0m1234567890ab"
export HCLOUD_TOKEN="MC4wNTI1YmE1M2E4YmE0YTQzMTQyZTdlODYy"
```
### 3. SSH Key Setup
#### DigitalOcean
```bash
# Upload your SSH public key
doctl compute ssh-key create provisioning-key
--public-key-from-file ~/.ssh/id_rsa.pub
# Note the key ID for workspace.ncl
doctl compute ssh-key list
```
#### AWS
```bash
# Create EC2 key pair (if needed)
aws ec2 create-key-pair --key-name provisioning-key
--query 'KeyMaterial' --output text > provisioning-key.pem
chmod 600 provisioning-key.pem
```
#### Hetzner
```bash
# Upload SSH key
hcloud ssh-key create --name provisioning-key
--public-key-from-file ~/.ssh/id_rsa.pub
# List keys
hcloud ssh-key list
```
### 4. DNS Setup
Update `workspace.ncl` with your domain:
- Replace `your-certificate-id` with actual AWS certificate ID
- Update load balancer CNAME to point to your domain
## Deployment
### Step 1: Configure the Workspace
Edit `workspace.ncl` to:
- Set your SSH key IDs
- Update certificate ID for HTTPS
- Set domain names
- Adjust instance counts if needed
Edit `config.toml` to:
- Set correct environment variable names
- Adjust thresholds and settings
### Step 2: Validate Configuration
```toml
# Validate Nickel syntax
nickel export workspace.ncl | jq .
# Validate provider credentials
provisioning provider verify digitalocean
provisioning provider verify aws
provisioning provider verify hetzner
```
### Step 3: Deploy
```bash
# Using provided deploy script
./deploy.nu
# Or manually via provisioning CLI
provisioning workspace deploy --config config.toml
```
### Step 4: Verify Deployment
```bash
# List resources per provider
doctl compute droplet list
aws rds describe-db-instances
hcloud volume list
# Test load balancer
curl http://your-domain.com/health
```
## Post-Deployment Configuration
### 1. Application Deployment
SSH into web servers and deploy application:
```bash
# Get web server IPs
doctl compute droplet list --format Name,PublicIPv4
# SSH to first server
ssh root@198.51.100.15
# Deploy application
cd /var/www
git clone https://github.com/your-org/web-app.git
cd web-app
./deploy.sh
```
### 2. Database Configuration
Connect to RDS database and initialize schema:
```bash
# Get RDS endpoint
aws rds describe-db-instances --query 'DBInstances[0].Endpoint.Address'
# Connect and initialize
psql -h webapp-db.c9akciq32.us-east-1.rds.amazonaws.com -U admin -d defaultdb < schema.sql
```
### 3. DNS Configuration
Point your domain to the load balancer:
```bash
# Get load balancer IP
doctl compute load-balancer list
# Update DNS CNAME
# Add CNAME record: app.example.com -> lb-123456789.nyc3.digitalocean.com
```
### 4. SSL/TLS Certificate
Use AWS Certificate Manager:
```bash
# Request certificate
aws acm request-certificate
--domain-name app.example.com
--validation-method DNS
# Validate and get certificate ID
aws acm list-certificates | grep app.example.com
# Update workspace.ncl with certificate ID
```
## Monitoring
### DigitalOcean Monitoring
- CPU usage tracked per droplet
- Memory usage alerts on Droplet greater than 85%
- Disk space alerts on greater than 90% full
### AWS CloudWatch
- RDS database metrics (CPU, connections, disk)
- Automatic failover notifications
- Slow query logging
### Hetzner Monitoring
- Volume usage tracking
- Manual monitoring script via cron
### Application Monitoring
Implement application-level monitoring:
```bash
# SSH to web server
ssh root@198.51.100.15
# Check app logs
tail -f /var/www/app/logs/application.log
# Monitor system resources
top
iostat -x 1
# Check database connection pool
psql -h webapp-db.c9akciq32.us-east-1.rds.amazonaws.com -c "SELECT count(plus) FROM pg_stat_activity;"
```
## Backup and Recovery
### Automated Backups
- **RDS**: Daily backups retained for 30 days (AWS handles)
- **Application Data**: Weekly backups to Hetzner volume
- **Configuration**: Version control via Git
### Manual Backup
```bash
# Backup RDS to Hetzner volume
ssh hetzner-backup-volume
# Mount Hetzner volume (if not mounted)
sudo mount /dev/sdb /mnt/backups
# Backup RDS database
pg_dump -h webapp-db.c9akciq32.us-east-1.rds.amazonaws.com -U admin -d defaultdb |
gzip > /mnt/backups/db-$(date +%Y%m%d).sql.gz
```
### Recovery Procedure
1. **Web Server Failure**: Load balancer automatically redirects to healthy server
2. **Database Failure**: RDS Multi-AZ automatic failover
3. **Complete Failure**: Restore from Hetzner backup volume
## Scaling
### Add More Web Servers
Edit `workspace.ncl`:
```nickel
droplets = digitalocean.Droplet & {
name = "web-server",
region = "nyc3",
size = "s-2vcpu-4gb",
count = 5
}
```
Redeploy:
```bash
./deploy.nu
```
### Upgrade Database
Edit `workspace.ncl`:
```nickel
database_tier = aws.RDS & {
identifier = "webapp-db",
instance_class = "db.t3.large"
}
```
Redeploy with minimal downtime (Multi-AZ handles switchover).
## Cost Optimization
### Reduce Costs
1. **Droplets**: Use smaller size or fewer instances
2. **Database**: Switch to smaller db.t3.small (approximately $30/month)
3. **Storage**: Reduce backup volume size
4. **Data Transfer**: Monitor and optimize outbound traffic
### Monitor Costs
```bash
# DigitalOcean estimated bill
doctl billing get
# AWS Cost Explorer
aws ce get-cost-and-usage --time-period Start=2024-01-01,End=2024-01-31
# Hetzner manual tracking via console
# Navigate to https://console.hetzner.cloud/billing
```
## Troubleshooting
### Issue: Web Servers Unreachable
**Diagnosis**:
```bash
doctl compute droplet list
doctl compute firewall list-rules firewall-id
```
**Solution**:
- Check firewall allows ports 80, 443
- Verify droplets have public IPs
- Check web server application status
### Issue: Database Connection Failure
**Diagnosis**:
```bash
aws rds describe-db-instances
aws security-group describe-security-groups
```
**Solution**:
- Verify RDS security group allows port 5432 from web servers
- Check RDS status is "available"
- Verify connection string in application
### Issue: Backup Volume Not Mounted
**Diagnosis**:
```bash
hcloud volume list
ssh hetzner-volume
lsblk
```
**Solution**:
```bash
sudo mkfs.ext4 /dev/sdb
sudo mount /dev/sdb /mnt/backups
echo '/dev/sdb /mnt/backups ext4 defaults,nofail 0 0' | sudo tee -a /etc/fstab
```
## Cleanup
To destroy all resources:
```bash
# This will delete everything - use carefully
provisioning workspace destroy --config config.toml
# Or manually
doctl compute droplet delete web-server-1 web-server-2 web-server-3
doctl compute load-balancer delete web-lb
aws rds delete-db-instance --db-instance-identifier webapp-db --skip-final-snapshot
hcloud volume delete webapp-backups
```
## Next Steps
1. **SSL/TLS**: Update certificate and enable HTTPS
2. **Auto-scaling**: Add DigitalOcean autoscaling based on load
3. **Multi-region**: Add additional AWS RDS read replicas in other regions
4. **Disaster Recovery**: Test failover procedures
5. **Cost Optimization**: Review and optimize resource sizes
## Support
For issues or questions:
- Review the multi-provider deployment guide
- Check provider-specific documentation
- Review workspace logs with debug flag: ./deploy.nu --debug
## Files
- `workspace.ncl`: Infrastructure definition (Nickel)
- `config.toml`: Provider credentials and settings
- `deploy.nu`: Deployment automation script (Nushell)
- `README.md`: This file