From c5931ab7f0a69a7d713260802de3d7f8bb04d57b Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 23 Nov 2025 21:29:51 +0000 Subject: [PATCH] Add DigitalOcean droplet deployment with GitHub Actions Complete deployment setup for agents.jeffemmett.com: - GitHub Actions workflow for automatic deployment to droplet - Nginx configuration with SSL support - Automated setup script for initial droplet configuration - Comprehensive deployment guide with troubleshooting - Supports deployment to both Cloudflare Pages and droplet Features: - Auto-deploy on push to main - SSL with Let's Encrypt - Optimized nginx config with caching and compression - Detailed documentation and setup instructions --- .github/workflows/deploy-droplet.yml | 67 ++++++++ deployment/DEPLOYMENT_GUIDE.md | 236 +++++++++++++++++++++++++++ deployment/README.md | 69 ++++++++ deployment/nginx-config.conf | 56 +++++++ deployment/setup-droplet.sh | 95 +++++++++++ 5 files changed, 523 insertions(+) create mode 100644 .github/workflows/deploy-droplet.yml create mode 100644 deployment/DEPLOYMENT_GUIDE.md create mode 100644 deployment/README.md create mode 100644 deployment/nginx-config.conf create mode 100755 deployment/setup-droplet.sh diff --git a/.github/workflows/deploy-droplet.yml b/.github/workflows/deploy-droplet.yml new file mode 100644 index 0000000..8fc0cba --- /dev/null +++ b/.github/workflows/deploy-droplet.yml @@ -0,0 +1,67 @@ +name: Deploy to DigitalOcean Droplet + +on: + push: + branches: + - main + workflow_dispatch: + +jobs: + deploy: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + + - name: Install dependencies + run: npm ci + + - name: Generate dashboard + run: python3 generate_index.py + + - name: Deploy to Droplet + uses: appleboy/ssh-action@v1.0.0 + with: + host: ${{ secrets.DROPLET_HOST }} + username: ${{ secrets.DROPLET_USER }} + key: ${{ secrets.DROPLET_SSH_KEY }} + script: | + # Navigate to deployment directory + cd /var/www/agents.jeffemmett.com || exit 1 + + # Pull latest changes + git fetch origin main + git reset --hard origin/main + + # Install dependencies and generate dashboard + npm ci + python3 generate_index.py + + # Set proper permissions + chown -R www-data:www-data /var/www/agents.jeffemmett.com + + # Reload nginx + systemctl reload nginx + + echo "✅ Deployment completed successfully!" + + - name: Notify deployment status + if: always() + run: | + if [ ${{ job.status }} == 'success' ]; then + echo "🚀 Successfully deployed to https://agents.jeffemmett.com" + else + echo "❌ Deployment failed" + exit 1 + fi diff --git a/deployment/DEPLOYMENT_GUIDE.md b/deployment/DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000..953fb62 --- /dev/null +++ b/deployment/DEPLOYMENT_GUIDE.md @@ -0,0 +1,236 @@ +# Deployment Guide for agents.jeffemmett.com + +This guide will help you deploy the Infinite Agents dashboard to your DigitalOcean droplet with automatic GitHub Actions deployments. + +## 🎯 Overview + +- **Production URL**: https://agents.jeffemmett.com +- **Droplet IP**: 143.198.39.165 +- **Web Server**: Nginx with SSL (Let's Encrypt) +- **Auto-Deploy**: GitHub Actions on push to `main` + +## 📋 Prerequisites + +1. DigitalOcean droplet at 143.198.39.165 +2. Domain `agents.jeffemmett.com` DNS configured in Cloudflare +3. SSH access to the droplet +4. GitHub repository access + +## 🚀 Initial Setup + +### Step 1: Configure DNS in Cloudflare + +In Cloudflare DNS settings for `jeffemmett.com`: + +``` +Type: A +Name: agents +Content: 143.198.39.165 +Proxy status: DNS only (gray cloud) +TTL: Auto +``` + +**Important**: Set to "DNS only" (not proxied) for initial SSL setup. + +### Step 2: Run Setup Script on Droplet + +SSH into your droplet and run the setup script: + +```bash +# SSH into droplet +ssh root@143.198.39.165 + +# Clone the repository temporarily to get setup script +git clone https://github.com/Jeff-Emmett/infinite-agents.git /tmp/setup +cd /tmp/setup + +# Make script executable and run it +chmod +x deployment/setup-droplet.sh +./deployment/setup-droplet.sh +``` + +The script will: +- Install nginx, Node.js, Python +- Clone the repository to `/var/www/agents.jeffemmett.com` +- Configure nginx with SSL +- Set up automatic SSL renewal +- Deploy the site + +### Step 3: Configure GitHub Secrets + +Add the following secrets to your GitHub repository: + +**Go to**: Repository → Settings → Secrets and variables → Actions → New repository secret + +Add these three secrets: + +1. **DROPLET_HOST** + ``` + 143.198.39.165 + ``` + +2. **DROPLET_USER** + ``` + root + ``` + +3. **DROPLET_SSH_KEY** + - Your private SSH key for the droplet + - To get it: `cat ~/.ssh/id_rsa` (on your local machine) + - Copy the entire key including `-----BEGIN` and `-----END` lines + +### Step 4: Test Deployment + +Push a change to the `main` branch or trigger the workflow manually: + +```bash +# Trigger manually via GitHub UI +Go to: Actions → Deploy to DigitalOcean Droplet → Run workflow + +# Or push a change +git push origin main +``` + +## 🔧 Manual Deployment (if needed) + +If you need to deploy manually: + +```bash +ssh root@143.198.39.165 +cd /var/www/agents.jeffemmett.com +git pull origin main +npm ci +python3 generate_index.py +chown -R www-data:www-data . +systemctl reload nginx +``` + +## 📊 Monitoring & Logs + +### Check nginx status +```bash +systemctl status nginx +``` + +### View nginx logs +```bash +# Access log +tail -f /var/log/nginx/agents.jeffemmett.com-access.log + +# Error log +tail -f /var/log/nginx/agents.jeffemmett.com-error.log +``` + +### Test nginx configuration +```bash +nginx -t +``` + +## 🔐 SSL Certificate + +SSL certificates are managed by Let's Encrypt and auto-renew. + +### Check certificate status +```bash +certbot certificates +``` + +### Manual renewal (if needed) +```bash +certbot renew +systemctl reload nginx +``` + +## 🔄 Updating the Site + +Updates are automatic! Just push to `main`: + +1. Make changes locally +2. Commit and push to `main` +3. GitHub Actions automatically deploys +4. Site updates in ~2 minutes + +## 🐛 Troubleshooting + +### Site not loading? +- Check DNS propagation: `dig agents.jeffemmett.com` +- Verify nginx is running: `systemctl status nginx` +- Check nginx logs for errors + +### Deployment failing? +- Verify GitHub secrets are set correctly +- Check GitHub Actions logs +- Ensure SSH key has proper permissions + +### SSL errors? +- Ensure DNS is pointing to droplet IP +- Run: `certbot renew --dry-run` +- Check certificate: `certbot certificates` + +## 📁 Directory Structure + +``` +/var/www/agents.jeffemmett.com/ +├── .github/workflows/ +│ ├── deploy.yml # GitHub Pages deployment +│ └── deploy-droplet.yml # Droplet deployment +├── deployment/ +│ ├── nginx-config.conf # Nginx configuration +│ ├── setup-droplet.sh # Initial setup script +│ └── DEPLOYMENT_GUIDE.md # This file +├── index.html # Generated dashboard +├── src/ # UI components +├── threejs_viz/ # Three.js demos +├── sdg_viz/ # SDG visualizations +└── [other demo directories] +``` + +## 🎯 Both Cloudflare Pages AND Droplet? + +You can deploy to both! + +- **Cloudflare Pages**: Automatic, global CDN, great for most users +- **Droplet**: Full control, custom server config, your own infrastructure + +Both will deploy automatically on push to `main`. + +## 🔗 Useful Commands + +```bash +# SSH into droplet +ssh root@143.198.39.165 + +# Check deployment +cd /var/www/agents.jeffemmett.com && git status + +# View recent commits +cd /var/www/agents.jeffemmett.com && git log -5 --oneline + +# Restart nginx +systemctl restart nginx + +# Test site locally +curl -I https://agents.jeffemmett.com +``` + +## ✅ Verification Checklist + +After setup, verify: +- [ ] Site loads at https://agents.jeffemmett.com +- [ ] SSL certificate is valid (green lock icon) +- [ ] All demo categories display correctly +- [ ] GitHub Actions workflow runs successfully +- [ ] Push to main triggers auto-deployment +- [ ] Site updates after deployment completes + +## 🆘 Support + +If you encounter issues: +1. Check the troubleshooting section above +2. Review GitHub Actions logs +3. Check nginx error logs on droplet +4. Verify DNS settings in Cloudflare + +--- + +**Happy deploying! 🚀** diff --git a/deployment/README.md b/deployment/README.md new file mode 100644 index 0000000..360bbb8 --- /dev/null +++ b/deployment/README.md @@ -0,0 +1,69 @@ +# Deployment Configuration + +This directory contains all deployment-related files for agents.jeffemmett.com. + +## 📁 Files + +- **`DEPLOYMENT_GUIDE.md`** - Complete deployment guide with step-by-step instructions +- **`setup-droplet.sh`** - Automated setup script for DigitalOcean droplet +- **`nginx-config.conf`** - Nginx web server configuration with SSL +- **`README.md`** - This file + +## 🚀 Quick Start + +### For DigitalOcean Droplet Deployment + +1. **Read the guide first**: [DEPLOYMENT_GUIDE.md](./DEPLOYMENT_GUIDE.md) + +2. **Configure DNS in Cloudflare**: + - Type: A + - Name: agents + - Content: 143.198.39.165 + - Proxy: DNS only (gray cloud) + +3. **Run setup on droplet**: + ```bash + ssh root@143.198.39.165 + curl -sSL https://raw.githubusercontent.com/Jeff-Emmett/infinite-agents/main/deployment/setup-droplet.sh | bash + ``` + +4. **Configure GitHub Secrets**: + - `DROPLET_HOST`: 143.198.39.165 + - `DROPLET_USER`: root + - `DROPLET_SSH_KEY`: Your private SSH key + +5. **Deploy**: + - Push to `main` branch + - Or trigger workflow manually in GitHub Actions + +## 🔧 Manual Deployment + +If you need to deploy manually: + +```bash +ssh root@143.198.39.165 +cd /var/www/agents.jeffemmett.com +git pull origin main +npm ci +python3 generate_index.py +chown -R www-data:www-data . +systemctl reload nginx +``` + +## 📚 Documentation + +See [DEPLOYMENT_GUIDE.md](./DEPLOYMENT_GUIDE.md) for complete documentation including: +- Prerequisites +- DNS configuration +- SSL setup +- Troubleshooting +- Monitoring & logs + +## 🎯 Deployment Options + +You can deploy to: +1. **DigitalOcean Droplet** (full control) - Uses `deploy-droplet.yml` +2. **GitHub Pages** (simple, free) - Uses `deploy.yml` +3. **Cloudflare Pages** (recommended) - Manual setup via Cloudflare UI + +All three can work simultaneously! diff --git a/deployment/nginx-config.conf b/deployment/nginx-config.conf new file mode 100644 index 0000000..0525306 --- /dev/null +++ b/deployment/nginx-config.conf @@ -0,0 +1,56 @@ +server { + listen 80; + listen [::]:80; + server_name agents.jeffemmett.com; + + # Redirect HTTP to HTTPS + return 301 https://$server_name$request_uri; +} + +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + server_name agents.jeffemmett.com; + + # SSL certificate paths (will be configured by Certbot) + ssl_certificate /etc/letsencrypt/live/agents.jeffemmett.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/agents.jeffemmett.com/privkey.pem; + include /etc/letsencrypt/options-ssl-nginx.conf; + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; + + # Root directory + root /var/www/agents.jeffemmett.com; + index index.html; + + # Logging + access_log /var/log/nginx/agents.jeffemmett.com-access.log; + error_log /var/log/nginx/agents.jeffemmett.com-error.log; + + # Security headers + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-XSS-Protection "1; mode=block" always; + + # Main location + location / { + try_files $uri $uri/ =404; + } + + # Cache static assets + location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ { + expires 1y; + add_header Cache-Control "public, immutable"; + } + + # HTML files - short cache for faster updates + location ~* \.html$ { + expires 1h; + add_header Cache-Control "public, must-revalidate"; + } + + # Gzip compression + gzip on; + gzip_vary on; + gzip_min_length 1024; + gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/javascript application/json image/svg+xml; +} diff --git a/deployment/setup-droplet.sh b/deployment/setup-droplet.sh new file mode 100755 index 0000000..a5d6aba --- /dev/null +++ b/deployment/setup-droplet.sh @@ -0,0 +1,95 @@ +#!/bin/bash + +# Droplet Setup Script for agents.jeffemmett.com +# Run this script on your DigitalOcean droplet as root + +set -e + +echo "🚀 Setting up agents.jeffemmett.com deployment environment..." + +# Update system +echo "📦 Updating system packages..." +apt-get update +apt-get upgrade -y + +# Install required packages +echo "📦 Installing required packages..." +apt-get install -y nginx python3 python3-pip nodejs npm git certbot python3-certbot-nginx curl + +# Verify Node.js version (need v20+) +echo "📦 Installing Node.js 20..." +curl -fsSL https://deb.nodesource.com/setup_20.x | bash - +apt-get install -y nodejs + +# Create deployment directory +echo "📁 Creating deployment directory..." +mkdir -p /var/www/agents.jeffemmett.com +cd /var/www/agents.jeffemmett.com + +# Clone repository (or pull if already exists) +if [ -d ".git" ]; then + echo "📥 Pulling latest code..." + git fetch origin main + git reset --hard origin/main +else + echo "📥 Cloning repository..." + git clone https://github.com/Jeff-Emmett/infinite-agents.git . + git checkout main +fi + +# Install dependencies +echo "📦 Installing Node.js dependencies..." +npm ci + +# Generate dashboard +echo "🎨 Generating dashboard..." +python3 generate_index.py + +# Set proper permissions +echo "🔒 Setting permissions..." +chown -R www-data:www-data /var/www/agents.jeffemmett.com +chmod -R 755 /var/www/agents.jeffemmett.com + +# Configure nginx +echo "🌐 Configuring nginx..." +cp deployment/nginx-config.conf /etc/nginx/sites-available/agents.jeffemmett.com +ln -sf /etc/nginx/sites-available/agents.jeffemmett.com /etc/nginx/sites-enabled/ +rm -f /etc/nginx/sites-enabled/default + +# Test nginx configuration +nginx -t + +# Obtain SSL certificate (only if not already present) +if [ ! -f /etc/letsencrypt/live/agents.jeffemmett.com/fullchain.pem ]; then + echo "🔐 Obtaining SSL certificate..." + echo "NOTE: Make sure DNS is pointing to this droplet before running certbot!" + read -p "Press Enter to continue with certbot, or Ctrl+C to cancel..." + certbot --nginx -d agents.jeffemmett.com --non-interactive --agree-tos --email admin@jeffemmett.com +else + echo "✅ SSL certificate already exists" +fi + +# Reload nginx +echo "🔄 Reloading nginx..." +systemctl reload nginx + +# Enable nginx on boot +systemctl enable nginx + +# Setup auto-renewal for SSL +echo "🔐 Setting up SSL auto-renewal..." +systemctl enable certbot.timer +systemctl start certbot.timer + +echo "" +echo "✅ Setup complete!" +echo "" +echo "📋 Next steps:" +echo "1. Verify site is accessible at https://agents.jeffemmett.com" +echo "2. Add GitHub secrets for automated deployments:" +echo " - DROPLET_HOST: 143.198.39.165" +echo " - DROPLET_USER: root" +echo " - DROPLET_SSH_KEY: (your private SSH key)" +echo "" +echo "3. Test deployment by pushing to main branch" +echo ""