diff --git a/manuscript/docker-swarm/authelia.md b/manuscript/docker-swarm/authelia.md index b281f7c..3dac9d8 100644 --- a/manuscript/docker-swarm/authelia.md +++ b/manuscript/docker-swarm/authelia.md @@ -3,11 +3,11 @@ title: Using Authelia to secure services in Docker description: Authelia is an open-source authentication and authorization server providing 2-factor authentication and single sign-on (SSO) for your applications via a web portal. --- -# Authelia +# Authelia in Docker Swarm -[Authelia](https://github.com/authelia/authelia) is an open-source authentication and authorization server providing 2-factor authentication and single sign-on (SSO) for your applications via a web portal. It acts as a companion of reverse proxies like Nginx, Traefik, or HAProxy to let them know whether queries should pass through. Unauthenticated users are redirected to Authelia Sign-in portal instead. +[Authelia](https://github.com/authelia/authelia) is an open-source authentication and authorization server providing 2-factor authentication and single sign-on (SSO) for your applications via a web portal. Like [Traefik Forward Auth][tfa], Authelia acts as a companion of reverse proxies like Nginx, [Traefik](/docker-swarm/traefik/), or HAProxy to let them know whether queries should pass through. Unauthenticated users are redirected to Authelia Sign-in portal instead. Authelia is a popular alternative to a heavyweight such as [KeyCloak][keycloak]. -![Authelia Screenshot](../images/authelia.png){ loading=lazy } +![Authelia Screenshot](/images/authelia.png){ loading=lazy } Features include @@ -47,96 +47,96 @@ Authelia configurations are defined in `/var/data/config/authelia/configuration. !!! warning Your variables may vary significantly from what's illustrated below, and it's best to read up and understand exactly what each option does. -???+ note "Much scroll, very text. Click here to collapse it for better readability" +```yaml title="/var/data/config/authelia/configuration.yml" +############################################################### +# Authelia configuration # +############################################################### - ```yaml - ############################################################### - # Authelia configuration # - ############################################################### +server: + host: 0.0.0.0 + port: 9091 - server: - host: 0.0.0.0 - port: 9091 +log: + level: warn - log: - level: warn +# This secret can also be set using the env variables AUTHELIA_JWT_SECRET_FILE +# I used this site to generate the secret: https://www.grc.com/passwords.htm +jwt_secret: SECRET_GOES_HERE - # This secret can also be set using the env variables AUTHELIA_JWT_SECRET_FILE - # I used this site to generate the secret: https://www.grc.com/passwords.htm - jwt_secret: SECRET_GOES_HERE +# https://docs.authelia.com/configuration/miscellaneous.html#default-redirection-url +default_redirection_url: https://authelia.example.com - # https://docs.authelia.com/configuration/miscellaneous.html#default-redirection-url - default_redirection_url: https://authelia.example.com +totp: + issuer: authelia.example.com + period: 30 + skew: 1 - totp: - issuer: authelia.example.com - period: 30 - skew: 1 +authentication_backend: + file: + path: /config/users_database.yml + # customize passwords based on https://docs.authelia.com/configuration/authentication/file.html + password: + algorithm: argon2id + iterations: 1 + salt_length: 16 + parallelism: 8 + memory: 1024 # blocks this much of the RAM. Tune this. - authentication_backend: - file: - path: /config/users_database.yml - # customize passwords based on https://docs.authelia.com/configuration/authentication/file.html - password: - algorithm: argon2id - iterations: 1 - salt_length: 16 - parallelism: 8 - memory: 1024 # blocks this much of the RAM. Tune this. +# https://docs.authelia.com/configuration/access-control.html +access_control: + default_policy: one_factor + rules: + - domain: "bitwarden.example.com" + policy: two_factor - # https://docs.authelia.com/configuration/access-control.html - access_control: - default_policy: one_factor - rules: - - domain: "bitwarden.example.com" - policy: two_factor + - domain: "whoami-authelia-2fa.example.com" + policy: two_factor - - domain: "whoami-authelia-2fa.example.com" - policy: two_factor - - - domain: "*.example.com" - policy: one_factor + - domain: "*.example.com" # (1)! + policy: one_factor - session: - name: authelia_session - # This secret can also be set using the env variables AUTHELIA_SESSION_SECRET_FILE - # Used a different secret, but the same site as jwt_secret above. - secret: SECRET_GOES_HERE - expiration: 3600 # 1 hour - inactivity: 300 # 5 minutes - domain: example.com # Should match whatever your root protected domain is +session: + name: authelia_session + # This secret can also be set using the env variables AUTHELIA_SESSION_SECRET_FILE + # Used a different secret, but the same site as jwt_secret above. + secret: SECRET_GOES_HERE + expiration: 3600 # 1 hour + inactivity: 300 # 5 minutes + domain: example.com # Should match whatever your root protected domain is - regulation: - max_retries: 3 - find_time: 120 - ban_time: 300 +regulation: + max_retries: 3 + find_time: 120 + ban_time: 300 - storage: - encryption_key: SECRET_GOES_HERE_20_CHARACTERS_OR_LONGER - local: - path: /config/db.sqlite3 +storage: + encryption_key: SECRET_GOES_HERE_20_CHARACTERS_OR_LONGER + local: + path: /config/db.sqlite3 - notifier: - # smtp: - # username: SMTP_USERNAME - # # This secret can also be set using the env variables AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE - # # password: # use docker secret file instead AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE - # host: SMTP_HOST - # port: 587 #465 - # sender: batman@example.com # customize for your setup +notifier: + # smtp: + # username: SMTP_USERNAME + # # This secret can also be set using the env variables AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE + # # password: # use docker secret file instead AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE + # host: SMTP_HOST + # port: 587 #465 + # sender: batman@example.com # customize for your setup - # For testing purpose, notifications can be sent in a file. Be sure map the volume in docker-compose. - filesystem: - filename: /config/notification.txt - ``` + # For testing purpose, notifications can be sent in a file. Be sure map the volume in docker-compose. + filesystem: + filename: /config/notification.txt +``` + +1. The wildcard rule must go last, since the first rule to match the request, wins ### Create Authelia user Accounts Create `/var/data/config/authelia/users_database.yml` this will be where we can create user accounts and give them groups -```yaml +```yaml title="/var/data/config/authelia/users_database.yml" # To create a hashed password you can run the following command: # `docker run authelia/authelia:latest authelia hash-password YOUR_PASSWORD`` users: @@ -159,65 +159,59 @@ Create a docker swarm config file in docker-compose syntax (v3), something like --8<-- "premix-cta.md" -???+ note "Much scroll, very YAML. Click here to collapse it for better readability" +```yaml title="/var/data/config/authelia/authelia.yml" +version: "3.2" - ```yaml - version: "3.2" +services: + authelia: + image: authelia/authelia + volumes: + - /var/data/config/authelia:/config + networks: + - traefik_public + deploy: + labels: + # traefik common + - traefik.enable=true + - traefik.docker.network=traefik_public - services: - authelia: - image: authelia/authelia - volumes: - - /var/data/config/authelia:/config - networks: - - traefik_public - deploy: - labels: - # traefik common - - traefik.enable=true - - traefik.docker.network=traefik_public + # traefikv1 + - traefik.frontend.rule=Host:authelia.example.com + - traefik.port=80 + - 'traefik.frontend.auth.forward.address=http://authelia:9091/api/verify?rd=https://authelia.example.com/' + - 'traefik.frontend.auth.forward.trustForwardHeader=true' + - 'traefik.frontend.auth.forward.authResponseHeaders=Remote-User,Remote-Groups,Remote-Name,Remote-Email' - # traefikv1 - - traefik.frontend.rule=Host:authelia.example.com - - traefik.port=80 - - 'traefik.frontend.auth.forward.address=http://authelia:9091/api/verify?rd=https://authelia.example.com/' - - 'traefik.frontend.auth.forward.trustForwardHeader=true' - - 'traefik.frontend.auth.forward.authResponseHeaders=Remote-User,Remote-Groups,Remote-Name,Remote-Email' + # traefikv2 + - "traefik.http.routers.authelia.rule=Host(`authelia.example.com`)" + - "traefik.http.routers.authelia.entrypoints=https" + - "traefik.http.services.authelia.loadbalancer.server.port=9091" + + whoami-1fa: # (1)! + image: containous/whoami + networks: + - traefik_public + deploy: + labels: + # traefik + - "traefik.enable=true" + - "traefik.docker.network=traefik_public" - # traefikv2 - - "traefik.http.routers.authelia.rule=Host(`authelia.example.com`)" - - "traefik.http.routers.authelia.entrypoints=https" - - "traefik.http.services.authelia.loadbalancer.server.port=9091" - # - "traefik.http.middlewares.authelia.forwardauth.address=http://authelia:9091/api/verify?rd=https://authelia.example.com" - # - "traefik.http.middlewares.authelia.forwardauth.trustForwardHeader=true" - # - "traefik.http.middlewares.authelia.forwardauth.authResponseHeaders=Remote-User, Remote-Groups" + # traefikv1 + - "traefik.frontend.rule=Host:whoami-authelia-1fa.example.com" + - traefik.port=80 + - 'traefik.frontend.auth.forward.address=http://authelia:9091/api/verify?rd=https://authelia.example.com/' + - 'traefik.frontend.auth.forward.trustForwardHeader=true' + - 'traefik.frontend.auth.forward.authResponseHeaders=Remote-User,Remote-Groups,Remote-Name,Remote-Email' - # This simply validates that traefik forward authentication is working - whoami-1fa: - image: containous/whoami - networks: - - traefik_public - deploy: - labels: - # traefik - - "traefik.enable=true" - - "traefik.docker.network=traefik_public" - - # traefikv1 - - "traefik.frontend.rule=Host:whoami-authelia-1fa.example.com" - - traefik.port=80 - - 'traefik.frontend.auth.forward.address=http://authelia:9091/api/verify?rd=https://authelia.example.com/' - - 'traefik.frontend.auth.forward.trustForwardHeader=true' - - 'traefik.frontend.auth.forward.authResponseHeaders=Remote-User,Remote-Groups,Remote-Name,Remote-Email' - - # traefikv2 - - "traefik.http.routers.whoami-authelia-1fa.rule=Host(`whoami-authelia-1fa.example.com`)" - - "traefik.http.routers.whoami-authelia-1fa.entrypoints=https" - - "traefik.http.routers.whoami-authelia-1fa.middlewares=authelia" - - "traefik.http.services.whoami-authelia-1fa.loadbalancer.server.port=80" + # traefikv2 + - "traefik.http.routers.whoami-authelia-1fa.rule=Host(`whoami-authelia-1fa.example.com`)" + - "traefik.http.routers.whoami-authelia-1fa.entrypoints=https" + - "traefik.http.routers.whoami-authelia-1fa.middlewares=authelia" + - "traefik.http.services.whoami-authelia-1fa.loadbalancer.server.port=80" - whoami-2fa: + whoami-2fa: # (2)! image: containous/whoami networks: - traefik_public @@ -242,26 +236,44 @@ Create a docker swarm config file in docker-compose syntax (v3), something like networks: traefik_public: - external: true - ``` + external: true +``` + +1. Optionally used to test 1FA authentication +2. Optionally used to test 2FA authentication + !!! question "Why not just use Traefik Forward Auth?" - [Traefik Forward Auth][tfa] is a very minimal authentication layer that provides google and openID authentication. Authelia provides more features such as multiple methods of authentication (*Hardware, OTP, Email*) and push notifications. + While [Traefik Forward Auth][tfa] is a very lightweight, minimal authentication layer, which provides OIDC-based authentication, Authelia provides more features such as multiple methods of authentication (*Hardware, OTP, Email*), advanced rules, and push notifications. -## Serving - -### Launch Authelia! +## Run Authelia Launch the Authelia stack by running ```docker stack deploy authelia -c ``` -## Test Authelia +### Test Authelia -To test the service works successfully, try logging into authelia itself first, as a user whose password you've setup in `/var/data/config/authelia/users_database.yml`. You'll notice that upon successful login, you're requested to setup 2FA. You probably didn't configure an SMTP server, but the contents of the email request should be found in ``/var/data/config/authelia/notifications.txt` +To test the service works successfully, try logging into Authelia itself first, as a user whose password you've setup in `/var/data/config/authelia/users_database.yml`. + +You'll notice that upon successful login, you're requested to setup 2FA. If (*like me!*) you didn't configure an SMTP server, you can still setup 2FA (*TOTP or webauthn*), and the setup link email instructions should be found in `/var/data/config/authelia/notifications.txt` Now you're ready to test 1FA and 2FA auth, against the two "whoami" services defined in the docker-compose file. -Try to access each in turn, and confirm that you're _not_ prompted for 2FA on whoami-authelia-1fa, but you _are_ prompted for 2FA on whoami-authelia-2fa ;) +Try to access each in turn, and confirm that you're _not_ prompted for 2FA on whoami-authelia-1fa, but you _are_ prompted for 2FA on whoami-authelia-2fa! :thumbsup: + +## Summary + +What have we achieved? By adding a simple label to any service, we can secure any service behind our Authelia, with minimal processing / handling overhead, and benefit from the 1FA/2FA multi-layered features provided by Autheila. + +!!! summary "Summary" + Created: + + * [X] Authelia configured and available to provide a layer of authentication to other services deployed in the stack + +### Authelia vs Keycloak + +[KeyCloak][keycloak] is the "big daddy" of self-hosted authentication platforms - it has a beautiful GUI, and a very advanced and mature featureset. Like Authelia, KeyCloak can [use an LDAP server](/recipes/keycloak/authenticate-against-openldap/) as a backend, but _unlike_ Authelia, KeyCloak allows for 2-way sync between that LDAP backend, meaning KeyCloak can be used to _create_ and _update_ the LDAP entries (*Authelia's is just a one-way LDAP lookup - you'll need another tool to actually administer your LDAP database*). + [^1]: The initial inclusion of Authelia was due to the efforts of @bencey in Discord (Thanks Ben!) diff --git a/manuscript/docker-swarm/traefik-forward-auth/keycloak.md b/manuscript/docker-swarm/traefik-forward-auth/keycloak.md index 018d20e..d2c5b1b 100644 --- a/manuscript/docker-swarm/traefik-forward-auth/keycloak.md +++ b/manuscript/docker-swarm/traefik-forward-auth/keycloak.md @@ -96,4 +96,9 @@ What have we achieved? By adding an additional three simple labels to any servic [^1]: Keycloak is very powerful. You can add 2FA and all other clever things outside of the scope of this simple recipe ;) +### Keycloak vs Authelia + +[KeyCloak][keycloak] is the "big daddy" of self-hosted authentication platforms - it has a beautiful GUI, and a very advanced and mature featureset. Like Authelia, KeyCloak can [use an LDAP server](/recipes/keycloak/authenticate-against-openldap/) as a backend, but _unlike_ Authelia, KeyCloak allows for 2-way sync between that LDAP backend, meaning KeyCloak can be used to _create_ and _update_ the LDAP entries (*Authelia's is just a one-way LDAP lookup - you'll need another tool to actually administer your LDAP database*). + + --8<-- "recipe-footer.md"