# 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