Files
ginxsom/docs/STATIC_DEPLOYMENT_PLAN.md
2025-12-13 14:53:25 -04:00

9.7 KiB

Static MUSL Binary Deployment Plan

Overview

This document outlines the deployment architecture for ginxsom using static MUSL binaries. The new approach eliminates remote compilation and simplifies deployment to a single binary upload.

Architecture Changes

Current Deployment (Old)

Local Machine:
  - Build dynamic binary with make
  - Upload entire project via rsync
  - Remote server compiles from source
  - Install dependencies (libsqlite3-dev, libfcgi-dev, etc.)
  - Build nostr_core_lib submodules remotely
  - Binary location: /home/ubuntu/ginxsom/ginxsom.fcgi
  - Database: /home/ubuntu/ginxsom/db/ginxsom.db
  - Blobs: /var/www/html/blossom/

New Deployment (Static MUSL)

Local Machine:
  - Build static MUSL binary with Docker (build_static.sh)
  - Upload only the binary (no source code needed)
  - No remote compilation required
  - Minimal dependencies (only spawn-fcgi)
  - Binary location: /usr/local/bin/ginxsom/ginxsom-fcgi
  - Database: /var/lib/ginxsom/ginxsom.db
  - Blobs: /var/www/blobs/

Directory Structure

Production Server Layout

/usr/local/bin/ginxsom/
├── ginxsom-fcgi              # Static binary (executable)
└── README.md                 # Version info and deployment notes

/var/lib/ginxsom/
├── ginxsom.db                # SQLite database
└── backups/                  # Database backups

/var/www/blobs/
├── <sha256>.jpg              # Blob files
├── <sha256>.png
└── ...

/tmp/
└── ginxsom-fcgi.sock         # FastCGI socket

Deployment Process

Phase 1: Build Static Binary (Local)

# Build the static binary
./build_static.sh

# Output: build/ginxsom-fcgi_static_x86_64
# Size: ~7-10 MB
# Dependencies: NONE (fully static)

Phase 2: Upload Binary

# Upload to server
scp build/ginxsom-fcgi_static_x86_64 ubuntu@laantungir.net:/tmp/

# Install to /usr/local/bin/ginxsom/
ssh ubuntu@laantungir.net << 'EOF'
  sudo mkdir -p /usr/local/bin/ginxsom
  sudo mv /tmp/ginxsom-fcgi_static_x86_64 /usr/local/bin/ginxsom/ginxsom-fcgi
  sudo chmod +x /usr/local/bin/ginxsom/ginxsom-fcgi
  sudo chown root:root /usr/local/bin/ginxsom/ginxsom-fcgi
EOF

Phase 3: Setup Data Directories

ssh ubuntu@laantungir.net << 'EOF'
  # Create database directory
  sudo mkdir -p /var/lib/ginxsom/backups
  sudo chown www-data:www-data /var/lib/ginxsom
  sudo chmod 755 /var/lib/ginxsom
  
  # Create blob storage directory
  sudo mkdir -p /var/www/blobs
  sudo chown www-data:www-data /var/www/blobs
  sudo chmod 755 /var/www/blobs
  
  # Migrate existing data if needed
  if [ -f /var/www/html/blossom/ginxsom.db ]; then
    sudo cp /var/www/html/blossom/ginxsom.db /var/lib/ginxsom/
    sudo chown www-data:www-data /var/lib/ginxsom/ginxsom.db
  fi
  
  if [ -d /var/www/html/blossom ]; then
    sudo cp -r /var/www/html/blossom/* /var/www/blobs/ 2>/dev/null || true
    sudo chown -R www-data:www-data /var/www/blobs
  fi
EOF

Phase 4: Install Minimal Dependencies

ssh ubuntu@laantungir.net << 'EOF'
  # Only spawn-fcgi is needed (no build tools!)
  sudo apt-get update
  sudo apt-get install -y spawn-fcgi
EOF

Phase 5: Start Service

ssh ubuntu@laantungir.net << 'EOF'
  # Stop existing process
  sudo pkill -f ginxsom-fcgi || true
  sudo rm -f /tmp/ginxsom-fcgi.sock
  
  # Start with spawn-fcgi
  sudo spawn-fcgi \
    -M 666 \
    -u www-data \
    -g www-data \
    -s /tmp/ginxsom-fcgi.sock \
    -U www-data \
    -G www-data \
    -d /var/lib/ginxsom \
    -- /usr/local/bin/ginxsom/ginxsom-fcgi \
       --db-path /var/lib/ginxsom/ginxsom.db \
       --storage-dir /var/www/blobs
EOF

Nginx Configuration Updates

Required Changes to /etc/nginx/conf.d/default.conf

# Blossom subdomains HTTPS - ginxsom FastCGI
server {
    listen 443 ssl;
    server_name blossom.laantungir.net;

    ssl_certificate /etc/letsencrypt/live/git.laantungir.net/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/git.laantungir.net/privkey.pem;

    # Security headers
    add_header X-Content-Type-Options nosniff always;
    add_header X-Frame-Options DENY always;
    add_header X-XSS-Protection "1; mode=block" always;

    # CORS for Blossom protocol
    add_header Access-Control-Allow-Origin * always;
    add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, HEAD, OPTIONS, PATCH" always;
    add_header Access-Control-Allow-Headers "Authorization, Content-Type, Content-Length, Accept, Origin, User-Agent, DNT, Cache-Control, X-Mx-ReqToken, Keep-Alive, X-Requested-With, If-Modified-Since, *" always;
    add_header Access-Control-Max-Age 86400 always;

    # CHANGED: Root directory for blob storage
    root /var/www/blobs;  # Was: /var/www/html/blossom

    # Maximum upload size
    client_max_body_size 100M;

    # ... rest of configuration remains the same ...
    
    # CHANGED: Update SCRIPT_FILENAME references
    location = /upload {
        if ($request_method !~ ^(PUT|HEAD)$) {
            return 405;
        }
        fastcgi_pass ginxsom_backend;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME /usr/local/bin/ginxsom/ginxsom-fcgi;  # Was: $document_root/ginxsom.fcgi
    }
    
    # Apply same change to all other FastCGI locations...
}

Benefits of New Architecture

1. Simplified Deployment

  • Before: Upload source → Install deps → Build submodules → Compile → Deploy
  • After: Upload binary → Start service

2. Reduced Dependencies

  • Before: gcc, make, git, libsqlite3-dev, libfcgi-dev, libcurl4-openssl-dev, etc.
  • After: spawn-fcgi only

3. Better Security

  • No build tools on production server
  • No source code on production server
  • Smaller attack surface

4. Faster Deployments

  • Before: ~5-10 minutes (build time)
  • After: ~30 seconds (upload + restart)

5. Consistent Binaries

  • Same binary works on any Linux distribution
  • No "works on my machine" issues
  • Reproducible builds via Docker

6. Cleaner Organization

  • Binary in standard location (/usr/local/bin/)
  • Data in standard location (/var/lib/)
  • Blobs separate from web root (/var/www/blobs/)

Migration Strategy

  1. Build static binary locally
  2. Upload to /tmp/
  3. Stop current service
  4. Create new directories
  5. Migrate data
  6. Update nginx config
  7. Start new service
  8. Verify functionality
  9. Clean up old files

Option 2: Blue-Green Deployment

  1. Setup new directories alongside old
  2. Deploy static binary
  3. Test on different port
  4. Switch nginx config
  5. Remove old deployment

Option 3: Fresh Install

  1. Backup database and blobs
  2. Remove old installation
  3. Deploy static binary
  4. Restore data
  5. Configure nginx
  6. Start service

Rollback Plan

If issues occur, rollback is simple:

# Stop new service
sudo pkill -f ginxsom-fcgi

# Restore old binary location
sudo spawn-fcgi \
  -M 666 \
  -u www-data \
  -g www-data \
  -s /tmp/ginxsom-fcgi.sock \
  -U www-data \
  -G www-data \
  -d /home/ubuntu/ginxsom \
  -- /home/ubuntu/ginxsom/ginxsom.fcgi \
     --db-path /home/ubuntu/ginxsom/db/ginxsom.db \
     --storage-dir /var/www/html/blossom

# Revert nginx config
sudo cp /etc/nginx/conf.d/default.conf.backup /etc/nginx/conf.d/default.conf
sudo nginx -s reload

SystemD Service (Future Enhancement)

Create /etc/systemd/system/ginxsom.service:

[Unit]
Description=Ginxsom Blossom Server
After=network.target

[Service]
Type=forking
User=www-data
Group=www-data
WorkingDirectory=/var/lib/ginxsom
ExecStart=/usr/bin/spawn-fcgi \
  -M 666 \
  -u www-data \
  -g www-data \
  -s /tmp/ginxsom-fcgi.sock \
  -U www-data \
  -G www-data \
  -d /var/lib/ginxsom \
  -- /usr/local/bin/ginxsom/ginxsom-fcgi \
     --db-path /var/lib/ginxsom/ginxsom.db \
     --storage-dir /var/www/blobs
ExecStop=/usr/bin/pkill -f ginxsom-fcgi
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

Enable and start:

sudo systemctl daemon-reload
sudo systemctl enable ginxsom
sudo systemctl start ginxsom
sudo systemctl status ginxsom

Verification Steps

After deployment, verify:

  1. Binary is static:

    ldd /usr/local/bin/ginxsom/ginxsom-fcgi
    # Should show: "not a dynamic executable"
    
  2. Service is running:

    ps aux | grep ginxsom-fcgi
    ls -la /tmp/ginxsom-fcgi.sock
    
  3. Health endpoint:

    curl -k https://blossom.laantungir.net/health
    # Should return: OK
    
  4. Upload test:

    # Use existing test scripts
    ./tests/file_put_bud02.sh
    
  5. Database access:

    sudo -u www-data sqlite3 /var/lib/ginxsom/ginxsom.db "SELECT COUNT(*) FROM blobs;"
    
  6. Blob storage:

    ls -la /var/www/blobs/ | head
    

Monitoring

Key metrics to monitor:

  • Binary size: du -h /usr/local/bin/ginxsom/ginxsom-fcgi
  • Database size: du -h /var/lib/ginxsom/ginxsom.db
  • Blob storage: du -sh /var/www/blobs/
  • Process status: systemctl status ginxsom (if using systemd)
  • Socket status: ls -la /tmp/ginxsom-fcgi.sock

Backup Strategy

Database Backups

# Daily backup
sudo -u www-data sqlite3 /var/lib/ginxsom/ginxsom.db ".backup /var/lib/ginxsom/backups/ginxsom-$(date +%Y%m%d).db"

# Keep last 7 days
find /var/lib/ginxsom/backups/ -name "ginxsom-*.db" -mtime +7 -delete

Blob Backups

# Sync to backup location
rsync -av /var/www/blobs/ /backup/ginxsom-blobs/

Conclusion

The static MUSL binary deployment provides:

  • Simpler deployment process
  • Fewer dependencies
  • Better security
  • Faster updates
  • Universal compatibility
  • Cleaner organization

This architecture follows Linux FHS (Filesystem Hierarchy Standard) best practices and provides a solid foundation for production deployment.