Integrate Caddy and fail2ban into main ubuntu-post-install.sh script

Users can now install and configure everything by simply running the main script.
Re-running the script allows adding new services to existing installations.

NEW SERVICES IN MAIN SCRIPT:

CADDY WEB SERVER:
- Automatic HTTPS with Let's Encrypt
- Reverse proxy for all services
- Creates example Caddyfile with ActualBudget and Keycloak configs
- Detects existing installations (asks before reconfiguring)
- Automatically backs up existing Caddyfile before changes
- Pre-configured with /var/log/caddy volume for fail2ban integration
- Includes HTTP/3 support

FAIL2BAN INTRUSION PREVENTION:
- Automated installation via apt
- Creates Caddy filter for JSON logs (401, 403, 429 status codes)
- Creates Caddy jail with configurable settings
- Automatically creates /var/log/caddy directory
- Tests configuration before restart
- Verifies jail is active after restart
- Shows status and useful commands

FEATURES:
 Detects if services already exist (won't overwrite)
 Backs up configurations before changes
 Interactive prompts for all settings
 Validates configurations before applying
 Can be re-run to add services to existing setup
 Works alongside existing services
 Follows same pattern as ActualBudget/Keycloak

WORKFLOW:
1. Run ubuntu-post-install.sh
2. Select services to install (ActualBudget, Keycloak, Caddy, fail2ban, etc.)
3. Script handles everything automatically
4. Re-run anytime to add more services

The caddy-setup-helper.sh remains available as a standalone tool for
advanced configuration, but the main script is now the primary method.
This commit is contained in:
Claude
2026-01-11 23:04:24 +00:00
parent d3f412dc28
commit 6d66441a69
+268
View File
@@ -3051,6 +3051,274 @@ KC_COMPOSE
fi
fi
# ---- CADDY WEB SERVER ----
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ CADDY - Modern Web Server & Reverse Proxy │"
echo "│ Automatic HTTPS, reverse proxy for all your services │"
echo "│ Port: 80 (HTTP), 443 (HTTPS) │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install Caddy reverse proxy? (y/n):" "n" INSTALL_CADDY
if [ "$INSTALL_CADDY" = "y" ] || [ "$INSTALL_CADDY" = "Y" ]; then
CADDY_DIR="$DOCKER_DIR/caddy"
# Check if Caddy is already installed
if [ -f "$CADDY_DIR/Caddyfile" ] || [ -f "$CADDY_DIR/docker-compose.yml" ]; then
echo ""
echo "⚠ Caddy appears to be already installed at $CADDY_DIR"
prompt_yn "Do you want to reconfigure it? (y/n):" "n" RECONFIGURE_CADDY
if [ "$RECONFIGURE_CADDY" != "y" ] && [ "$RECONFIGURE_CADDY" != "Y" ]; then
echo " Skipping Caddy installation"
INSTALL_CADDY="n"
fi
fi
if [ "$INSTALL_CADDY" = "y" ] || [ "$INSTALL_CADDY" = "Y" ]; then
if [ "$DRY_RUN" = true ]; then
echo "[DRY-RUN] Would create $CADDY_DIR"
else
echo "Installing Caddy..."
mkdir -p "$CADDY_DIR/data" "$CADDY_DIR/config"
# Backup existing Caddyfile if it exists
if [ -f "$CADDY_DIR/Caddyfile" ]; then
mkdir -p "$CADDY_DIR/backups"
BACKUP_FILE="$CADDY_DIR/backups/Caddyfile.backup.$(date +%Y%m%d_%H%M%S)"
cp "$CADDY_DIR/Caddyfile" "$BACKUP_FILE"
echo " ✓ Backed up existing Caddyfile to: $BACKUP_FILE"
fi
cd "$CADDY_DIR"
cat > docker-compose.yml << 'CADDY_COMPOSE'
name: caddy
services:
caddy:
image: caddy:latest
container_name: caddy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp" # HTTP/3
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- ./data:/data
- ./config:/config
- /var/log/caddy:/var/log/caddy
environment:
- ACME_AGREE=true
labels:
- "io.podman.annotations.label/fail2ban.enable=true"
CADDY_COMPOSE
# Create Caddyfile if it doesn't exist
if [ ! -f "Caddyfile" ]; then
cat > Caddyfile << 'CADDYFILE'
{
# Global options
admin off
# Email for Let's Encrypt notifications
# email admin@yourdomain.com
}
# Example configuration - edit this for your services
# Uncomment and modify these examples:
# ActualBudget
# budget.yourdomain.com {
# log {
# output file /var/log/caddy/actualbudget-access.log
# format json
# level INFO
# }
# reverse_proxy localhost:5006
# header {
# Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
# X-Frame-Options "SAMEORIGIN"
# X-Content-Type-Options "nosniff"
# X-XSS-Protection "1; mode=block"
# Referrer-Policy "strict-origin-when-cross-origin"
# }
# }
# Keycloak
# auth.yourdomain.com {
# log {
# output file /var/log/caddy/keycloak-access.log
# format json
# level INFO
# }
# reverse_proxy localhost:8180
# header {
# Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
# X-Frame-Options "SAMEORIGIN"
# X-Content-Type-Options "nosniff"
# X-XSS-Protection "1; mode=block"
# Referrer-Policy "strict-origin-when-cross-origin"
# }
# }
# Add more services here...
CADDYFILE
echo " ✓ Created example Caddyfile"
else
echo " Using existing Caddyfile"
fi
echo " ✓ Caddy configured at $CADDY_DIR"
prompt_yn "Start Caddy now? (y/n):" "y" START_CADDY
if [ "$START_CADDY" = "y" ] || [ "$START_CADDY" = "Y" ]; then
docker compose up -d 2>/dev/null && echo " ✓ Caddy started" || echo " ⚠ Failed to start Caddy"
fi
echo ""
echo " Configuration file: $CADDY_DIR/Caddyfile"
echo " Edit Caddyfile to add your domains and services"
echo " Reload config: cd $CADDY_DIR && docker exec -w /etc/caddy caddy caddy reload"
echo ""
echo " ⚠ IMPORTANT: Edit the Caddyfile to configure your domains!"
echo " - Uncomment and modify the example configurations"
echo " - Add your domain names"
echo " - Configure services you want to expose"
echo ""
fi
fi
fi
# ---- FAIL2BAN ----
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ FAIL2BAN - Intrusion Prevention System │"
echo "│ Automatically ban IPs with failed auth attempts │"
echo "│ Protects SSH, Caddy, and other services │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install and configure fail2ban? (y/n):" "n" INSTALL_FAIL2BAN
if [ "$INSTALL_FAIL2BAN" = "y" ] || [ "$INSTALL_FAIL2BAN" = "Y" ]; then
if [ "$DRY_RUN" = true ]; then
echo "[DRY-RUN] Would install fail2ban"
else
echo "Installing fail2ban..."
# Check if fail2ban is already installed
if command -v fail2ban-client &> /dev/null; then
echo " ✓ fail2ban is already installed"
else
echo " Installing fail2ban package..."
if sudo apt update && sudo apt install -y fail2ban; then
echo " ✓ fail2ban installed successfully"
else
echo " ⚠ Failed to install fail2ban"
echo " You may need to install it manually: sudo apt install fail2ban"
fi
fi
# Create log directory for Caddy
if [ ! -d "/var/log/caddy" ]; then
sudo mkdir -p /var/log/caddy
sudo chmod 755 /var/log/caddy
echo " ✓ Created /var/log/caddy directory"
fi
# Check if Caddy filter exists
FILTER_FILE="/etc/fail2ban/filter.d/caddy-auth.conf"
if [ ! -f "$FILTER_FILE" ]; then
echo " Creating fail2ban filter for Caddy..."
FILTER_CONTENT='[Definition]
failregex = ^.*"remote_ip":"<HOST>".*"status":(?:401|403|429).*$
^.*"remote_addr":"<HOST>.*"status":(?:401|403|429).*$
ignoreregex = ^.*"remote_ip":"(?:127\.0\.0\.1|::1)".*$
datepattern = "ts":%%s'
if echo "$FILTER_CONTENT" | sudo tee "$FILTER_FILE" > /dev/null; then
echo " ✓ Created Caddy fail2ban filter"
else
echo " ⚠ Failed to create filter - you may need to create it manually"
fi
else
echo " ✓ Caddy fail2ban filter already exists"
fi
# Check if Caddy jail exists
JAIL_FILE="/etc/fail2ban/jail.d/caddy.conf"
if [ ! -f "$JAIL_FILE" ]; then
echo " Creating fail2ban jail for Caddy..."
echo ""
echo " Configure fail2ban settings (press Enter for defaults):"
prompt_text " Max retries before ban:" "5" F2B_MAXRETRY
prompt_text " Find time window (seconds):" "600" F2B_FINDTIME
prompt_text " Ban duration (seconds):" "3600" F2B_BANTIME
JAIL_CONTENT="[caddy-auth]
enabled = true
port = http,https
filter = caddy-auth
logpath = /var/log/caddy/access.log
/var/log/caddy/*-access.log
maxretry = $F2B_MAXRETRY
findtime = $F2B_FINDTIME
bantime = $F2B_BANTIME
action = iptables-multiport[name=CaddyAuth, port=\"http,https\", protocol=tcp]
backend = auto"
if echo "$JAIL_CONTENT" | sudo tee "$JAIL_FILE" > /dev/null; then
echo " ✓ Created Caddy fail2ban jail"
else
echo " ⚠ Failed to create jail - you may need to create it manually"
fi
else
echo " ✓ Caddy fail2ban jail already exists"
fi
# Test fail2ban configuration
echo ""
echo " Testing fail2ban configuration..."
if sudo fail2ban-client -t &> /dev/null; then
echo " ✓ fail2ban configuration is valid"
else
echo " ⚠ fail2ban configuration has errors"
echo " Check with: sudo fail2ban-client -t"
fi
# Restart fail2ban
prompt_yn "Restart fail2ban to apply changes? (y/n):" "y" RESTART_F2B
if [ "$RESTART_F2B" = "y" ] || [ "$RESTART_F2B" = "Y" ]; then
if sudo systemctl restart fail2ban; then
echo " ✓ fail2ban restarted successfully"
# Wait for fail2ban to start
sleep 2
# Check jail status
if sudo fail2ban-client status caddy-auth &> /dev/null; then
echo " ✓ caddy-auth jail is active"
echo ""
sudo fail2ban-client status caddy-auth
else
echo " ⚠ caddy-auth jail is not active (may need Caddy logs to exist first)"
fi
else
echo " ⚠ Failed to restart fail2ban"
echo " Check logs: sudo journalctl -u fail2ban -n 50"
fi
fi
echo ""
echo " Useful commands:"
echo " Check jail status: sudo fail2ban-client status caddy-auth"
echo " View banned IPs: sudo fail2ban-client get caddy-auth banip"
echo " Unban IP: sudo fail2ban-client set caddy-auth unbanip 1.2.3.4"
echo " View logs: sudo tail -f /var/log/fail2ban.log"
echo ""
fi
fi
# ---- LYRION MUSIC SERVER ----
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"