Discopter Pi Guide

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

  1. Create a directory for the Authelia docker container.
    mkdir authelia
  2. Go into the directory.
    cd authelia
  3. Now make two more directories. One will be for the Authelia configuration, the other for redis
    mkdir config
    mkdir redis
  4. Now create the docker-compose.yml
    nano docker-compose.yml
  5. 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

  1. Create a configuration file in the config directory.
    nano config/configuration.yml
  2. 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

  1. Go to the location of your Caddyfile (most likely your home directory) and open it for editing.
    nano Caddyfile
  2. 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
    }
  3. 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

  1. Passwords have to be hashed. Run the following command for each user's password:
    docker run authelia/authelia:latest authelia hash-password '<user password>'
  2. Create the user database in the config directory
    nano config/users_database.yml
  3. 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

  1. Reload Caddy, if you haven't already.
    caddy reload
    Deal with any formatting errors, per Chapter 13.
  2. Make sure you are in the authelia directory containing docker-compose.yml
  3. Build the container.
    docker-compose up -d
  4. 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.