From 25cb83437648b44662dd3e8820885114a62dab01 Mon Sep 17 00:00:00 2001 From: Riley Zhang Date: Wed, 24 Jun 2026 05:56:49 +0200 Subject: [PATCH] deploy: add hatch.surf static site deployment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Extended GitHub Actions workflow to deploy to server via rsync - Fixed favicon reference in index.html (favicon.png → favicon-48.png) - Added deploy-site.sh script for manual deployments - Added deploy-homepage.md documentation Co-Authored-By: Paperclip --- .github/workflows/deploy-site.yml | 33 +++++- docs/engineering/deploy-homepage.md | 170 ++++++++++++++++++++++++++++ scripts/deploy-site.sh | 92 +++++++++++++++ site/index.html | 2 +- 4 files changed, 293 insertions(+), 4 deletions(-) create mode 100644 docs/engineering/deploy-homepage.md create mode 100755 scripts/deploy-site.sh diff --git a/.github/workflows/deploy-site.yml b/.github/workflows/deploy-site.yml index 8e8266ec..4c4668c6 100644 --- a/.github/workflows/deploy-site.yml +++ b/.github/workflows/deploy-site.yml @@ -1,4 +1,4 @@ -name: Deploy static site to GitHub Pages +name: Deploy static site on: push: @@ -20,7 +20,8 @@ concurrency: cancel-in-progress: false jobs: - deploy: + deploy-github-pages: + name: Deploy to GitHub Pages environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} @@ -40,4 +41,30 @@ jobs: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v4 \ No newline at end of file + uses: actions/deploy-pages@v4 + + deploy-server: + name: Deploy to hatch.surf server + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Deploy via rsync + uses: burnett01/rsync-deployments@7.0.1 + with: + switches: -avz --delete + path: site/ + remote_path: /var/www/hatch.surf/ + remote_host: ${{ secrets.DEPLOY_HOST }} + remote_user: ${{ secrets.DEPLOY_USER }} + remote_key: ${{ secrets.DEPLOY_KEY }} + + - name: Reload nginx + uses: appleboy/ssh-action@v1 + with: + host: ${{ secrets.DEPLOY_HOST }} + username: ${{ secrets.DEPLOY_USER }} + key: ${{ secrets.DEPLOY_KEY }} + script: | + nginx -t && systemctl reload nginx diff --git a/docs/engineering/deploy-homepage.md b/docs/engineering/deploy-homepage.md new file mode 100644 index 00000000..16265619 --- /dev/null +++ b/docs/engineering/deploy-homepage.md @@ -0,0 +1,170 @@ +# Deploying the Hatch Homepage + +This document describes how the Hatch static homepage is deployed to hatch.surf. + +## Overview + +The homepage is deployed to two locations: + +1. **GitHub Pages** - Serves as a fallback and for GitHub-based discovery +2. **hatch.surf server** - Primary deployment at https://hatch.surf + +## Architecture + +``` +site/ +├── index.html # Main homepage +├── style.css # Stylesheet +├── brand/ # Logo and favicon assets +│ ├── favicon/ +│ └── og/ +└── blog/ # Blog directory (placeholder) +``` + +## Server Setup + +### Prerequisites + +- Server: 46.250.250.48 (hatch.surf) +- nginx installed and configured +- Let's Encrypt certificate for hatch.surf +- SSH access for deployment + +### Nginx Configuration + +The nginx server block is located at: +- `/etc/nginx/sites-available/hatch.surf.conf` +- Symlinked to `/etc/nginx/sites-enabled/hatch.surf.conf` + +Configuration highlights: +- HTTP → HTTPS redirect +- SSL with Let's Encrypt certificate +- Security headers (X-Content-Type-Options, X-Frame-Options, Referrer-Policy) +- Gzip compression +- Static asset caching (30 days) + +### SSL Certificate + +- Certificate managed by Let's Encrypt +- Auto-renewal via certbot +- Expiry: September 22, 2026 + +## Deployment + +### Automated (GitHub Actions) + +When changes are pushed to `main` branch affecting `site/` directory: + +1. **GitHub Pages** - Deployed automatically via GitHub Actions +2. **Server** - Deployed via rsync to `/var/www/hatch.surf/` + +Required GitHub secrets: +- `DEPLOY_HOST` - Server IP (46.250.250.48) +- `DEPLOY_USER` - SSH username (root) +- `DEPLOY_KEY` - SSH private key (base64 encoded) + +### Manual Deployment + +Use the deployment script: + +```bash +# Dry run +./scripts/deploy-site.sh --dry-run + +# Deploy +DEPLOY_HOST=46.250.250.48 \ +DEPLOY_USER=root \ +DEPLOY_KEY=$(cat ~/.ssh/id_rsa | base64) \ +./scripts/deploy-site.sh +``` + +### Direct rsync + +```bash +rsync -avz --delete site/ root@46.250.250.48:/var/www/hatch.surf/ +ssh root@46.250.250.48 "nginx -t && systemctl reload nginx" +``` + +## Verification + +### Check Site Status + +```bash +# HTTP redirect +curl -s -o /dev/null -w "%{http_code}" http://hatch.surf/ + +# HTTPS site +curl -s -o /dev/null -w "%{http_code}" https://hatch.surf/ + +# SSL certificate +curl -v https://hatch.surf/ 2>&1 | grep -E "expire|issuer|subject" + +# Static assets +curl -s -o /dev/null -w "%{http_code}" https://hatch.surf/style.css +curl -s -o /dev/null -w "%{http_code}" https://hatch.surf/brand/og/default.png +``` + +### Browser Verification + +1. Visit https://hatch.surf +2. Verify no browser warnings (SSL valid) +3. Check that all assets load (CSS, images) +4. Test responsive design + +## Troubleshooting + +### SSL Certificate Issues + +```bash +# Check certificate status +sudo certbot certificates + +# Renew certificate manually +sudo certbot renew --cert-name hatch.surf + +# Test nginx config +sudo nginx -t +``` + +### Deployment Failures + +1. Check GitHub Actions logs +2. Verify SSH access: `ssh root@46.250.250.48` +3. Check nginx status: `sudo systemctl status nginx` +4. Check nginx logs: `sudo tail -f /var/log/nginx/error.log` + +### Missing Assets + +1. Verify files exist on server: `ls -la /var/www/hatch.surf/brand/` +2. Check nginx access logs: `sudo tail -f /var/log/nginx/access.log` +3. Ensure proper file permissions: `chown -R www-data:www-data /var/www/hatch.surf` + +## Maintenance + +### Updating Content + +1. Edit files in `site/` directory +2. Commit and push to `main` branch +3. GitHub Actions will auto-deploy to both locations + +### SSL Renewal + +Certbot is configured to auto-renew. To check renewal status: + +```bash +sudo certbot renew --dry-run +``` + +### Backup + +The site is version-controlled in Git. For server backups: + +```bash +# Backup nginx config +sudo tar -czf nginx-hatch-backup.tar.gz /etc/nginx/sites-available/hatch.surf.conf /etc/letsencrypt/live/hatch.surf/ +``` + +## Related Issues + +- [ELF-192](/ELF/issues/ELF-192) - Build homepage and deploy it on hatch.surf +- [ELF-171](/ELF/issues/ELF-171) - Server setup (nginx, SSL) diff --git a/scripts/deploy-site.sh b/scripts/deploy-site.sh new file mode 100755 index 00000000..24d1e66d --- /dev/null +++ b/scripts/deploy-site.sh @@ -0,0 +1,92 @@ +#!/bin/bash +# Deploy static site to hatch.surf server +# Usage: ./scripts/deploy-site.sh [--dry-run] +# +# Environment variables required: +# DEPLOY_HOST - SSH host (e.g., 46.250.250.48) +# DEPLOY_USER - SSH user (e.g., root) +# DEPLOY_KEY - SSH private key (base64 encoded, optional if using ssh-agent) +# +# The script deploys the contents of the site/ directory to /var/www/hatch.surf + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +SITE_DIR="$REPO_ROOT/site" +REMOTE_DIR="/var/www/hatch.surf" + +# Configuration +DEPLOY_HOST="${DEPLOY_HOST:-46.250.250.48}" +DEPLOY_USER="${DEPLOY_USER:-root}" +DEPLOY_KEY="${DEPLOY_KEY:-}" + +# Parse arguments +DRY_RUN=false +for arg in "$@"; do + case $arg in + --dry-run) + DRY_RUN=true + ;; + esac +done + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +log() { + echo -e "${GREEN}✓${NC} $1" +} + +warn() { + echo -e "${YELLOW}⚠${NC} $1" +} + +error() { + echo -e "${RED}✗${NC} $1" >&2 + exit 1 +} + +# Validate +if [ ! -d "$SITE_DIR" ]; then + error "Site directory not found: $SITE_DIR" +fi + +if [ ! -f "$SITE_DIR/index.html" ]; then + error "index.html not found in $SITE_DIR" +fi + +# Setup SSH key if provided +SSH_OPTS="-o StrictHostKeyChecking=no -o ConnectTimeout=10" +if [ -n "$DEPLOY_KEY" ]; then + SSH_KEY_FILE=$(mktemp) + echo "$DEPLOY_KEY" | base64 -d > "$SSH_KEY_FILE" + chmod 600 "$SSH_KEY_FILE" + SSH_OPTS="$SSH_OPTS -i $SSH_KEY_FILE" +fi + +# Deploy +DEPLOY_TARGET="${DEPLOY_USER}@${DEPLOY_HOST}" + +if [ "$DRY_RUN" = true ]; then + warn "Dry run - would deploy to $DEPLOY_TARGET:$REMOTE_DIR" + rsync -avz --delete --dry-run $SSH_OPTS "$SITE_DIR/" "$DEPLOY_TARGET:$REMOTE_DIR/" +else + log "Deploying to $DEPLOY_TARGET:$REMOTE_DIR" + rsync -avz --delete $SSH_OPTS "$SITE_DIR/" "$DEPLOY_TARGET:$REMOTE_DIR/" + + # Reload nginx + log "Reloading nginx..." + ssh $SSH_OPTS "$DEPLOY_TARGET" "nginx -t && systemctl reload nginx" + + log "Deployment complete!" + log "Site live at https://hatch.surf" +fi + +# Cleanup SSH key if created +if [ -n "$SSH_KEY_FILE" ]; then + rm -f "$SSH_KEY_FILE" +fi diff --git a/site/index.html b/site/index.html index 9ca45652..97d91eba 100644 --- a/site/index.html +++ b/site/index.html @@ -20,7 +20,7 @@ - +