#!/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 if [[ "$1" == "--fresh" ]]; then FRESH_INSTALL=true fi # Configuration REMOTE_HOST="laantungir.net" REMOTE_USER="ubuntu" # Deployment paths REMOTE_BINARY_DIR="/usr/local/bin/ginxsom" REMOTE_BINARY_PATH="$REMOTE_BINARY_DIR/ginxsom-fcgi" REMOTE_DB_PATH="$REMOTE_BINARY_DIR" REMOTE_BLOB_DIR="/var/www/blobs" REMOTE_SOCKET="/tmp/ginxsom-fcgi.sock" # Production keys ADMIN_PUBKEY="1ec454734dcbf6fe54901ce25c0c7c6bca5edd89443416761fadc321d38df139" SERVER_PRIVKEY="90df3fe61e7d19e50f387e4c5db87eff1a7d2a1037cd55026c4b21a4fda8ecf6" # 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 "==========================================" 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:~/ginxsom-fcgi_new || { print_error "Failed to upload binary" exit 1 } print_success "Binary uploaded to ~/ginxsom-fcgi_new" echo "" # Step 3: Setup directories print_status "Step 3: Setting up directories..." ssh $REMOTE_USER@$REMOTE_HOST << EOF set -e # Create binary/database directory echo "Creating application directory..." sudo mkdir -p $REMOTE_BINARY_DIR sudo chown www-data:www-data $REMOTE_BINARY_DIR sudo chmod 755 $REMOTE_BINARY_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 # Create logs directory echo "Creating logs directory..." sudo mkdir -p $REMOTE_BINARY_DIR/logs/app sudo chown -R www-data:www-data $REMOTE_BINARY_DIR/logs sudo chmod -R 755 $REMOTE_BINARY_DIR/logs 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: Handle fresh install if requested if [ "$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/*.db sudo rm -rf $REMOTE_BLOB_DIR/* echo "Existing data removed" EOF print_success "Fresh install prepared" echo "" else print_status "Step 4: Preserving existing data" 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: Upload and install systemd service file print_status "Step 6: Installing systemd service file..." scp ginxsom.service $REMOTE_USER@$REMOTE_HOST:~/ginxsom.service || { print_error "Failed to upload service file" exit 1 } ssh $REMOTE_USER@$REMOTE_HOST << 'EOF' sudo cp ~/ginxsom.service /etc/systemd/system/ sudo systemctl daemon-reload echo "Service file installed" EOF if [ $? -eq 0 ]; then print_success "Service file installed" else print_error "Failed to install service file" exit 1 fi echo "" # Step 7: Stop existing service and install new binary print_status "Step 7: 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 ~/ginxsom-fcgi_new $REMOTE_BINARY_PATH sudo chmod +x $REMOTE_BINARY_PATH sudo chown www-data:www-data $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 8: Start ginxsom through systemd (keeps process supervised and auto-restarted) print_status "Step 8: Starting ginxsom service..." ssh $REMOTE_USER@$REMOTE_HOST << 'EOF' set -e echo "Restarting systemd service..." sudo systemctl restart ginxsom.service sleep 2 if sudo systemctl is-active --quiet ginxsom.service; then echo "Service is active" else echo "ERROR: ginxsom.service is not active" sudo systemctl status --no-pager ginxsom.service || true sudo journalctl -u ginxsom.service -n 80 --no-pager || true exit 1 fi # Verify socket is listening if [ -S /tmp/ginxsom-fcgi.sock ]; then echo "FastCGI socket created successfully" ls -la /tmp/ginxsom-fcgi.sock else echo "ERROR: Socket not created" sudo systemctl status --no-pager ginxsom.service || true sudo journalctl -u ginxsom.service -n 80 --no-pager || true exit 1 fi # Show process list for diagnostics pgrep -af ginxsom-fcgi || true EOF if [ $? -eq 0 ]; then print_success "FastCGI service started" else print_error "Failed to start FastCGI service" 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 VERIFY_FAILED=false # 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_error "✗ Health check failed" curl -k -v --max-time 10 "https://blossom.laantungir.net/health" 2>&1 | head -10 || true VERIFY_FAILED=true fi # Test API health endpoint echo "" echo "Testing API health endpoint..." API_HEALTH_STATUS=$(curl -k -s -o /dev/null -w "%{http_code}" --max-time 10 "https://blossom.laantungir.net/api/health" || echo "000") if [[ "$API_HEALTH_STATUS" == "200" ]]; then print_success "✓ API health endpoint responding (200)" else print_error "✗ API health endpoint failed (HTTP $API_HEALTH_STATUS)" curl -k -v --max-time 10 "https://blossom.laantungir.net/api/health" 2>&1 | head -20 || true VERIFY_FAILED=true fi # Test files API endpoint echo "" echo "Testing files API endpoint..." API_FILES_STATUS=$(curl -k -s -o /dev/null -w "%{http_code}" --max-time 10 "https://blossom.laantungir.net/api/files?limit=1" || echo "000") if [[ "$API_FILES_STATUS" == "200" ]]; then print_success "✓ Files API endpoint responding (200)" elif [[ "$API_FILES_STATUS" == "401" || "$API_FILES_STATUS" == "403" ]]; then print_success "✓ Files API endpoint reachable (HTTP $API_FILES_STATUS indicates auth is enforced)" else print_error "✗ Files API endpoint failed (HTTP $API_FILES_STATUS)" curl -k -v --max-time 10 "https://blossom.laantungir.net/api/files?limit=1" 2>&1 | head -20 || true VERIFY_FAILED=true 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 if [ "$VERIFY_FAILED" = true ]; then print_error "Deployment verification failed - one or more critical endpoints are unhealthy" exit 1 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 " API Health: curl -k https://blossom.laantungir.net/api/health" echo " Files API: curl -k 'https://blossom.laantungir.net/api/files?limit=5'" 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" else print_status "Existing data preserved - verify database and blobs" 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 ""