MFA behind Caddy
Two factor authantication on selfhosted services behind caddy with caddy-security lug-in
what you’ll get:
- A portal with links to your selfhosted services protected behind a reverse proxy
- Automated redirects to https with automatic ssl
- Two factor authentication
This caddy plugin minimises your requred domains as youll only need one dynamic dns domain name and the plugin will handle the redirects to your internal localhost ip’s that your services reside.
Note that youll need to authenticate your service either from your portal url or the direct service URL you specify in the plug in
what you’ll need:
- caddyserver
- caddy-security plugin
- xcaddy
- GO language
- bcrypt-cl (optional)
Bellow commands are for arch, use you package manager.
# Install go
sudo pacman -S go
install xcaddy
go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest
Build caddy with the caddy-security plugins for arm using GOOS and GOARCH env variables:
1
2
3
4
GOOS=linux GOARCH=arm64 go/bin/xcaddy build \
--with github.com/greenpau/caddy-security \
--with github.com/greenpau/caddy-trace \
--with github.com/caddy-dns/cloucloudflare
this will create a caddy executable in your HOME
- move to to /usr/bin
sudo cp caddy /usr/bin/
- Test that it worked
caddy version
install bcrypt-cl to create hash for passwords
go install github.com/ryicoh/bcrypt-cli@latest
- add ~/go/bin to PATH
export PATH=~/go/bin:$PATH
-
select your password e.g. “mypassoword”
-
get the hash
echo "mypassoword" | bcrypt-CLI
- create caddy config dir
sudo mkdir /etc/caddy/
- create caddy config
sudo nano /etc/caddy/Caddyfile
paste
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
{
order authenticate first
order trace before reverse_proxy
order authorize before reverse_proxy
security {
messaging email provider localhost-smtp-server {
address 192.168.1.24:1025 #your raspberry's ip
protocol smtp
passwordless
sender root@localhost "My Auth Portal"
bcc ippo@localhost #your random username
}
authentication portal myportal {
crypto default token lifetime 3600
crypto key sign-verify {env.JWT_SECRET}
backend local /var/lib/caddy/users.json local #use caddy's $HOME so that it can write
cookie domain ippocratis.duckdns.org #your valid dynamic dns pointing in your raspberry
ui {
links { # Icons here -> https://icons8.com/line-awesome
"radicale" https://radicale.ippocratis.duckdns.org icon "las la-cloud"
"photoprism" https://photoprism.ippocratis.duckdns.org icon "las la-photo-video"
"wallabag" https://wallabag.ippocratis.duckdns.org icon "las la-tv"
}
}
transform user {
match origin local
action add role authp/user
ui link "Portal Settings" /settings icon "las la-cog"
}
}
authorization policy mypolicy {
set auth url https://auth.ippocratis.duckdns.org/
crypto key verify {env.JWT_SECRET}
allow roles authp/admin authp/user
}
}
}
auth.ippocatis.duckdns.org {
route {
authenticate with myportal
}
}
radicale.ippocratis.duckdns.org {
authorize with mypolicy
reverse_proxy localhost:5232
}
photoprism.ippocratis.duckdns.org {
authorize with mypolicy
reverse_proxy localhost:2342
}
- Create a group named caddy
sudo groupadd --system caddy
- Create a user named caddy, with a writeable home directory
1
2
3
4
5
6
7
sudo useradd --system \
--gid caddy \
--create-home \
--home-dir /var/lib/caddy \
--shell /usr/sbin/nologin \
--comment "Caddy web server" \
caddy
- choose a systemd unit file
https://github.com/caddyserver/dist/blob/master/init/caddy.service
- copy it
The usual place to save the service file is: /etc/systemd/system/caddy.service
on manjaro arm its under
/etc/systemd/system/multi-user.target.wants/caddy.service
- create service
sudo nano /etc/systemd/system/multi-user.target.wants/caddy.service
paste it
- reload daemon
sudo systemctl daemon-reload
- enable unit
sudo systemctl enable --now caddy
- grab the webadmin users password from logs (will change later)
journalctl -u caddy --no-pager | grep webadmin@localdomain.local
-
copy secret
-
navigate to auth.ippocratis.duckdns.org (auth url in our example)
user = webadmin pass = your copied secret
- change password
on the web interface
go to portal settings
passwords
and change it
password criteria (length,lower/upercase etc) is under /var/lib/caddy/users.json
add multifactor authentication
on the web interface
go to portal settings
mfa
add mfa app
scan qr
open your mfa app eg aegis and scan the qr
relogin to test it
user and password are stored in /var/lib/caddy/users.json
select caddy’s $HOME (/var/lib/caddy) as caddy may not be able to write on other dirs
- test redirections
on the web interface open a link e.g. radicale in our example
then log out
cookie should not let you log in with the “direct url”
try to to navigate to radicale.ippocratis.duckdns.org in our example the radicale redir
it should ask you your mfa key and not let you in
Enjoy