Keycloak never reliably ran (fiddly reverse-proxy/hostname config) and the repo has standardized on Authelia for SSO + 2FA. This rips Keycloak out entirely: - Delete the install block, whiptail menu entry, uninstall plumbing, and EXISTING_SERVICES detection from both 24.04 and 26.04 scripts - Delete docker-compose-keycloak.yml, fix-keycloak-proxy.sh, and KEYCLOAK-SETUP-GUIDE.md - Remove the Keycloak block from caddy-setup-helper.sh - Update docs (CADDY-FAIL2BAN-SETUP.md, SECURITY-IMPROVEMENTS.md, NEW-SCRIPT-STRUCTURE.md, SCRIPT-FLOW-INTRO.txt) to reference Authelia Also documents the fail2ban/Authelia overlap: Authelia handles failed-login regulation (per-account lockout); the Caddy fail2ban jail is complementary firewall-level IP banning. Neither does geo-blocking — noted CrowdSec / Caddy GeoIP as the path for that. https://claude.ai/code/session_017eA2qqq9jfF2tNtpUYL8vK
380 lines
8.5 KiB
Markdown
380 lines
8.5 KiB
Markdown
# Caddy with Fail2ban Setup Guide
|
|
|
|
This guide helps you integrate new services with an existing Caddy reverse proxy and set up fail2ban protection.
|
|
|
|
## Quick Start
|
|
|
|
For servers with Caddy already installed:
|
|
|
|
```bash
|
|
# Run the automated helper script
|
|
./caddy-setup-helper.sh
|
|
```
|
|
|
|
This script will:
|
|
- ✅ Detect your Caddy installation
|
|
- ✅ Locate and backup your Caddyfile
|
|
- ✅ Check for fail2ban configuration
|
|
- ✅ Provide examples for adding new services
|
|
|
|
## Manual Setup
|
|
|
|
### 1. Backup Your Caddyfile
|
|
|
|
**IMPORTANT:** Always backup before making changes!
|
|
|
|
```bash
|
|
# Find your Caddyfile location
|
|
CADDYFILE=~/docker/caddy/Caddyfile # Adjust path as needed
|
|
|
|
# Create backup directory
|
|
mkdir -p $(dirname "$CADDYFILE")/backups
|
|
|
|
# Backup with timestamp
|
|
cp "$CADDYFILE" "$(dirname "$CADDYFILE")/backups/Caddyfile.backup.$(date +%Y%m%d_%H%M%S)"
|
|
```
|
|
|
|
### 2. Add New Services to Caddy
|
|
|
|
Add these blocks to your Caddyfile:
|
|
|
|
#### ActualBudget (Personal Finance)
|
|
|
|
```caddy
|
|
budget.yourdomain.com {
|
|
log {
|
|
output file /var/log/caddy/actualbudget-access.log
|
|
format json
|
|
level INFO
|
|
}
|
|
|
|
reverse_proxy localhost:5006
|
|
|
|
# Security headers
|
|
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"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Authelia (SSO + 2FA auth portal)
|
|
|
|
```caddy
|
|
auth.yourdomain.com {
|
|
log {
|
|
output file /var/log/caddy/authelia-access.log
|
|
format json
|
|
level INFO
|
|
}
|
|
|
|
reverse_proxy localhost:9091
|
|
|
|
# Security headers
|
|
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"
|
|
}
|
|
}
|
|
```
|
|
|
|
### 3. Reload Caddy Configuration
|
|
|
|
After editing the Caddyfile:
|
|
|
|
```bash
|
|
# Format the Caddyfile (optional but recommended)
|
|
docker exec -w /etc/caddy caddy caddy fmt --overwrite
|
|
|
|
# Reload Caddy configuration
|
|
docker exec -w /etc/caddy caddy caddy reload
|
|
```
|
|
|
|
If you get errors, check Caddy logs:
|
|
```bash
|
|
docker logs caddy
|
|
```
|
|
|
|
### 4. Restore from Backup (if needed)
|
|
|
|
If something goes wrong:
|
|
|
|
```bash
|
|
# Find your backup
|
|
ls -lah ~/docker/caddy/backups/
|
|
|
|
# Restore the backup
|
|
cp ~/docker/caddy/backups/Caddyfile.backup.YYYYMMDD_HHMMSS ~/docker/caddy/Caddyfile
|
|
|
|
# Reload Caddy
|
|
docker exec -w /etc/caddy caddy caddy reload
|
|
docker exec -w /etc/caddy caddy caddy fmt --overwrite
|
|
```
|
|
|
|
## Fail2ban Configuration
|
|
|
|
### Prerequisites
|
|
|
|
1. **Enable JSON logging in Caddy** (shown in examples above)
|
|
2. **Install fail2ban** on the host:
|
|
```bash
|
|
sudo apt update
|
|
sudo apt install fail2ban -y
|
|
```
|
|
|
|
### Installation Steps
|
|
|
|
#### Step 1: Install Fail2ban Filter
|
|
|
|
```bash
|
|
# Copy the filter configuration
|
|
sudo cp fail2ban-caddy-filter.conf /etc/fail2ban/filter.d/caddy-auth.conf
|
|
```
|
|
|
|
Or create it manually:
|
|
|
|
```bash
|
|
sudo tee /etc/fail2ban/filter.d/caddy-auth.conf > /dev/null <<'EOF'
|
|
[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
|
|
EOF
|
|
```
|
|
|
|
#### Step 2: Install Fail2ban Jail
|
|
|
|
```bash
|
|
# Copy the jail configuration
|
|
sudo cp fail2ban-caddy-jail.conf /etc/fail2ban/jail.d/caddy.conf
|
|
```
|
|
|
|
Or create it manually:
|
|
|
|
```bash
|
|
sudo tee /etc/fail2ban/jail.d/caddy.conf > /dev/null <<'EOF'
|
|
[caddy-auth]
|
|
enabled = true
|
|
port = http,https
|
|
filter = caddy-auth
|
|
logpath = /var/log/caddy/access.log
|
|
/var/log/caddy/*-access.log
|
|
maxretry = 5
|
|
findtime = 600
|
|
bantime = 3600
|
|
action = iptables-multiport[name=CaddyAuth, port="http,https", protocol=tcp]
|
|
backend = auto
|
|
EOF
|
|
```
|
|
|
|
#### Step 3: Create Log Directory
|
|
|
|
```bash
|
|
# Create log directory if using Docker Caddy
|
|
sudo mkdir -p /var/log/caddy
|
|
sudo chmod 755 /var/log/caddy
|
|
|
|
# If Caddy runs as specific user:
|
|
# sudo chown caddy:caddy /var/log/caddy
|
|
```
|
|
|
|
#### Step 4: Update Caddy Docker Compose
|
|
|
|
Add log volume to your Caddy docker-compose.yml:
|
|
|
|
```yaml
|
|
services:
|
|
caddy:
|
|
image: caddy:latest
|
|
container_name: caddy
|
|
restart: unless-stopped
|
|
ports:
|
|
- "80:80"
|
|
- "443:443"
|
|
volumes:
|
|
- ./Caddyfile:/etc/caddy/Caddyfile
|
|
- ./data:/data
|
|
- ./config:/config
|
|
- /var/log/caddy:/var/log/caddy # Add this line
|
|
```
|
|
|
|
Then restart Caddy:
|
|
```bash
|
|
cd ~/docker/caddy
|
|
docker compose down
|
|
docker compose up -d
|
|
```
|
|
|
|
#### Step 5: Restart Fail2ban
|
|
|
|
```bash
|
|
sudo systemctl restart fail2ban
|
|
sudo systemctl status fail2ban
|
|
```
|
|
|
|
### Testing Fail2ban
|
|
|
|
```bash
|
|
# Check if jail is running
|
|
sudo fail2ban-client status caddy-auth
|
|
|
|
# Test the filter against your logs
|
|
sudo fail2ban-regex /var/log/caddy/access.log /etc/fail2ban/filter.d/caddy-auth.conf
|
|
|
|
# View banned IPs
|
|
sudo fail2ban-client get caddy-auth banip
|
|
|
|
# Manually ban/unban an IP (for testing)
|
|
sudo fail2ban-client set caddy-auth banip 1.2.3.4
|
|
sudo fail2ban-client set caddy-auth unbanip 1.2.3.4
|
|
```
|
|
|
|
### Troubleshooting
|
|
|
|
#### Fail2ban not detecting attacks
|
|
|
|
1. **Check log format:**
|
|
```bash
|
|
tail -f /var/log/caddy/access.log
|
|
```
|
|
Ensure it's JSON format with `remote_ip` or `remote_addr` field.
|
|
|
|
2. **Test filter manually:**
|
|
```bash
|
|
sudo fail2ban-regex /var/log/caddy/access.log /etc/fail2ban/filter.d/caddy-auth.conf --print-all-matched
|
|
```
|
|
|
|
3. **Check fail2ban logs:**
|
|
```bash
|
|
sudo tail -f /var/log/fail2ban.log
|
|
```
|
|
|
|
#### Caddy configuration errors
|
|
|
|
1. **Validate Caddyfile:**
|
|
```bash
|
|
docker exec caddy caddy validate --config /etc/caddy/Caddyfile
|
|
```
|
|
|
|
2. **Check Caddy logs:**
|
|
```bash
|
|
docker logs caddy --tail 50
|
|
```
|
|
|
|
## Advanced Configuration
|
|
|
|
### Aggressive Fail2ban Settings
|
|
|
|
For tighter security:
|
|
|
|
```ini
|
|
[caddy-auth]
|
|
maxretry = 3 # Ban after 3 attempts (instead of 5)
|
|
findtime = 300 # Within 5 minutes (instead of 10)
|
|
bantime = 86400 # Ban for 24 hours (instead of 1)
|
|
```
|
|
|
|
### Ban Time Increment
|
|
|
|
Ban repeat offenders for longer:
|
|
|
|
```ini
|
|
[caddy-auth]
|
|
bantime.increment = true
|
|
bantime.factor = 24
|
|
bantime.maxtime = 604800 # Maximum 1 week ban
|
|
```
|
|
|
|
### Email Notifications
|
|
|
|
Get notified when IPs are banned:
|
|
|
|
```ini
|
|
[caddy-auth]
|
|
action = iptables-multiport[name=CaddyAuth, port="http,https", protocol=tcp]
|
|
sendmail-whois[name=CaddyAuth, dest=admin@yourdomain.com]
|
|
```
|
|
|
|
### Per-Service Jails
|
|
|
|
Create separate jails for different services:
|
|
|
|
```ini
|
|
[caddy-actualbudget]
|
|
enabled = true
|
|
port = http,https
|
|
filter = caddy-auth
|
|
logpath = /var/log/caddy/actualbudget-access.log
|
|
maxretry = 3
|
|
bantime = 7200
|
|
|
|
[caddy-authelia]
|
|
enabled = true
|
|
port = http,https
|
|
filter = caddy-auth
|
|
logpath = /var/log/caddy/authelia-access.log
|
|
maxretry = 5
|
|
bantime = 3600
|
|
```
|
|
|
|
> **Note:** Authelia already performs its own failed-login *regulation*
|
|
> (per-account lockout after repeated failures). This jail is complementary
|
|
> defense-in-depth that bans the offending IP at the firewall level, and also
|
|
> covers services that don't sit behind Authelia. Neither Authelia nor
|
|
> fail2ban provides **geo-blocking** — for country-level blocking or IP
|
|
> reputation feeds, consider [CrowdSec](https://www.crowdsec.net/) (a modern
|
|
> fail2ban alternative with a Caddy bouncer) or a Caddy GeoIP module.
|
|
|
|
## Best Practices
|
|
|
|
1. **Always backup before changes**
|
|
2. **Test configuration before reloading** (`caddy validate`)
|
|
3. **Monitor fail2ban logs** initially to tune settings
|
|
4. **Use strong passwords** for admin interfaces
|
|
5. **Keep services updated** (`docker compose pull && docker compose up -d`)
|
|
6. **Regular backups** of configuration and data
|
|
7. **Use HTTPS** via Caddy for all services
|
|
8. **Implement rate limiting** in Caddy for API endpoints
|
|
|
|
## Quick Reference
|
|
|
|
### Common Commands
|
|
|
|
```bash
|
|
# Caddy
|
|
docker exec -w /etc/caddy caddy caddy reload
|
|
docker exec -w /etc/caddy caddy caddy fmt --overwrite
|
|
docker exec caddy caddy validate --config /etc/caddy/Caddyfile
|
|
docker logs caddy --tail 50
|
|
|
|
# Fail2ban
|
|
sudo systemctl restart fail2ban
|
|
sudo fail2ban-client status caddy-auth
|
|
sudo fail2ban-client set caddy-auth unbanip 1.2.3.4
|
|
sudo tail -f /var/log/fail2ban.log
|
|
|
|
# Backup
|
|
cp ~/docker/caddy/Caddyfile ~/docker/caddy/Caddyfile.backup
|
|
```
|
|
|
|
### Service Ports
|
|
|
|
- **ActualBudget**: 5006
|
|
- **Authelia**: 9091
|
|
- **Caddy**: 80 (HTTP), 443 (HTTPS)
|
|
|
|
## Support
|
|
|
|
For issues:
|
|
- Caddy documentation: https://caddyserver.com/docs/
|
|
- Fail2ban manual: https://www.fail2ban.org/wiki/index.php/MANUAL_0_8
|
|
- ActualBudget docs: https://actualbudget.org/docs/
|
|
- Authelia docs: https://www.authelia.com/
|