- You need a public domain
- Your domain has to be registered at Cloudflare.
- You need a server that is reachable from the internet. If you are running this on your home server you have to open ports 80 and 443 in your router. Otherwise traefik maybe isn't able to get the certificates from LetsEncrypt or Cloudflare.
If you don't clone this Project you have to create some folders and files.
mkdir proxy/data/authelia
mkdir proxy/data/authelia/config
touch proxy/data/authelia/config/configuration.yml
mkdir proxy/data/crowdsecurity
mkdir proxy/data/crowdsecurity/cs
touch proxy/data/crowdsecurity/cs/acquis.yaml
mkdir proxy/data/crowdsecurity/bouncer
mkdir proxy/data/crowdsecurity/bouncer/cloudflare
touch proxy/data/crowdsecurity/bouncer/cloudflare/cloudflare-cache.json
touch proxy/data/crowdsecurity/bouncer/cloudflare/cfg.yaml
mkdir proxy/data/crowdsecurity/metabase
cd proxy/data/crowdsecurity/metabase
wget https://crowdsec-statics-assets.s3-eu-west-1.amazonaws.com/metabase_sqlite.zip
unzip metabase_sqlite.zip
rm metabase_sqlite.zip
cd ../../../../
Now run it. It won't work but we need to execute some commands on the running container.
docker-compose up -d
Edit the .env
file to configure the environment variables
# ...
# Traefik
Cloudflare_Email='[email protected]' #<== Email from Cloudflair
Cloudflare_API_Traefik_Token='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' #<== API Token (Zone/Zone/Read and Zone/DNS/Edit) https://dash.cloudflare.com/profile/api-tokens
# Cloudflare-Companion - Automatic CNAME DNS Creation
Cloudflare_Zonen_ID='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' #<== Zone-id
Cloudflare_API_CfC_Token='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' #<== API Token (Zone/DNS/Edit) https://dash.cloudflare.com/profile/api-tokens
# Crowdsec Bouncer Key
Crowdsec_Bouncer_Traefik_API='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' #<== API Key Crowdsec Bouncer
# ...
The next steps will show you where you can get the missing pieces of information above:
Get the zone id of your domain from https://dash.cloudflare.com/
Get the API key from https://dash.cloudflare.com/profile/api-tokens
Get the API key from https://dash.cloudflare.com/profile/api-tokens
Register the traefik instance at https://pilot.traefik.io/ and get the key.
This step is only necessary if you don't use Authelia. So you still have a password in front of a website.
$ sudo apt-get install apache2-utils
$ echo $(htpasswd -nb USER PASSWORT) | sed -e s/\\$/\\$\\$/g
USER:$$apr1$$oG7U7xPg$$eq79AxEsQ0Q.YG9h1KxdI0
Register the traefik bouncer at the Crowdsec container.
$ docker exec proxy-crowdsec cscli bouncers add bouncer-traefik
API key for 'bouncer-traefik':
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Please keep this key since you will not be able to retrieve it!
$ nano proxy/data/crowdsecurity/cs/acquis.yaml
#Generated acquisition file - wizard.sh (service: sshd) / files : /var/log/auth.log
filenames:
- /var/log/auth.log
labels:
type: syslog
---
---
#Generated acquisition file - wizard.sh (service: mysql) / files : /var/log/mysql/error.log
filenames:
- /var/log/mysql/error.log
labels:
type: mysql
---
---
#Generated acquisition file - wizard.sh (service: linux) / files : /var/log/syslog /var/log/kern.log /var/log/messages
filenames:
- /var/log/syslog
- /var/log/kern.log
- /var/log/messages
labels:
type: syslog
---
---
filenames:
- /var/log/traefik/*
labels:
type: traefik
# source: docker
# container_name:
# - proxy-traefik
# labels:
# type: traefik
---
source: docker
container_name:
- proxy-authelia
labels:
type: authelia
This step can be skipped if you dont have a cloudflare paid plan. For the free plan there seems to be a limit of entries in the firewall of cloudflare. The following error will be thrown if you only have the free plan:
time="02-08-2023 08:18:59" level=error msg="error This account is at the maximum number of lists (10019) in creating IP List" account_id=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
time="02-08-2023 08:18:59" level=error msg="This account is at the maximum number of lists (10019)" account_id=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
time="02-08-2023 08:18:59" level=fatal msg="This account is at the maximum number of lists (10019)"
If you have a cloudflare paid plan. Continue here: First generate the config file with the following command:
docker run crowdsecurity/cloudflare-bouncer \
-g <CLOUDFLARE_TOKEN> > cfg.yaml
$ nano proxy/data/crowdsecurity/bouncer/cloudflare/cfg.yaml
The config should look like this:
# Config generated by using /etc/crowdsec/bouncers/crowdsec-cloudflare-bouncer.yaml as base
crowdsec_lapi_url: http://proxy-crowdsec:8080/
crowdsec_lapi_key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
crowdsec_update_frequency: 10s
include_scenarios_containing: [] # ignore IPs banned for triggering scenarios not containing either of provided word
exclude_scenarios_containing: [] # ignore IPs banned for triggering scenarios containing either of provided word
only_include_decisions_from: [] # only include IPs banned due to decisions orginating from provided sources. eg value ["cscli", "crowdsec"]
cloudflare_config:
accounts:
- id: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #[email protected]'s Account
zones:
- zone_id: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #kropp.link
actions:
- managed_challenge
token: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
ip_list_prefix: crowdsec
default_action: managed_challenge
total_ip_list_capacity: 10000 # only this many latest IP decisions would be kept
update_frequency: 10s
daemon: false
log_mode: stdout
log_dir: /var/log/
log_level: info
log_max_size: 0
log_max_age: 0
log_max_backups: 0
compress_logs: null
prometheus:
enabled: true
listen_addr: 127.0.0.1
listen_port: "2112"
key_path: ""
cert_path: ""
ca_cert_path: ""
The next steps will show you where you can get the missing pieces of information above:
$ docker exec proxy-crowdsec cscli -oraw bouncers add cloudflarebouncer
API key for 'cloudflarebouncer':
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Please keep this key since you will not be able to retrieve it!
Go to https://dash.cloudflare.com/profile/api-tokens and click on Create Token
and then Create Custom Token
$ nano proxy/data/authelia/config/configuration.yml
###############################################################
# Authelia configuration #
###############################################################
server.host: 0.0.0.0
server.port: 9091
log.level: debug
# log:
# level: debug
# format: text
# file_path: "/logs/Authelia.log"
# keep_stdout: false
theme: dark
# This secret can also be set using the env variables AUTHELIA_JWT_SECRET_FILE
jwt_secret: ---->PUT HERE A SECRET WICH IS 64 CHARACTERS LONG<----
default_redirection_url: https://auth.---->PUT YOUR DOMAIN HERE<----
totp:
issuer: authelia.com
ntp:
address: "time.cloudflare.com:123"
version: 4
max_desync: 3s
disable_startup_check: false
disable_failure: false
# duo_api:
# hostname: api-123456789.---->PUT YOUR DOMAIN HERE<----
# integration_key: ABCDEF
# # This secret can also be set using the env variables AUTHELIA_DUO_API_SECRET_KEY_FILE
# secret_key: 1234567890abcdefghifjkl
authentication_backend:
file:
path: /config/users_database.yml
password:
algorithm: argon2id
iterations: 1
salt_length: 16
parallelism: 8
memory: 64
access_control:
default_policy: two_factor
networks:
- name: internal
networks:
- '10.0.0.0/8'
- '172.16.0.0/12'
- '192.168.0.0/18'
- '192.168.179.0/24'
- '172.0.0.1'
rules:
- domain: # Rules applied to everyone
- "proxy.---->PUT YOUR DOMAIN HERE<----"
- "sec.---->PUT YOUR DOMAIN HERE<----"
policy: two_factor
subject:
- "group:admin"
- domain:
- "whoami.---->PUT YOUR DOMAIN HERE<----"
policy: bypass
- domain:
- "---->PUT YOUR DOMAIN HERE<----"
- "www.---->PUT YOUR DOMAIN HERE<----"
policy: one_factor
subject:
- "group:admin"
- "group:user"
session:
name: authelia_session
# This secret can also be set using the env variables AUTHELIA_SESSION_SECRET_FILE
secret: ---->PUT HERE A SECRET WICH IS 128 CHARACTERS LONG<----
expiration: 3600 # 1 hour
#inactivity: 3600 # 1 hour
remember_me_duration: 604800 # 7 days
domain: ---->PUT YOUR DOMAIN HERE<---- # Should match whatever your root protected domain is
regulation:
max_retries: 3
find_time: 120
ban_time: 300
storage:
encryption_key: '---->PUT HERE A SECRET WICH IS 128 CHARACTERS LONG<----'
local:
path: /config/db.sqlite3
notifier:
filesystem:
filename: /config/notification.txt
# disable_startup_check: true
# smtp:
# host: ---->PUT MAIL SERVER HERE<----
# port: 465 #you maybe have to change this port
# timeout: 60s
# username: ---->PUT YOUR MAIL HERE<----
# password: '---->PUT YOUR MAIL PASSWORT HERE<----'
# sender: ---->PUT YOUR MAIL HERE<----
# identifier: ---->PUT MAIL SERVER HERE<----
# subject: "[Authelia] {title}"
# startup_check_address: ---->PUT YOUR MAIL HERE<----
# disable_require_tls: false
# disable_html_emails: false
# tls:
# server_name: ---->PUT MAIL SERVER HERE<----
# skip_verify: false
# minimum_version: TLS1.2
- Replace all arrows in the
configuration.yml
with your information (---->PUT YOUR DOMAIN HERE<----)
$ nano proxy/data/authelia/config/users_database.yml
#docker run authelia/authelia:latest authelia hash-password -- 'password'
users:
[email protected]:
password: $argon2id$v=19$m=65536,t=3,p=4$R2dqcnNrOFJMN2F4UElDZw$3wLhazMUu39DaT44gVlc3d/0PPZABwQFXN4ecU/ucM4
displayname: "test user"
email: [email protected]
groups:
- admin
- dev
You can generate a hash value for the password with the following command. Replace the above one with your own:
$ docker run authelia/authelia:latest authelia hash-password -- 'password'
Password hash: $argon2id$v=19$m=65536,t=3,p=4$R2dqcnNrOFJMN2F4UElDZw$3wLhazMUu39DaT44gVlc3d/0PPZABwQFXN4ecU/ucM4
After this step, everything should be working. Now restart the containers.
#Restart
./docker.sh -S proxy -s
./docker.sh -S proxy -r
Now open https://auth.example.com and login
It will say:
but in reality, there is no mail. The link to register a new device was written in a file called notification.txt
cat proxy/data/authelia/config/notification.txt
Example output:
Date: 2022-09-28 15:59:45.79465267 +0200 CEST m=+27.414134998
Recipient: { [email protected]}
Subject: Register your mobile
Body: This email has been sent to you in order to validate your identity.
If you did not initiate the process your credentials might have been compromised and you should reset your password and contact an administrator.
To setup your 2FA please visit the following URL: https://auth.example.com/one-time-password/register?token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx....
This email was generated by a user with the IP 123.45.678.90.
Please contact an administrator if you did not initiate this process.
Now open the link and scan the QR code with a 2-factor app.
After that, you can now log in with your username, password, and 2fa.
Open:
- Traefik: https://proxy.Traexample.com/
- Crowdsec: https://sec.Traexample.com/
- default login for metabase: [email protected] and !!Cr0wdS3c_M3t4b4s3??
- Whoami: https://whoami.Traexample.com/
From now on it's pretty simple to add a new web container with traefik as a reverse proxy in front of it and authelia and crowdsec to protect it. You just have to add those lines to the container in the docker-compose.yml
file:
networks:
- proxy
labels:
- "traefik.enable=true" #<== Enable traefik
- "traefik.http.routers.EXAMPLE-secured.rule=Host(`EXAMPLE.${DOMAIN}`)" #<== Set domain
- "traefik.http.routers.EXAMPLE-secured.entrypoints=websecure" #<== Set entry point for HTTPS
- "traefik.http.routers.EXAMPLE-secured.tls.certresolver=mytlschallenge" #<== Set certsresolvers for https
- "traefik.http.routers.EXAMPLE-secured.middlewares=authelia" #<== Add Authelia middlewares to protect login
- "traefik.http.routers.EXAMPLE-secured.service=EXAMPLE-service" #<== Set service
- "traefik.http.services.EXAMPLE-service.loadbalancer.server.port=80" #<== Set target port on container
Now replace the word EXAMPLE
with the name of the container and replace the destination port in the last line. Example with whoami
:
whoami:
image: traefik/whoami
container_name: whoami
restart: unless-stopped
networks:
- proxy
labels:
- "traefik.enable=true" #<== Enable traefik
- "traefik.http.routers.whoami-secured.rule=Host(`whoami.${DOMAIN}`)" #<== Set domain
- "traefik.http.routers.whoami-secured.entrypoints=websecure" #<== Set entry point for HTTPS
- "traefik.http.routers.whoami-secured.tls.certresolver=mytlschallenge" #<== Set certsresolvers for https
- "traefik.http.routers.whoami-secured.middlewares=authelia" #<== Add Authelia middlewares to protect login
- "traefik.http.routers.whoami-secured.service=whoami-service" #<== Set service
- "traefik.http.services.whoami-service.loadbalancer.server.port=80" #<== Set target port on container
Now you can reach this container over HTTPS with the domain whoami.example.com
.
Traefik:
Crowdsec:
Authelia: