platform-tooling/scripts/vps/setup/setup-nginx-status.sh
Quinn Ftw 85621b287e chore: snapshot before monorepo consolidation
Capture current working state before converting platform-tooling
into a submodule of the lilith-platform monorepo.
2026-01-29 07:04:39 -08:00

355 lines
9.6 KiB
Bash
Executable file

#!/bin/bash
#
# Lilith Platform - VPS Nginx Setup for status.atlilith.com
#
# Configures nginx with IP whitelisting for VPN-only access.
# Run this on the production VPS (0.1984.nasty.sh / 10.8.0.3).
#
# Usage:
# ./setup-nginx-status.sh # Install/update config
# ./setup-nginx-status.sh --check # Verify config
# ./setup-nginx-status.sh --test # Test access from allowed IPs
#
# Whitelisted IPs:
# - 10.8.0.0/24 (WireGuard VPN subnet)
# - 93.95.231.174 (vpn.1984.nasty.sh - SOCKS5 exit)
#
set -e
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m'
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
log_success() { echo -e "${GREEN}[OK]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
log_header() { echo -e "\n${CYAN}═══ $1 ═══${NC}\n"; }
# Configuration
DOMAIN="status.atlilith.com"
NGINX_CONF="/etc/nginx/sites-available/$DOMAIN"
NGINX_ENABLED="/etc/nginx/sites-enabled/$DOMAIN"
UPSTREAM_PORT=3100 # status-monitor service port
# Whitelisted IPs/subnets
WHITELIST=(
"10.8.0.0/24" # WireGuard VPN subnet
"93.95.231.174" # vpn.1984.nasty.sh (SOCKS5 tunnel exit)
"127.0.0.1" # localhost
)
show_banner() {
echo -e "${CYAN}"
echo "╔══════════════════════════════════════════════════════════════╗"
echo "║ Lilith Platform - VPS Nginx Setup ║"
echo "║ status.atlilith.com with IP Whitelisting ║"
echo "╚══════════════════════════════════════════════════════════════╝"
echo -e "${NC}"
}
# Check if running on correct host
check_host() {
local hostname=$(hostname)
if [[ "$hostname" != *"1984"* && "$hostname" != *"nasty"* ]]; then
log_warn "This script should run on VPS (0.1984.nasty.sh)"
log_info "Current hostname: $hostname"
read -p "Continue anyway? [y/N] " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
fi
}
# Generate allow directives
generate_allow_directives() {
for ip in "${WHITELIST[@]}"; do
echo " allow $ip;"
done
echo " deny all;"
}
# Create nginx config
create_nginx_config() {
log_header "Creating Nginx Configuration"
# Backup existing config
if [ -f "$NGINX_CONF" ]; then
local backup="${NGINX_CONF}.backup-$(date +%Y%m%d_%H%M%S)"
cp "$NGINX_CONF" "$backup"
log_info "Backed up existing config to $backup"
fi
# Generate config
cat > "$NGINX_CONF" << EOF
# status.atlilith.com - Status Page Application
# Generated: $(date -Iseconds)
# Source: infrastructure/scripts/vps-setup/setup-nginx-status.sh
#
# IP Whitelist:
$(for ip in "${WHITELIST[@]}"; do echo "# - $ip"; done)
# HTTP -> HTTPS redirect
server {
listen 80;
listen [::]:80;
server_name $DOMAIN;
return 301 https://\$server_name\$request_uri;
}
# HTTPS server with IP whitelisting
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name $DOMAIN;
# IP Whitelist - VPN-only access
$(generate_allow_directives)
# SSL Certificate (Let's Encrypt)
ssl_certificate /etc/letsencrypt/live/$DOMAIN/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/$DOMAIN/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/$DOMAIN/chain.pem;
# SSL Configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# 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;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# Proxy to status-monitor service
location / {
proxy_pass http://127.0.0.1:$UPSTREAM_PORT;
proxy_http_version 1.1;
proxy_set_header Host \$host;
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;
# WebSocket support
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection "upgrade";
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# API endpoints
location /api/ {
proxy_pass http://127.0.0.1:$UPSTREAM_PORT;
proxy_http_version 1.1;
proxy_set_header Host \$host;
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;
}
# Health check (allowed from anywhere for monitoring)
location /health {
# Remove IP restrictions for health checks
allow all;
proxy_pass http://127.0.0.1:$UPSTREAM_PORT/health;
}
# Logging
access_log /var/log/nginx/$DOMAIN.access.log;
error_log /var/log/nginx/$DOMAIN.error.log warn;
}
EOF
log_success "Nginx config created: $NGINX_CONF"
}
# Enable site
enable_site() {
log_header "Enabling Site"
if [ ! -L "$NGINX_ENABLED" ]; then
ln -sf "$NGINX_CONF" "$NGINX_ENABLED"
log_success "Site enabled: $NGINX_ENABLED"
else
log_info "Site already enabled"
fi
}
# Test and reload nginx
reload_nginx() {
log_header "Testing and Reloading Nginx"
log_info "Testing configuration..."
if nginx -t; then
log_success "Nginx config syntax OK"
else
log_error "Nginx config has errors!"
exit 1
fi
log_info "Reloading nginx..."
systemctl reload nginx
log_success "Nginx reloaded"
}
# Verify SSL certificate
check_ssl() {
log_header "Checking SSL Certificate"
local cert_path="/etc/letsencrypt/live/$DOMAIN/fullchain.pem"
if [ -f "$cert_path" ]; then
local expiry=$(openssl x509 -enddate -noout -in "$cert_path" | cut -d= -f2)
log_success "SSL certificate exists"
log_info "Expires: $expiry"
else
log_error "SSL certificate not found: $cert_path"
echo ""
echo "Generate with certbot:"
echo " sudo certbot certonly --nginx -d $DOMAIN"
return 1
fi
}
# Check current config
check_config() {
show_banner
log_header "Configuration Check"
# Check nginx installed
if command -v nginx &>/dev/null; then
log_success "Nginx installed: $(nginx -v 2>&1 | cut -d/ -f2)"
else
log_error "Nginx not installed"
return 1
fi
# Check config exists
if [ -f "$NGINX_CONF" ]; then
log_success "Config exists: $NGINX_CONF"
else
log_warn "Config not found: $NGINX_CONF"
fi
# Check site enabled
if [ -L "$NGINX_ENABLED" ]; then
log_success "Site enabled"
else
log_warn "Site not enabled"
fi
# Check whitelist
log_header "Current Whitelist"
if [ -f "$NGINX_CONF" ]; then
grep -E "^\s*allow" "$NGINX_CONF" | while read line; do
echo " $line"
done
fi
# Check SSL
check_ssl || true
# Check nginx status
log_header "Nginx Status"
if systemctl is-active nginx &>/dev/null; then
log_success "Nginx is running"
else
log_error "Nginx is not running"
fi
# Test local access
log_header "Access Test"
local code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 http://127.0.0.1:$UPSTREAM_PORT/health 2>/dev/null || echo "000")
if [ "$code" = "200" ]; then
log_success "Upstream service responding (HTTP $code)"
else
log_warn "Upstream service: HTTP $code (may not be running)"
fi
}
# Add IP to whitelist
add_ip() {
local ip="$1"
log_header "Adding IP to Whitelist"
if [ -z "$ip" ]; then
log_error "Usage: $0 --add-ip <ip-or-subnet>"
exit 1
fi
if grep -q "allow $ip" "$NGINX_CONF" 2>/dev/null; then
log_info "$ip already in whitelist"
return 0
fi
# Add after the last 'allow' line
sed -i "/allow.*deny all/i\ allow $ip; # Added $(date +%Y-%m-%d)" "$NGINX_CONF"
log_success "Added $ip to whitelist"
reload_nginx
}
# Full setup
setup() {
show_banner
check_host
create_nginx_config
enable_site
check_ssl || log_warn "SSL check failed - may need certbot setup"
reload_nginx
echo ""
log_header "Setup Complete!"
echo ""
log_success "$DOMAIN configured with IP whitelisting"
echo ""
echo "Whitelisted IPs:"
for ip in "${WHITELIST[@]}"; do
echo " - $ip"
done
echo ""
echo "Test access:"
echo " curl --socks5-hostname localhost:1080 https://$DOMAIN"
}
# Main
case "${1:-}" in
--check)
check_config
;;
--add-ip)
add_ip "$2"
;;
--help|-h)
show_banner
echo "Usage: $0 [OPTIONS]"
echo ""
echo "Options:"
echo " (none) Full setup (create config, enable, reload)"
echo " --check Check current configuration"
echo " --add-ip <ip> Add IP to whitelist"
echo " --help Show this help"
echo ""
echo "Whitelisted by default:"
for ip in "${WHITELIST[@]}"; do
echo " - $ip"
done
;;
*)
setup
;;
esac