Chapter 16: Securing Your Web Services with Authelia
Did you like the login screen at the front of this website? Securing your web services is an absolute must if you are going to expose them to the internet. Some, like Vaultwarden and NextCloud, come with their own authentication, including two-factor logins, so Authelia is not needed. You could double up and still put Authelia in front of these services but bear in mind that it will lower the usability. Sending links, doing video calls, or using mobile apps will no longer be possible. And at that point, why even bother putting them onto the internet as you might as well just do a VPN-only setup.
Use Authelia instead to secure services that don't offer good authentication. A dashboard, for example, should under no circumstances be exposed to the internet without a login. That doesn't stop people from doing it though and if you try hard enough, you can discover people's unsecured dashboards out in the wilds of the internet. Don't be like those users. But always ask yourself before putting something behind a domain name if it's really necessary to begin with.
In addition to Docker containers for Authelia, we'll also make one for Redis, or Remote Dictionary Server. Authelia will use Redis to handle its cache.
Unlike Vaultwarden and NextCloud, we're not going to consider a VPN-only configuration. For that reason, we will need a domain name. If you don't plan on using a domain for any of your services and are using local access only, then there's no need to secure it behind Authelia. Your VPN configuration is protection enough.
Step 1: Create the Authelia DNS Record
Login to your registrar and create a DNS A record. Use "auth" or something similar as the subdomain and ensure it points to your public IP. Refer to Chapter 9 for updating your dynamic DNS service to cover this new subdomain. You may need to wait an hour or two before the record propagates.
Step 2: Prepare the Docker Container
- Create a directory for the Authelia docker container.
mkdir authelia - Go into the directory.
cd authelia - Now make two more directories. One will be for the Authelia configuration, the other for redis
mkdir configmkdir redis - Now create the docker-compose.yml
nano docker-compose.yml - Copy and paste the following:
version: '3.3'
services:
authelia:
image: authelia/authelia
volumes:
- ./config:/config
ports:
- 9091:9091
restart: unless-stopped
healthcheck:
disable: true
environment:
- TZ=America/New_York
depends_on:
- redis
redis:
image: redis:alpine
volumes:
- ./redis:/data
expose:
- 6379
restart: unless-stopped
environment:
- TZ=America/New_York
With Authelia, you have four policies you can set for a domain. Deny will not allow any access. That's a good default policy. Much like our firewall, we have to specifically add a domain to our Allow List in order to grant access. Bypass is the opposite and will not provide any authentication challenge to a user. We're going to make this the policy for anything running on our local network. Finally, one_factor and two_factor are what bring up the challenge page, as seen on this website. Setting to one_factor will be password only while two_factor will require something like an authenticator app. Use the below as a general template and adjust as needed for your domains.
Step 3: Configure Authelia
- Create a configuration file in the
configdirectory.nano config/configuration.yml - Copy and paste the following, changing values as needed:
###############################################################
# Authelia configuration #
###############################################################
server:
host: 0.0.0.0
port: 9091
jwt_secret: <Generate a random series of characters>
log:
level: debug
default_redirection_url: <The auth subdomain, like https://auth.example.com>
totp:
issuer: <Your TLD, like example.com>
period: 30
skew: 1
authentication_backend:
disable_reset_password: false
file:
path: /config/users_database.yml
password:
algorithm: argon2id
iterations: 1
salt_length: 16
parallelism: 8
memory: 64
access_control:
default_policy: deny
rules:
- domain:
- "*"
networks:
- <Pi IP Address>/24
policy: bypass
- domain:
- "<passwordlogin1.example.com>"
- "<passwordlogin2.example.com>"
policy: one_factor
- domain:
- "<twofactor.example.com>"
policy: two_factor
session:
name: authelia_session
secret: <Another long secret password, random characters preferably>
expiration: 3600 # 1 hour
inactivity: 7200 # 2 hours
domain: <Your TLD, like example.com>
redis:
host: authelia_redis_1
port: 6379
regulation:
max_retries: 5
find_time: 2m
ban_time: 10m
theme: dark
storage:
encryption_key: <Another long random string here>
local:
path: /config/db.sqlite3
notifier:
filesystem:
filename: /config/notification.txt
Step 4: Configure Caddy
- Go to the location of your Caddyfile (most likely your home directory) and open it for editing.
nano Caddyfile - Create a normal reverse proxy entry for Authelia. This example will use the discopter.tech domain. Adjust yours as needed.
# Authelia
auth.discopter.tech {
reverse_proxy <Pi IP>:9091
} - Create or edit the reverse proxy settings for the service you wish to protect.
# Pi Workshop Website
pi.discopter.tech {
forward_auth <Pi IP and Authelia port> {
uri /api/verify?rd=https://auth.discopter.tech
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
}
reverse_proxy <Pi IP and service port>
}
The next step involves creating user accounts. To simplify setup, we're using the default SQLite database with Caddy. This will support a group of family and friends, and perhaps a guest account. If you are going to add more than about eight accounts, you may wish to look into configuring Authelia to use a more robust database, like MySQL or MariaDB. For each user, the username is at the top level of each entry. You'll also specify a display name. You can optionally specify groups. Group settings are more for professional use of Authelia with administrators, so don't put too much thought into them. You are most likely the only person who will be configuring Authelia, so group policies aren't so much a thing you'll need to worry about.
Another value to specify is the email. In Step 3, at the bottom of the Authelia configuration file, we set the notifications to create a text file in the config directory. In order to actually email a user, you'd need to setup a mail server on the Pi. Trust me when I say it's not worth it. As a result, put whatever you want as the email. Any "emails" Authelia generates will just create text files on your Pi instead.
Step 5: Create User Accounts
- Passwords have to be hashed. Run the following command for each user's password:
docker run authelia/authelia:latest authelia hash-password '<user password>' - Create the user database in the
configdirectorynano config/users_database.yml - Input something like the below:
users:
admin:
displayname: "Admin"
password: "<Argon hashed password made in Step 5.1>"
email: [email protected]
groups:
- admins
spouse:
displayname: "Spousey McSpouse"
password: "<Another argon hashed password made in Step 5.1>"
email: [email protected]
groups: []
Step 6: Finish Up
- Reload Caddy, if you haven't already.
caddy reload
Deal with any formatting errors, per Chapter 13. - Make sure you are in the
autheliadirectory containingdocker-compose.yml - Build the container.
docker-compose up -d - Try to access your service. It should give you the Authelia challenge page you see when trying to access this site.
And now your domain is protected by Authelia. If using two factor authentication, be sure to setup an authenticator app. You may need to help a user of an account the first time as any "emails" sent to them will be in the authelia/config/notification.txt file. If you run into any trouble, check the logs for the container.
docker logs authelia_authelia_1 Something else to note, if you decide to start getting ambitious with Authelia. Your Docker container instance will only protect one TLD at a time. If you get another TLD, you'll have to spin up another container. Your can manage all of your domains in one Caddyfile though.
