Hardening & Monitoring
Layer on CrowdSec, Fail2ban, Beszel monitoring, and Traefik access logs for defense-in-depth security and full observability.
Completed Part 3, services exposed through Pangolin
60–90 minutes
CrowdSec, Fail2ban, Beszel monitoring, and audit logging
Your Pangolin deployment is live: encrypted tunnels from your VPS to home, identity-aware access on every resource, and services like Jellyfin, Home Assistant, and Nextcloud accessible from anywhere. The final step is ensuring this infrastructure stays secure and observable over time.
In this final part, we'll layer on CrowdSec for crowd-sourced threat intelligence, Fail2ban as a lightweight brute-force shield, Beszel for server monitoring, and Traefik's access logs for audit trails. Together, these tools give you a defense-in-depth posture that blocks known bad actors at the edge while giving you full visibility into what's happening across your infrastructure.
Layer 1: CrowdSec — Community-Driven Threat Detection
CrowdSec is an open-source intrusion prevention system that analyzes Traefik logs, detects attack patterns, and blocks malicious IPs using a community-shared blocklist. If the Pangolin installer asked whether you wanted CrowdSec and you selected Yes in Part 1, the bouncer is already installed.
Verify CrowdSec is Running
sudo docker ps | grep crowdsec
sudo docker exec crowdsec cscli bouncers listYou should see the Traefik bouncer registered. If CrowdSec wasn't installed during Pangolin setup, you can add it manually — refer to the Pangolin documentation for the exact Docker Compose configuration.
Install Relevant Collections
CrowdSec uses "collections" to detect specific attack patterns. Install collections relevant to your exposed services:
# Core web attack detection
sudo docker exec crowdsec cscli collections install \
crowdsecurity/traefik \
crowdsecurity/http-cve \
crowdsecurity/base-http-scenarios
# If you're exposing SSH on the VPS
sudo docker exec crowdsec cscli collections install \
crowdsecurity/sshd
# Verify installed collections
sudo docker exec crowdsec cscli collections listRegister with the CrowdSec Console
The CrowdSec Console (app.crowdsec.net) gives you a web dashboard to view alerts, manage decisions, and see your contribution to the community blocklist. Registration is free:
sudo docker exec crowdsec cscli console enroll YOUR_ENROLLMENT_KEYOnce enrolled, you'll see real-time alerts whenever CrowdSec detects and blocks an attack pattern against your Pangolin VPS.
Community Power
CrowdSec's community blocklist contains over 10 million malicious IP addresses contributed by thousands of operators worldwide. By running CrowdSec, you automatically benefit from this shared intelligence and contribute your own detections back.
Layer 2: Fail2ban — Brute-Force Protection
While CrowdSec handles sophisticated attack patterns, Fail2ban provides straightforward brute-force protection by monitoring log files and banning IPs that exceed a threshold of failed attempts. It's a belt-and-suspenders approach.
Install Fail2ban on the VPS
sudo apt install fail2ban -y
sudo systemctl enable fail2banConfigure SSH Jail
Create a local configuration that won't be overwritten by package updates:
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 5
banaction = ufw
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 86400sudo systemctl restart fail2banThis configuration bans any IP that fails three SSH login attempts within 10 minutes, locking them out for 24 hours.
Monitor Fail2ban Status
# View active jails
sudo fail2ban-client status
# Check SSH jail specifically
sudo fail2ban-client status sshd
# View banned IPs
sudo fail2ban-client get sshd bannedIntegration Note
CrowdSec and Fail2ban can coexist without conflict. CrowdSec operates at the Traefik middleware level (blocking HTTP requests), while Fail2ban operates at the UFW/iptables level (blocking network connections). They protect different layers of your stack.
Layer 3: Beszel — Lightweight Server Monitoring
Beszel is a lightweight, self-hosted monitoring platform that tracks CPU, memory, disk, network, and Docker container metrics with historical data and configurable alerts. It's the perfect fit for a homelab — a single Go binary for agents and Docker for the hub — without the complexity of a Prometheus + Grafana stack.
Deploy the Beszel Hub
We'll run the Beszel hub on the VPS so it can monitor both the VPS itself and your home server through the Pangolin tunnel.
mkdir -p ~/beszel && cd ~/beszel
cat > docker-compose.yml << 'EOF'
services:
beszel:
image: henrygd/beszel:latest
container_name: beszel
restart: unless-stopped
ports:
- "127.0.0.1:8090:8090"
volumes:
- ./beszel_data:/beszel_data
EOF
docker compose up -dBinding to 127.0.0.1 ensures the Beszel web interface is only accessible locally. We'll expose it through Pangolin itself with SSO protection.
Expose Beszel Through Pangolin
Create a new resource in Pangolin:
- Name: Beszel Monitoring
- Domain:
monitor.tunnel.yourdomain.com - Target:
http://localhost:8090(since it's on the same VPS) - Authentication: Platform SSO — Admin Only
Since Beszel runs on the VPS alongside Pangolin, you don't need a tunnel for this one — it's local.
Deploy Beszel Agents
Install agents on each system you want to monitor. For your home server, install the agent and connect it through the WireGuard tunnel:
# On your home server
docker run -d \
--name beszel-agent \
--restart unless-stopped \
--network host \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-e PORT=45876 \
-e KEY="your-beszel-agent-key" \
henrygd/beszel-agent:latestIn the Beszel hub dashboard, click "Add System" and enter the home server's WireGuard tunnel IP. The agent communicates over SSH key authentication, so it's secure even without additional encryption.
Configure Alerts
Beszel supports configurable alerts via SMTP or Shoutrrr URL schemas (Slack, Discord, Telegram, Gotify, and more). Set up alerts for:
- • CPU usage exceeding 90% for more than 5 minutes
- • Memory usage above 85%
- • Disk usage above 90% on any partition
- • System offline — agent stops reporting
- • Docker container stopped unexpectedly
Navigate to the bell icon in Beszel's dashboard to configure notification thresholds per system.
Layer 4: Traefik Access Logs
Access logs provide the audit trail that ties everything together. Every request that passes through your Pangolin VPS is logged by Traefik, giving you visibility into who accessed what and when.
Enable Access Logging
If Pangolin's installer didn't enable access logs by default, add the configuration to Traefik's config file:
accessLog:
filePath: "/var/log/traefik/access.log"
format: json
bufferingSize: 100
filters:
statusCodes:
- "200-499"
fields:
headers:
defaultMode: dropRestart Traefik to apply the changes. JSON format makes the logs easy to parse with tools like jq:
# View recent requests
sudo docker exec traefik tail -50 /var/log/traefik/access.log | jq .
# Filter for specific service
sudo docker exec traefik cat /var/log/traefik/access.log | \
jq 'select(.RouterName | contains("jellyfin"))'
# Find 4xx errors
sudo docker exec traefik cat /var/log/traefik/access.log | \
jq 'select(.DownstreamStatus >= 400 and .DownstreamStatus < 500)'Log Rotation
Traefik logs can grow quickly on an active server. Set up logrotate to keep them manageable:
/path/to/pangolin/config/logs/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
copytruncate
}Putting It All Together: Defense in Depth
Here's the complete security and monitoring architecture you've built across this series:
| Layer | Tool | Function |
|---|---|---|
| Network | WireGuard (via Pangolin/Gerbil) | Encrypted tunnel; no open ports at home |
| Edge Filtering | CrowdSec | Community blocklist; attack pattern detection |
| Brute-Force | Fail2ban | Rate limiting and IP banning for SSH and services |
| Identity | Pangolin SSO + OIDC | Per-service authentication and authorization |
| Transport | Traefik + Let's Encrypt | SSL termination; automatic certificate management |
| Monitoring | Beszel | Real-time metrics, Docker stats, and alerting |
| Audit | Traefik Access Logs | Full request logging with JSON parsing |
Every request passes through multiple checkpoints. A malicious actor must survive the CrowdSec blocklist, pass Fail2ban's rate limits, authenticate through Pangolin's identity layer, and then still face the backend service's own authentication. Meanwhile, Beszel watches for anomalies and Traefik logs everything for post-incident analysis.
Ongoing Maintenance Checklist
A secure deployment requires periodic attention. Here's a monthly checklist:
- Update Pangolin: Check the Pangolin GitHub releases page and update via
docker compose pull && docker compose up -d. - Update CrowdSec: Run
docker exec crowdsec cscli hub update && docker exec crowdsec cscli hub upgrade. - Review Fail2ban logs: Check for excessively banned IPs — this might indicate a targeted attack or misconfigured service.
- Check Beszel alerts: Review any triggered alerts and investigate the root cause.
- Audit user access: Review Pangolin's user list and remove any accounts that are no longer needed.
- Verify SSL certificates: Let's Encrypt certificates auto-renew, but check the
acme.jsonfile dates to confirm renewal is working. - Back up configuration: Back up the entire Pangolin config directory, Beszel data, and Fail2ban configuration. Store offsite.
- OS updates: Run
apt update && apt upgradeon the VPS and home server.
Series Wrap-Up
Over the course of this four-part series, you've built a complete zero-trust access stack for your homelab:
- • Part 1: Pangolin installation on a RamNode VPS with WireGuard tunnels to your home network.
- • Part 2: Identity-aware access with SSO, OIDC, per-service auth policies, and 2FA.
- • Part 3: Service-specific configuration for Jellyfin, Home Assistant, Nextcloud, and more.
- • Part 4: Defense-in-depth hardening with CrowdSec, Fail2ban, Beszel monitoring, and access logs.
The total monthly cost of this setup is remarkably low. A $5/month RamNode VPS, a $10/year domain, and your existing home server hardware. For that, you get enterprise-grade zero-trust access to your entire homelab with no dependency on third-party tunnel services.
Get Started
RamNode's KVM VPS plans start at $4/month with up to $500 in annual credits for new accounts. That's more than a year of free hosting for your Pangolin deployment. Visit ramnode.com to get started →
