v0.1.19 - Lots of remote hosting fixes

This commit is contained in:
Your Name
2025-12-13 14:53:25 -04:00
parent a5f92e4da3
commit a5880ebdf6
21 changed files with 16122 additions and 6358 deletions

388
docs/NEW_DEPLOY_SCRIPT.md Normal file
View File

@@ -0,0 +1,388 @@
# New deploy_lt.sh Script
This is the complete new deployment script for static binary deployment. Save this as `deploy_lt.sh` in the project root.
```bash
#!/bin/bash
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
print_status() { echo -e "${BLUE}[INFO]${NC} $1"; }
print_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; }
print_error() { echo -e "${RED}[ERROR]${NC} $1"; }
# Parse command line arguments
FRESH_INSTALL=false
MIGRATE_DATA=true
if [[ "$1" == "--fresh" ]]; then
FRESH_INSTALL=true
MIGRATE_DATA=false
elif [[ "$1" == "--no-migrate" ]]; then
MIGRATE_DATA=false
fi
# Configuration
REMOTE_HOST="laantungir.net"
REMOTE_USER="ubuntu"
# New paths (static binary deployment)
REMOTE_BINARY_DIR="/usr/local/bin/ginxsom"
REMOTE_BINARY_PATH="$REMOTE_BINARY_DIR/ginxsom-fcgi"
REMOTE_DB_DIR="/var/lib/ginxsom"
REMOTE_DB_PATH="$REMOTE_DB_DIR/ginxsom.db"
REMOTE_BLOB_DIR="/var/www/blobs"
REMOTE_SOCKET="/tmp/ginxsom-fcgi.sock"
# Old paths (for migration)
OLD_BINARY_PATH="/home/ubuntu/ginxsom/ginxsom.fcgi"
OLD_DB_PATH="/home/ubuntu/ginxsom/db/ginxsom.db"
OLD_BLOB_DIR="/var/www/html/blossom"
# Local paths
LOCAL_BINARY="build/ginxsom-fcgi_static_x86_64"
print_status "=========================================="
print_status "Ginxsom Static Binary Deployment"
print_status "=========================================="
print_status "Target: $REMOTE_HOST"
print_status "Binary: $REMOTE_BINARY_PATH"
print_status "Database: $REMOTE_DB_PATH"
print_status "Blobs: $REMOTE_BLOB_DIR"
print_status "Fresh install: $FRESH_INSTALL"
print_status "Migrate data: $MIGRATE_DATA"
print_status "=========================================="
echo ""
# Step 1: Verify local binary exists
print_status "Step 1: Verifying local static binary..."
if [[ ! -f "$LOCAL_BINARY" ]]; then
print_error "Static binary not found: $LOCAL_BINARY"
print_status "Please run: ./build_static.sh"
exit 1
fi
# Verify it's actually static
if ldd "$LOCAL_BINARY" 2>&1 | grep -q "not a dynamic executable\|statically linked"; then
print_success "Binary is static"
else
print_warning "Binary may not be fully static - proceeding anyway"
fi
BINARY_SIZE=$(du -h "$LOCAL_BINARY" | cut -f1)
print_success "Found static binary ($BINARY_SIZE)"
echo ""
# Step 2: Upload binary to server
print_status "Step 2: Uploading binary to server..."
scp "$LOCAL_BINARY" $REMOTE_USER@$REMOTE_HOST:/tmp/ginxsom-fcgi_new || {
print_error "Failed to upload binary"
exit 1
}
print_success "Binary uploaded to /tmp/ginxsom-fcgi_new"
echo ""
# Step 3: Setup directories and install binary
print_status "Step 3: Setting up directories and installing binary..."
ssh $REMOTE_USER@$REMOTE_HOST << EOF
set -e
# Create binary directory
echo "Creating binary directory..."
sudo mkdir -p $REMOTE_BINARY_DIR
# Create database directory
echo "Creating database directory..."
sudo mkdir -p $REMOTE_DB_DIR/backups
sudo chown www-data:www-data $REMOTE_DB_DIR
sudo chmod 755 $REMOTE_DB_DIR
# Create blob storage directory
echo "Creating blob storage directory..."
sudo mkdir -p $REMOTE_BLOB_DIR
sudo chown www-data:www-data $REMOTE_BLOB_DIR
sudo chmod 755 $REMOTE_BLOB_DIR
echo "Directories created successfully"
EOF
if [ $? -ne 0 ]; then
print_error "Failed to create directories"
exit 1
fi
print_success "Directories created"
echo ""
# Step 4: Migrate data if requested
if [ "$MIGRATE_DATA" = true ] && [ "$FRESH_INSTALL" = false ]; then
print_status "Step 4: Migrating existing data..."
ssh $REMOTE_USER@$REMOTE_HOST << EOF
set -e
# Migrate database
if [ -f $OLD_DB_PATH ]; then
echo "Migrating database from $OLD_DB_PATH..."
sudo cp $OLD_DB_PATH $REMOTE_DB_PATH
sudo chown www-data:www-data $REMOTE_DB_PATH
sudo chmod 644 $REMOTE_DB_PATH
echo "Database migrated"
elif [ -f $OLD_BLOB_DIR/ginxsom.db ]; then
echo "Migrating database from $OLD_BLOB_DIR/ginxsom.db..."
sudo cp $OLD_BLOB_DIR/ginxsom.db $REMOTE_DB_PATH
sudo chown www-data:www-data $REMOTE_DB_PATH
sudo chmod 644 $REMOTE_DB_PATH
echo "Database migrated"
else
echo "No existing database found - will be created on first run"
fi
# Migrate blobs
if [ -d $OLD_BLOB_DIR ] && [ "\$(ls -A $OLD_BLOB_DIR 2>/dev/null)" ]; then
echo "Migrating blobs from $OLD_BLOB_DIR..."
# Copy only blob files (SHA256 hashes with extensions)
sudo find $OLD_BLOB_DIR -type f -regextype posix-extended -regex '.*/[a-f0-9]{64}\.[a-z0-9]+' -exec cp {} $REMOTE_BLOB_DIR/ \; 2>/dev/null || true
sudo chown -R www-data:www-data $REMOTE_BLOB_DIR
BLOB_COUNT=\$(ls -1 $REMOTE_BLOB_DIR | wc -l)
echo "Migrated \$BLOB_COUNT blob files"
else
echo "No existing blobs found"
fi
EOF
if [ $? -eq 0 ]; then
print_success "Data migration completed"
else
print_warning "Data migration had issues - check manually"
fi
echo ""
elif [ "$FRESH_INSTALL" = true ]; then
print_status "Step 4: Fresh install - removing existing data..."
ssh $REMOTE_USER@$REMOTE_HOST << EOF
sudo rm -f $REMOTE_DB_PATH
sudo rm -rf $REMOTE_BLOB_DIR/*
echo "Existing data removed"
EOF
print_success "Fresh install prepared"
echo ""
else
print_status "Step 4: Skipping data migration (--no-migrate)"
echo ""
fi
# Step 5: Install minimal dependencies
print_status "Step 5: Installing minimal dependencies..."
ssh $REMOTE_USER@$REMOTE_HOST << 'EOF'
set -e
# Check if spawn-fcgi is installed
if ! command -v spawn-fcgi &> /dev/null; then
echo "Installing spawn-fcgi..."
sudo apt-get update -qq
sudo apt-get install -y spawn-fcgi
echo "spawn-fcgi installed"
else
echo "spawn-fcgi already installed"
fi
EOF
if [ $? -eq 0 ]; then
print_success "Dependencies verified"
else
print_error "Failed to install dependencies"
exit 1
fi
echo ""
# Step 6: Stop existing service and install new binary
print_status "Step 6: Stopping existing service and installing new binary..."
ssh $REMOTE_USER@$REMOTE_HOST << EOF
set -e
# Stop any existing ginxsom processes
echo "Stopping existing ginxsom processes..."
sudo pkill -f ginxsom-fcgi || true
sleep 2
# Remove old socket
sudo rm -f $REMOTE_SOCKET
# Install new binary
echo "Installing new binary..."
sudo mv /tmp/ginxsom-fcgi_new $REMOTE_BINARY_PATH
sudo chmod +x $REMOTE_BINARY_PATH
sudo chown root:root $REMOTE_BINARY_PATH
echo "Binary installed successfully"
EOF
if [ $? -eq 0 ]; then
print_success "Binary installed"
else
print_error "Failed to install binary"
exit 1
fi
echo ""
# Step 7: Start ginxsom FastCGI process
print_status "Step 7: Starting ginxsom FastCGI process..."
ssh $REMOTE_USER@$REMOTE_HOST << EOF
set -e
echo "Starting ginxsom FastCGI with configuration:"
echo " Binary: $REMOTE_BINARY_PATH"
echo " Database: $REMOTE_DB_PATH"
echo " Storage: $REMOTE_BLOB_DIR"
echo " Socket: $REMOTE_SOCKET"
echo ""
sudo spawn-fcgi \
-M 666 \
-u www-data \
-g www-data \
-s $REMOTE_SOCKET \
-U www-data \
-G www-data \
-d $REMOTE_DB_DIR \
-- $REMOTE_BINARY_PATH \
--db-path $REMOTE_DB_PATH \
--storage-dir $REMOTE_BLOB_DIR
# Give it a moment to start
sleep 2
# Verify process is running
if [ -S $REMOTE_SOCKET ]; then
echo "FastCGI socket created successfully"
ls -la $REMOTE_SOCKET
else
echo "ERROR: Socket not created"
exit 1
fi
# Check if process is running
if pgrep -f ginxsom-fcgi > /dev/null; then
echo "Process is running (PID: \$(pgrep -f ginxsom-fcgi))"
else
echo "WARNING: Process not found by pgrep (may be normal for FastCGI)"
fi
EOF
if [ $? -eq 0 ]; then
print_success "FastCGI process started"
else
print_error "Failed to start FastCGI process"
exit 1
fi
echo ""
# Step 8: Test nginx configuration and reload
print_status "Step 8: Testing and reloading nginx..."
ssh $REMOTE_USER@$REMOTE_HOST << 'EOF'
# Test nginx configuration
if sudo nginx -t 2>&1; then
echo "Nginx configuration test passed"
sudo nginx -s reload
echo "Nginx reloaded successfully"
else
echo "WARNING: Nginx configuration test failed"
echo "You may need to update nginx configuration manually"
echo "See docs/STATIC_DEPLOYMENT_PLAN.md for details"
fi
EOF
if [ $? -eq 0 ]; then
print_success "Nginx reloaded"
else
print_warning "Nginx reload had issues - check configuration"
fi
echo ""
# Step 9: Test deployment
print_status "Step 9: Testing deployment..."
echo ""
# Wait a moment for service to fully start
sleep 2
# Test health endpoint
echo "Testing health endpoint..."
if curl -k -s --max-time 10 "https://blossom.laantungir.net/health" | grep -q "OK"; then
print_success "✓ Health check passed"
else
print_warning "✗ Health check failed - checking response..."
curl -k -v --max-time 10 "https://blossom.laantungir.net/health" 2>&1 | head -10
fi
# Test root endpoint
echo ""
echo "Testing root endpoint..."
if curl -k -s --max-time 10 "https://blossom.laantungir.net/" | grep -q "Ginxsom"; then
print_success "✓ Root endpoint responding"
else
print_warning "✗ Root endpoint not responding as expected"
fi
echo ""
print_status "=========================================="
print_success "Deployment completed!"
print_status "=========================================="
echo ""
print_status "Service Information:"
echo " URL: https://blossom.laantungir.net"
echo " Binary: $REMOTE_BINARY_PATH"
echo " Database: $REMOTE_DB_PATH"
echo " Blobs: $REMOTE_BLOB_DIR"
echo " Socket: $REMOTE_SOCKET"
echo ""
print_status "Test Commands:"
echo " Health: curl -k https://blossom.laantungir.net/health"
echo " Info: curl -k https://blossom.laantungir.net/"
echo " Upload: ./tests/file_put_bud02.sh"
echo ""
print_status "Server Commands:"
echo " Check status: ssh $REMOTE_USER@$REMOTE_HOST 'ps aux | grep ginxsom-fcgi'"
echo " View logs: ssh $REMOTE_USER@$REMOTE_HOST 'sudo journalctl -f | grep ginxsom'"
echo " Restart: ssh $REMOTE_USER@$REMOTE_HOST 'sudo pkill ginxsom-fcgi && sudo spawn-fcgi ...'"
echo ""
if [ "$FRESH_INSTALL" = true ]; then
print_warning "Fresh install completed - database and blobs have been reset"
fi
if [ "$MIGRATE_DATA" = true ] && [ "$FRESH_INSTALL" = false ]; then
print_status "Data migration completed - verify blob count and database"
echo " Check blobs: ssh $REMOTE_USER@$REMOTE_HOST 'ls -la $REMOTE_BLOB_DIR | wc -l'"
echo " Check DB: ssh $REMOTE_USER@$REMOTE_HOST 'sudo -u www-data sqlite3 $REMOTE_DB_PATH \"SELECT COUNT(*) FROM blobs;\"'"
fi
echo ""
print_status "For nginx configuration updates, see: docs/STATIC_DEPLOYMENT_PLAN.md"
print_status "=========================================="
```
## Usage
```bash
# Normal deployment with data migration
./deploy_lt.sh
# Fresh install (removes all data)
./deploy_lt.sh --fresh
# Deploy without migrating data
./deploy_lt.sh --no-migrate
```
## Key Changes from Old Script
1. **No remote compilation** - uploads pre-built static binary
2. **New directory structure** - follows FHS standards
3. **Minimal dependencies** - only spawn-fcgi needed
4. **Data migration** - automatically migrates from old locations
5. **Simplified process** - ~30 seconds vs ~5-10 minutes

View File

@@ -0,0 +1,478 @@
# Nginx Configuration Updates for Static Binary Deployment
## Overview
This document describes the required nginx configuration changes to support the new static binary deployment with updated directory paths.
## Changes Required
### 1. Blob Storage Root Directory
**Change from:**
```nginx
root /var/www/html/blossom;
```
**Change to:**
```nginx
root /var/www/blobs;
```
### 2. FastCGI Script Filename
**Change from:**
```nginx
fastcgi_param SCRIPT_FILENAME $document_root/ginxsom.fcgi;
```
**Change to:**
```nginx
fastcgi_param SCRIPT_FILENAME /usr/local/bin/ginxsom/ginxsom-fcgi;
```
## Complete Updated Configuration
Save this as `/etc/nginx/conf.d/default.conf` on the server (or update the existing file):
```nginx
# FastCGI upstream configuration
upstream ginxsom_backend {
server unix:/tmp/ginxsom-fcgi.sock;
}
# Main domains
server {
if ($host = laantungir.net) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name laantungir.com www.laantungir.com laantungir.net www.laantungir.net laantungir.org www.laantungir.org;
root /var/www/html;
index index.html index.htm;
# CORS for Nostr NIP-05 verification
add_header Access-Control-Allow-Origin * always;
add_header Access-Control-Allow-Methods "GET, OPTIONS" always;
add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range" always;
location / {
try_files $uri $uri/ =404;
}
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /var/www/html;
}
}
# Main domains HTTPS - using the main certificate
server {
listen 443 ssl;
server_name laantungir.com www.laantungir.com laantungir.net www.laantungir.net laantungir.org www.laantungir.org;
ssl_certificate /etc/letsencrypt/live/laantungir.net/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/laantungir.net/privkey.pem; # managed by Certbot
root /var/www/html;
index index.html index.htm;
# CORS for Nostr NIP-05 verification
add_header Access-Control-Allow-Origin * always;
add_header Access-Control-Allow-Methods "GET, OPTIONS" always;
add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range" always;
location / {
try_files $uri $uri/ =404;
}
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /var/www/html;
}
}
# Blossom subdomains HTTP - redirect to HTTPS (keep for ACME)
server {
listen 80;
server_name blossom.laantungir.net;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$server_name$request_uri;
}
}
# 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;
# UPDATED: Root directory for blob storage
root /var/www/blobs;
# Maximum upload size
client_max_body_size 100M;
# OPTIONS preflight handler
if ($request_method = OPTIONS) {
return 204;
}
# PUT /upload - File uploads
location = /upload {
if ($request_method !~ ^(PUT|HEAD)$) {
return 405;
}
fastcgi_pass ginxsom_backend;
include fastcgi_params;
# UPDATED: Direct path to binary
fastcgi_param SCRIPT_FILENAME /usr/local/bin/ginxsom/ginxsom-fcgi;
}
# GET /list/<pubkey> - List user blobs
location ~ "^/list/([a-f0-9]{64})$" {
if ($request_method !~ ^(GET)$) {
return 405;
}
fastcgi_pass ginxsom_backend;
include fastcgi_params;
# UPDATED: Direct path to binary
fastcgi_param SCRIPT_FILENAME /usr/local/bin/ginxsom/ginxsom-fcgi;
}
# PUT /mirror - Mirror content
location = /mirror {
if ($request_method !~ ^(PUT)$) {
return 405;
}
fastcgi_pass ginxsom_backend;
include fastcgi_params;
# UPDATED: Direct path to binary
fastcgi_param SCRIPT_FILENAME /usr/local/bin/ginxsom/ginxsom-fcgi;
}
# PUT /report - Report content
location = /report {
if ($request_method !~ ^(PUT)$) {
return 405;
}
fastcgi_pass ginxsom_backend;
include fastcgi_params;
# UPDATED: Direct path to binary
fastcgi_param SCRIPT_FILENAME /usr/local/bin/ginxsom/ginxsom-fcgi;
}
# GET /auth - NIP-42 challenges
location = /auth {
if ($request_method !~ ^(GET)$) {
return 405;
}
fastcgi_pass ginxsom_backend;
include fastcgi_params;
# UPDATED: Direct path to binary
fastcgi_param SCRIPT_FILENAME /usr/local/bin/ginxsom/ginxsom-fcgi;
}
# Admin API
location /api/ {
if ($request_method !~ ^(GET|PUT)$) {
return 405;
}
fastcgi_pass ginxsom_backend;
include fastcgi_params;
# UPDATED: Direct path to binary
fastcgi_param SCRIPT_FILENAME /usr/local/bin/ginxsom/ginxsom-fcgi;
}
# Blob serving - SHA256 patterns
location ~ "^/([a-f0-9]{64})(\.[a-zA-Z0-9]+)?$" {
# Handle DELETE via rewrite
if ($request_method = DELETE) {
rewrite ^/(.*)$ /fcgi-delete/$1 last;
}
# Route HEAD to FastCGI
if ($request_method = HEAD) {
rewrite ^/(.*)$ /fcgi-head/$1 last;
}
# GET requests - serve files directly
if ($request_method != GET) {
return 405;
}
try_files /$1.txt /$1.jpg /$1.jpeg /$1.png /$1.webp /$1.gif /$1.pdf /$1.mp4 /$1.mp3 /$1.md =404;
# Cache headers
add_header Cache-Control "public, max-age=31536000, immutable";
}
# Internal FastCGI handlers
location ~ "^/fcgi-delete/([a-f0-9]{64}).*$" {
internal;
fastcgi_pass ginxsom_backend;
include fastcgi_params;
# UPDATED: Direct path to binary
fastcgi_param SCRIPT_FILENAME /usr/local/bin/ginxsom/ginxsom-fcgi;
fastcgi_param REQUEST_URI /$1;
}
location ~ "^/fcgi-head/([a-f0-9]{64}).*$" {
internal;
fastcgi_pass ginxsom_backend;
include fastcgi_params;
# UPDATED: Direct path to binary
fastcgi_param SCRIPT_FILENAME /usr/local/bin/ginxsom/ginxsom-fcgi;
fastcgi_param REQUEST_URI /$1;
}
# Health check
location /health {
access_log off;
return 200 "OK\n";
add_header Content-Type text/plain;
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;
}
# Default location - Server info from FastCGI
location / {
if ($request_method !~ ^(GET)$) {
return 405;
}
fastcgi_pass ginxsom_backend;
include fastcgi_params;
# UPDATED: Direct path to binary
fastcgi_param SCRIPT_FILENAME /usr/local/bin/ginxsom/ginxsom-fcgi;
}
}
server {
listen 80;
server_name relay.laantungir.com relay.laantungir.net relay.laantungir.org;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
proxy_pass http://127.0.0.1:8888;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header Sec-WebSocket-Key $http_sec_websocket_key;
proxy_set_header Sec-WebSocket-Version $http_sec_websocket_version;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
proxy_connect_timeout 60s;
proxy_buffering off;
proxy_request_buffering off;
gzip off;
}
}
# Relay HTTPS - proxy to c-relay
server {
listen 443 ssl;
server_name relay.laantungir.com relay.laantungir.net relay.laantungir.org;
ssl_certificate /etc/letsencrypt/live/git.laantungir.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/git.laantungir.net/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8888;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header Sec-WebSocket-Key $http_sec_websocket_key;
proxy_set_header Sec-WebSocket-Version $http_sec_websocket_version;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
proxy_connect_timeout 60s;
proxy_buffering off;
proxy_request_buffering off;
gzip off;
}
}
# Git subdomains HTTP - redirect to HTTPS
server {
listen 80;
server_name git.laantungir.com git.laantungir.net git.laantungir.org;
# Allow larger file uploads for Git releases
client_max_body_size 50M;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$server_name$request_uri;
}
}
# Auth subdomains HTTP - redirect to HTTPS
server {
listen 80;
server_name auth.laantungir.com auth.laantungir.net auth.laantungir.org;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
}
}
# Git subdomains HTTPS - proxy to gitea
server {
listen 443 ssl;
server_name git.laantungir.com git.laantungir.net git.laantungir.org;
# Allow larger file uploads for Git releases
client_max_body_size 50M;
ssl_certificate /etc/letsencrypt/live/git.laantungir.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/git.laantungir.net/privkey.pem;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_buffering off;
proxy_request_buffering off;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
proxy_connect_timeout 60s;
gzip off;
proxy_set_header Host $host;
proxy_set_header Sec-WebSocket-Key $http_sec_websocket_key;
proxy_set_header Sec-WebSocket-Version $http_sec_websocket_version;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
}
# Auth subdomains HTTPS - proxy to nostr-auth
server {
listen 443 ssl;
server_name auth.laantungir.com auth.laantungir.net auth.laantungir.org;
ssl_certificate /etc/letsencrypt/live/git.laantungir.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/git.laantungir.net/privkey.pem;
location / {
proxy_pass http://localhost:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_buffering off;
proxy_request_buffering off;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
proxy_connect_timeout 60s;
gzip off;
proxy_set_header Host $host;
proxy_set_header Sec-WebSocket-Key $http_sec_websocket_key;
proxy_set_header Sec-WebSocket-Version $http_sec_websocket_version;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
}
```
## Manual Update Steps
If you prefer to update the existing configuration manually:
```bash
# 1. Backup current configuration
ssh ubuntu@laantungir.net
sudo cp /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.backup
# 2. Edit the configuration
sudo nano /etc/nginx/conf.d/default.conf
# 3. Find and replace (in the blossom server block):
# - Change: root /var/www/html/blossom;
# - To: root /var/www/blobs;
# 4. Find and replace (all FastCGI locations):
# - Change: fastcgi_param SCRIPT_FILENAME $document_root/ginxsom.fcgi;
# - To: fastcgi_param SCRIPT_FILENAME /usr/local/bin/ginxsom/ginxsom-fcgi;
# 5. Test configuration
sudo nginx -t
# 6. If test passes, reload nginx
sudo nginx -s reload
# 7. If test fails, restore backup
sudo cp /etc/nginx/conf.d/default.conf.backup /etc/nginx/conf.d/default.conf
sudo nginx -s reload
```
## Verification
After updating the configuration:
```bash
# Check nginx syntax
sudo nginx -t
# Check if ginxsom is responding
curl -k https://blossom.laantungir.net/health
# Check blob serving (if you have existing blobs)
curl -k https://blossom.laantungir.net/<some-sha256-hash>.jpg
```
## Summary of Changes
| Item | Old Value | New Value |
|------|-----------|-----------|
| Blob root | `/var/www/html/blossom` | `/var/www/blobs` |
| Binary path | `$document_root/ginxsom.fcgi` | `/usr/local/bin/ginxsom/ginxsom-fcgi` |
| Binary location | `/home/ubuntu/ginxsom/ginxsom.fcgi` | `/usr/local/bin/ginxsom/ginxsom-fcgi` |
These changes align with the new static binary deployment architecture and Linux FHS standards.

View File

@@ -0,0 +1,383 @@
# 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)
```bash
# 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
```bash
# 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
```bash
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
```bash
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
```bash
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`
```nginx
# 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
### Option 1: In-Place Migration (Recommended)
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:
```bash
# 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`:
```ini
[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:
```bash
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**:
```bash
ldd /usr/local/bin/ginxsom/ginxsom-fcgi
# Should show: "not a dynamic executable"
```
2. **Service is running**:
```bash
ps aux | grep ginxsom-fcgi
ls -la /tmp/ginxsom-fcgi.sock
```
3. **Health endpoint**:
```bash
curl -k https://blossom.laantungir.net/health
# Should return: OK
```
4. **Upload test**:
```bash
# Use existing test scripts
./tests/file_put_bud02.sh
```
5. **Database access**:
```bash
sudo -u www-data sqlite3 /var/lib/ginxsom/ginxsom.db "SELECT COUNT(*) FROM blobs;"
```
6. **Blob storage**:
```bash
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
```bash
# 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
```bash
# 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.