Why?
I recently had to set up Traefik and Crowdsec on six virtual servers in a row. I decided it was easier to create a script that did all the installation for me, and now I'm sharing it.
Set up a Secure Docker Proxy in Minutes
wget https://raw.githubusercontent.com/MadJalapeno/homelab-traefik/refs/heads/main/install.sh
chmod +x install.sh
./install.sh
I recently had to set up Traefik and Crowdsec on six virtual servers in a row. I decided it was easier to create a script that did all the installation for me, and now I'm sharing it.
The script installs Traefik as your reverse proxy with automatic HTTPS certificates and integrates CrowdSec for intelligent threat protection. Everything runs in Docker containers.
$ ./install.sh
β Docker Installed
β Docker daemon is running
β Port 80 and 443 are free
β Installing Traefik & CrowdSec
β Setting up bouncers
β Generating SSL certificates
All done!
services:
nginx:
image: nginx
labels:
- "traefik.enable=true"
- "traefik.http.routers.nginx.rule=Host(`nginx.example.com`)"
- "traefik.http.routers.nginx.tls.certresolver=letsencrypt"
Traefik handles SSL certificates automatically via Let's Encrypt. Just add labels to your Docker services and certificates are obtained and renewed automatically.
CrowdSec monitors your traffic in real-time, detects malicious behavior, and automatically blocks threats. It shares intelligence with a global community to stay ahead of attackers.
$ cscli decisions list
ββββββββββββββββββββ¬βββββββββββ¬ββββββββββββββββ
β IP β Duration β Reason β
ββββββββββββββββββββΌβββββββββββΌββββββββββββββββ€
β 192.168.1.100 β 4h β bruteforce β
β 10.0.0.50 β 24h β http-probing β
β 172.16.0.10 β 1h β bad-reputationβ
ββββββββββββββββββββ΄βββββββββββ΄ββββββββββββββββ
$ docker ps
CONTAINER ID IMAGE
a1b2c3d4e5f6 traefik:latest
b2c3d4e5f6g7 crowdsec/crowdsec
c3d4e5f6g7h8 crowdsec/traefik-bouncer
$ docker network ls
NETWORK ID NAME
abc123def456 proxy
Three containers work together seamlessly: Traefik routes traffic, CrowdSec analyzes logs, and the bouncer blocks threats. All connected via a dedicated Docker network.
All configuration is stored in simple YAML files. Modify routing rules, add middleware, customize CrowdSec scenarios, or adjust security policies with ease.
$ tree config/
config/
βββ traefik/
β βββ traefik.yml
β βββ conf/
β βββ certs/
βββ crowdsec/
βββ acquis.yaml
βββ scenarios/
βββ custom-rules.yaml
Dashboards:
π· Traefik Dashboard
https://traefik.yourdomain.com
View routers, services, middleware
π‘οΈ CrowdSec Metrics
$ cscli metrics
Decisions, scenarios, parsers
Monitor everything through Traefik's web dashboard and CrowdSec's command-line tools. You can also sign up for more monitoring at https://crowdsec.net.
root@hetzner:/root# wget https://raw.githubusercontent.com/MadJalapeno/homelab-traefik/refs/heads/main/install.sh
--2025-12-14 00:15:18-- https://raw.githubusercontent.com/MadJalapeno/homelab-traefik/refs/heads/main/install.sh
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.111.133, 185.199.108.133, 185.199.110.133, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.111.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 8979 (8.8K) [text/plain]
Saving to: 'install.sh'
install.sh 100%[==================================================================================================================================================>] 8.77K --.-KB/s in 0s
2025-12-14 00:15:18 (32.6 MB/s) - 'install.sh' saved [8979/8979]
root@hetzner:/root# chmod +x install.sh
root@hetzner:/root# ./install.sh
V 0.1.0 - Grouped Stack Approach
*******
Checking system requirements
*******
β Docker installed (version: 28.5.1)
β Docker Compose installed (version: 2.40.2)
β Docker daemon is running
β Docker permissions OK
*******
Checking ports available
*******
Port 80 free
Port 443 free
Port 8080 free
All ports available!
Please enter your info
Your Domain Name for certificates: example.com
Your Cloudflare API Key: [create a key on cloudflare for your zone]
Email for Lets Encrypt: letsencrypt@example.com
Installation directory [/opt/docker/traefik-stack]:
Creating directory structure...
Certificates will be stored in: /opt/docker/traefik-stack/traefik/config/certs/
Dynamic configs monitored in: /opt/docker/traefik-stack/traefik/config/conf/
Downloading configuration files...
Cloning into '/opt/docker/traefik-stack'...
remote: Enumerating objects: 121, done.
remote: Counting objects: 100% (121/121), done.
remote: Compressing objects: 100% (89/89), done.
remote: Total 121 (delta 44), reused 86 (delta 23), pack-reused 0 (from 0)
Receiving objects: 100% (121/121), 22.30 KiB | 845.00 KiB/s, done.
Resolving deltas: 100% (44/44), done.
Configuring files with your information...
Updating .env file
Updating docker-compose.yml
Configuration complete
Creating Docker network...
Network 'proxy' already exists
Starting Traefik...
[+] Running 5/5
β traefik Pulled 9.5s
β 2d35ebdb57d9 Already exists 0.0s
β 8aeb4cefcd95 Pull complete 1.3s
β efdb5f46fa18 Pull complete 7.7s
β d4a90fc484f6 Pull complete 7.8s
[+] Running 1/1
β Container traefik Started 0.7s
Waiting for Traefik to initialize...
Traefik started
Starting CrowdSec...
[+] Running 10/10
β crowdsec Pulled 9.3s
β f637881d1138 Pull complete 1.0s
β 6774f787086e Pull complete 1.3s
β 069d0590ee44 Pull complete 4.6s
β 9aa81eb4aef6 Pull complete 4.7s
β a122a0eabcce Pull complete 4.7s
β 5940392cd12a Pull complete 4.7s
β c7071de5156d Pull complete 5.9s
β 4c6af1387582 Pull complete 6.0s
β 54f5f0313a47 Pull complete 7.7s
[+] Running 2/2
β Container traefik Running 0.0s
β Container crowdsec Started 2.9s
Waiting for CrowdSec to initialize before we grab an API key(60 seconds)...
60 50 40 30 20 10
CrowdSec started
Configuring CrowdSec Bouncer...
Generating API key...
API Key generated successfully
API Key: [redacted]
Starting CrowdSec Bouncer...
[+] Running 5/5
β bouncer Pulled 4.3s
β 79e0d8860fad Pull complete 0.9s
β bf75762436b0 Pull complete 1.3s
β 7e335a1999f3 Pull complete 1.4s
β 220a13292c9d Pull complete 1.7s
[+] Running 3/3
β Container traefik Running 0.0s
β Container crowdsec Running 0.0s
β Container bouncer-traefik Started 0.7s
Waiting for bouncer to start...
***************************************
Installation Complete!
***************************************
Installation Summary:
Installation directory: /opt/docker/traefik-stack
Domain: example.com
Traefik Dashboard: https://traefik.example.com
Services Status:
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
bouncer-traefik fbonalair/traefik-crowdsec-bouncer "/app" bouncer 6 seconds ago Up 5 seconds (health: starting)
crowdsec crowdsecurity/crowdsec:latest "/bin/bash /docker_sβ¦" crowdsec About a minute ago Up About a minute
traefik traefik:latest "/entrypoint.sh traeβ¦" traefik About a minute ago Up About a minute 0.0.0.0:80->80/tcp, [::]:80->80/tcp, 0.0.0.0:443->443/tcp, [::]:443->443/tcp, 0.0.0.0:8080->8080/tcp, [::]:8080->8080/tcp
Directory Structure:
/opt/docker/traefik-stack/
βββ docker-compose.yml # Main stack configuration
βββ .env # Environment variables
βββ logs/ # Traefik logs (monitored by CrowdSec)
βββ traefik/
β βββ config/
β βββ traefik.yml # Main Traefik config
β βββ certs/ # SSL certificates (acme.json)
β βββ conf/ # Dynamic configs (auto-monitored)
β βββ README.md # How to use dynamic configs
β βββ *.yml # Add your service configs here
βββ crowdsec/
βββ config/ # CrowdSec configuration
β βββ acquis.yaml # Log acquisition config
βββ data/ # CrowdSec data
Certificate Information:
Location: /opt/docker/traefik-stack/traefik/config/certs/acme.json
Provider: Let's Encrypt via Cloudflare DNS-01 challenge
Auto-renewal: Handled automatically by Traefik
Wildcard cert: *.example.com and example.com
Dynamic Configuration:
Monitored directory: /opt/docker/traefik-stack/traefik/config/conf/
Add .yml files here to configure new services
Changes are detected automatically (no restart needed)
See README.md in that directory for examples
Useful Commands (run from /opt/docker/traefik-stack):
docker compose ps # View all services
docker compose logs -f # View all logs
docker compose logs -f traefik # View Traefik logs
docker compose restart # Restart all services
docker compose down # Stop all services
docker compose up -d # Start all services
CrowdSec Commands:
docker exec crowdsec cscli decisions list # View blocked IPs
docker exec crowdsec cscli metrics # View metrics
docker exec crowdsec cscli alerts list # View alerts
docker exec crowdsec cscli bouncers list # View bouncers
Done! Your Traefik security stack is running.
root@hetzner:/root#