personal_infra/scripts/setup_layer_3_caddy.sh
2025-11-06 23:09:44 +01:00

345 lines
11 KiB
Bash
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
###############################################################################
# Layer 3: Reverse Proxy (Caddy)
#
# This script deploys Caddy reverse proxy on VPS machines.
# Must be run after Layer 1A (VPS setup) is complete.
###############################################################################
set -e # Exit on error
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Project root directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
ANSIBLE_DIR="$PROJECT_ROOT/ansible"
###############################################################################
# Helper Functions
###############################################################################
print_header() {
echo -e "\n${BLUE}========================================${NC}"
echo -e "${BLUE}$1${NC}"
echo -e "${BLUE}========================================${NC}\n"
}
print_success() {
echo -e "${GREEN}${NC} $1"
}
print_error() {
echo -e "${RED}${NC} $1"
}
print_warning() {
echo -e "${YELLOW}${NC} $1"
}
print_info() {
echo -e "${BLUE}${NC} $1"
}
confirm_action() {
local prompt="$1"
local response
read -p "$(echo -e ${YELLOW}${prompt}${NC} [y/N]: )" response
[[ "$response" =~ ^[Yy]$ ]]
}
###############################################################################
# Verification Functions
###############################################################################
check_layer_0_complete() {
print_header "Verifying Layer 0 Prerequisites"
local errors=0
if [ -z "$VIRTUAL_ENV" ]; then
print_error "Virtual environment not activated"
echo "Run: source venv/bin/activate"
((errors++))
else
print_success "Virtual environment activated"
fi
if ! command -v ansible &> /dev/null; then
print_error "Ansible not found"
((errors++))
else
print_success "Ansible found"
fi
if [ ! -f "$ANSIBLE_DIR/inventory.ini" ]; then
print_error "inventory.ini not found"
((errors++))
else
print_success "inventory.ini exists"
fi
if [ $errors -gt 0 ]; then
print_error "Layer 0 is not complete"
exit 1
fi
print_success "Layer 0 prerequisites verified"
}
get_hosts_from_inventory() {
local group="$1"
cd "$ANSIBLE_DIR"
ansible-inventory -i inventory.ini --list | \
python3 -c "import sys, json; data=json.load(sys.stdin); print(' '.join(data.get('$group', {}).get('hosts', [])))" 2>/dev/null || echo ""
}
check_target_hosts() {
print_header "Checking Target Hosts"
local has_hosts=false
print_info "Caddy will be deployed to these hosts:"
echo ""
for group in vipy watchtower spacey; do
local hosts=$(get_hosts_from_inventory "$group")
if [ -n "$hosts" ]; then
echo " [$group]: $hosts"
has_hosts=true
else
print_warning "[$group]: not configured (skipping)"
fi
done
echo ""
if [ "$has_hosts" = false ]; then
print_error "No target hosts configured for Caddy"
print_info "Caddy needs vipy, watchtower, or spacey in inventory.ini"
exit 1
fi
print_success "Target hosts verified"
}
check_ssh_connectivity() {
print_header "Testing SSH Connectivity"
local ssh_key=$(grep "ansible_ssh_private_key_file" "$ANSIBLE_DIR/inventory.ini" | head -n1 | sed 's/.*ansible_ssh_private_key_file=\([^ ]*\).*/\1/')
ssh_key="${ssh_key/#\~/$HOME}"
local all_good=true
for group in vipy watchtower spacey; do
local hosts=$(get_hosts_from_inventory "$group")
if [ -n "$hosts" ]; then
for host in $hosts; do
print_info "Testing SSH to $host as counterweight..."
if timeout 10 ssh -i "$ssh_key" -o StrictHostKeyChecking=no -o BatchMode=yes counterweight@$host "echo 'SSH OK'" &>/dev/null; then
print_success "SSH to $host: OK"
else
print_error "Cannot SSH to $host as counterweight"
print_warning "Make sure Layer 1A is complete for this host"
all_good=false
fi
done
fi
done
if [ "$all_good" = false ]; then
echo ""
print_error "SSH connectivity test failed"
print_info "Ensure Layer 1A (VPS setup) is complete"
echo ""
if ! confirm_action "Continue anyway?"; then
exit 1
fi
fi
echo ""
print_success "SSH connectivity verified"
}
###############################################################################
# Caddy Deployment
###############################################################################
deploy_caddy() {
print_header "Deploying Caddy"
cd "$ANSIBLE_DIR"
print_info "This will:"
echo " • Install Caddy from official repositories"
echo " • Configure Caddy service"
echo " • Open firewall ports 80/443"
echo " • Create sites-enabled directory structure"
echo " • Enable automatic HTTPS with Let's Encrypt"
echo ""
print_info "Target hosts: vipy, watchtower, spacey (if configured)"
echo ""
print_warning "Important:"
echo " • Caddy will start with empty configuration"
echo " • Services will add their own config files in later layers"
echo " • Ports 80/443 must be available on the VPSs"
echo ""
if ! confirm_action "Proceed with Caddy deployment?"; then
print_warning "Skipped Caddy deployment"
return 1
fi
print_info "Running: ansible-playbook -i inventory.ini services/caddy_playbook.yml"
echo ""
if ansible-playbook -i inventory.ini services/caddy_playbook.yml; then
print_success "Caddy deployment complete"
return 0
else
print_error "Caddy deployment failed"
return 1
fi
}
###############################################################################
# Verification Functions
###############################################################################
verify_caddy() {
print_header "Verifying Caddy Installation"
cd "$ANSIBLE_DIR"
local ssh_key=$(grep "ansible_ssh_private_key_file" "$ANSIBLE_DIR/inventory.ini" | head -n1 | sed 's/.*ansible_ssh_private_key_file=\([^ ]*\).*/\1/')
ssh_key="${ssh_key/#\~/$HOME}"
echo "Checking Caddy on each host..."
echo ""
for group in vipy watchtower spacey; do
local hosts=$(get_hosts_from_inventory "$group")
if [ -n "$hosts" ]; then
for host in $hosts; do
print_info "Checking $host..."
# Check if caddy is installed
if timeout 5 ssh -i "$ssh_key" -o StrictHostKeyChecking=no -o BatchMode=yes counterweight@$host "command -v caddy" &>/dev/null; then
print_success "$host: Caddy installed"
else
print_error "$host: Caddy not found"
continue
fi
# Check if caddy service is running
if timeout 5 ssh -i "$ssh_key" -o StrictHostKeyChecking=no -o BatchMode=yes counterweight@$host "sudo systemctl is-active caddy" &>/dev/null; then
print_success "$host: Caddy service running"
else
print_error "$host: Caddy service not running"
fi
# Check if sites-enabled directory exists
if timeout 5 ssh -i "$ssh_key" -o StrictHostKeyChecking=no -o BatchMode=yes counterweight@$host "test -d /etc/caddy/sites-enabled" &>/dev/null; then
print_success "$host: sites-enabled directory exists"
else
print_warning "$host: sites-enabled directory not found"
fi
# Check if ports 80/443 are open
if timeout 5 ssh -i "$ssh_key" -o StrictHostKeyChecking=no -o BatchMode=yes counterweight@$host "sudo ufw status | grep -E '80|443'" &>/dev/null; then
print_success "$host: Firewall ports 80/443 open"
else
print_warning "$host: Could not verify firewall ports"
fi
echo ""
done
fi
done
}
###############################################################################
# Summary Functions
###############################################################################
print_summary() {
print_header "Layer 3 Setup Complete! 🎉"
echo "Summary of what was configured:"
echo ""
print_success "Caddy installed on VPS hosts"
print_success "Caddy service running"
print_success "Firewall ports 80/443 opened"
print_success "Sites-enabled directory structure created"
echo ""
print_info "What Caddy provides:"
echo " • Automatic HTTPS with Let's Encrypt"
echo " • Reverse proxy for all web services"
echo " • HTTP/2 support"
echo " • Simple per-service configuration"
echo ""
print_info "How services use Caddy:"
echo " • Each service adds a config file to /etc/caddy/sites-enabled/"
echo " • Main Caddyfile imports all configs"
echo " • Caddy automatically manages SSL certificates"
echo ""
print_warning "Important Notes:"
echo " • Caddy is currently running with default/empty config"
echo " • Services deployed in later layers will add their configs"
echo " • DNS must point to your VPS IPs for SSL to work"
echo ""
print_info "Next steps:"
echo " 1. Verify Caddy is accessible (optional): curl http://<vps-ip>"
echo " 2. Proceed to Layer 4: ./scripts/setup_layer_4_monitoring.sh"
echo ""
}
###############################################################################
# Main Execution
###############################################################################
main() {
clear
print_header "🌐 Layer 3: Reverse Proxy (Caddy)"
echo "This script will deploy Caddy reverse proxy on your VPS machines."
echo ""
print_info "Targets: vipy, watchtower, spacey"
echo ""
if ! confirm_action "Continue with Layer 3 setup?"; then
echo "Setup cancelled."
exit 0
fi
check_layer_0_complete
check_target_hosts
check_ssh_connectivity
# Deploy Caddy
if deploy_caddy; then
verify_caddy
print_summary
else
print_error "Caddy deployment failed"
exit 1
fi
}
# Run main function
main "$@"