Zero-Trust Homelab Access Series
    Part 4 of 4

    Hardening & Monitoring

    Layer on CrowdSec, Fail2ban, Beszel monitoring, and Traefik access logs for defense-in-depth security and full observability.

    60–90 min
    Intermediate–Advanced
    Prerequisites

    Completed Part 3, services exposed through Pangolin

    Time to Complete

    60–90 minutes

    What You'll Build

    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

    Check CrowdSec status
    sudo docker ps | grep crowdsec
    sudo docker exec crowdsec cscli bouncers list

    You 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:

    Install CrowdSec collections
    # 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 list

    Register 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:

    Enroll in CrowdSec Console
    sudo docker exec crowdsec cscli console enroll YOUR_ENROLLMENT_KEY

    Once 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

    Install Fail2ban
    sudo apt install fail2ban -y
    sudo systemctl enable fail2ban

    Configure SSH Jail

    Create a local configuration that won't be overwritten by package updates:

    /etc/fail2ban/jail.local
    [DEFAULT]
    bantime  = 3600
    findtime = 600
    maxretry = 5
    banaction = ufw
    
    [sshd]
    enabled  = true
    port     = ssh
    filter   = sshd
    logpath  = /var/log/auth.log
    maxretry = 3
    bantime  = 86400
    Restart Fail2ban
    sudo systemctl restart fail2ban

    This configuration bans any IP that fails three SSH login attempts within 10 minutes, locking them out for 24 hours.

    Monitor Fail2ban Status

    Check 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 banned

    Integration 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.

    Beszel Hub docker-compose.yml
    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 -d

    Binding 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:

    1. Name: Beszel Monitoring
    2. Domain: monitor.tunnel.yourdomain.com
    3. Target: http://localhost:8090 (since it's on the same VPS)
    4. 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:

    Home Server Agent
    # 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:latest

    In 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:

    config/traefik/traefik_config.yml
    accessLog:
      filePath: "/var/log/traefik/access.log"
      format: json
      bufferingSize: 100
      filters:
        statusCodes:
          - "200-499"
      fields:
        headers:
          defaultMode: drop

    Restart Traefik to apply the changes. JSON format makes the logs easy to parse with tools like jq:

    Parse access logs with 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:

    /etc/logrotate.d/traefik
    /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:

    LayerToolFunction
    NetworkWireGuard (via Pangolin/Gerbil)Encrypted tunnel; no open ports at home
    Edge FilteringCrowdSecCommunity blocklist; attack pattern detection
    Brute-ForceFail2banRate limiting and IP banning for SSH and services
    IdentityPangolin SSO + OIDCPer-service authentication and authorization
    TransportTraefik + Let's EncryptSSL termination; automatic certificate management
    MonitoringBeszelReal-time metrics, Docker stats, and alerting
    AuditTraefik Access LogsFull 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.json file 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 upgrade on 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 →