Ensure all CHANGEME
and domain.tld
values are changed to match YOUR environment!
Important changes: Traefik 2.x write up has been renamed from the main
branch to traefik2
. Traefik 3.x and Authentik 2024.x now reside on the traefik3
branch, which will be the default branch.
This guide assumes that there is a working Traefik v3.x+ running and that the Traefik network is called traefik. I will also be using the embedded outpost instead of a standalone proxy outpost container.
Additionally, I am NOT allowing Authentik to view the Docker socket (/var/run/docker.sock
) and auto create providers.
If you want to learn more on how to setup Traefik or just some more detailed explanation, visit Anand and Smart Home Beginner at https://www.smarthomebeginner.com/.
My folder / repo structure is weird because this is a condensed version of what I have running. I did not want to leave dead links or bad configurations, so modify to your environment.
Authentik is heavier on resources than Authelia, but it is pretty neat!
Ensure that a DNS record exists for authentik.domain.tld
as the compose and all material here assumes that will be the record name. This is the bare minimum requirement!
I highly recommend Pi-hole https://pi-hole.net/ for your domain!
Records that are used in this example:
traefik.domain.tld
- Traefik 3.x Dashboard authentik.domain.tld
- Authentik WebUI whoami-individual.domain.tld
- WhoAmI using Authentik middleware - Individual Provider whoami-catchall.domain.tld
- WhoAmI using Authentik middleware - Domain Wide Catch Allwhoami.domain.tld
- WhoAmI no authentik middleware The way I have my records in Pi-hole setup, since all of these are containers:
DNS Records | Domain | IP |
---|---|---|
traefik.domain.tld | 192.168.1.26 |
This IP is the host that my containers are running on.
CNAME Records | Domain | Target |
---|---|---|
authentik.domain.tld | traefik.domain.tld | |
whoami-individual.domain.tld | traefik.domain.tld | |
whoami-catchall.domain.tld | traefik.domain.tld | |
whoami.domain.tld | traefik.domain.tld |
Authentik's developer has an initial docker compose setup guide and docker-compose.yml
located at:
[!NOTE]
https://goauthentik.io/docs/installation/docker-compose
https://goauthentik.io/docker-compose.yml
In order for the forwardAuth to make sense, I've modified the provided docker-compose.yml and added the appropriate Traefik labels. I am also using docker secrets in order to protect sensitive information.
[!NOTE]
I am using "fake" docker secrets and binding them into the compose instead of saving sensitive data in environment variables. You can remove the secrets section and work with regular environment variables if that makes more sense for your environment. This is strictly a working example, hopefully with enough documentation to help anyone else that might be stuck.
First create an environment variable file .env
in the same directory as the compose.yaml
with the following information, ensuring to update everywhere that has a CHANGEME to match your environment. If you want, these values can all be manually coded into the compose.yaml
instead of having a separate file.
Check .env for the latest version of the contents below.
I really like how Anand did his compose.yaml
file to be a stack of includes for cleaner organization.
compose.yaml - Defines the base networks, secrets, and other compose files below to include when ran.
The 2 other whoami
containers are inside of the Authentik compose since they are examples, strictly for demonstration and then removed.
The following secrets (defined in the base compose.yaml need to be created)
I recommend you create secrets with the following syntax:
echo -n 'VALUE_CHANGEME' > SECRET_NAME_CHANGEME
Check out Traefik's info at https://doc.traefik.io/traefik/https/acme/#providers. Cloudflare Specific information: https://go-acme.github.io/lego/dns/cloudflare/
cf_email
cf_dns_api_token
echo -n 'CHANGEME@gmail.com' > cf_email
echo -n 'CHANGEME-LONGAPI-CHANGEME' > cf_dns_api_token
Authentik specific (https://docs.goauthentik.io/docs/installation/docker-compose#preparation)
authentik_postgresql_db
authentik_postgresql_user
authentik_postgresql_password
authentik_secret_key
echo -n 'authentik_db' > authentik_postgresql_db
echo -n 'authentik_user' > authentik_postgresql_user
openssl rand 36 | base64 -w 0 > authentik_postgresql_password
openssl rand 60 | base64 -w 0 > authentik_secret_key
Create a gmail account and input the info.
gmail_smtp_username
gmail_smtp_password
echo -n 'CHANGEME@gmail.com' > gmail_smtp_username
echo -n 'CHANGEME' > gmail_smtp_password
Go to https://dev.maxmind.com/geoip/geolite2-free-geolocation-data in order to generate a free license key (https://www.maxmind.com/en/accounts/current/license-key) for use.
geoip_account_id
geoip_license_key
echo -n 'CHANGEME' > geoip_account_id
echo -n 'CHANGEME' > geoip_license_key
I like having Traefik's configuration in a file, it makes more sense to me compared to passing a ton of command arguments in the compose.
When traefik comes up and authenticates with Let's Encrypt a acme.json
will be created at
./appdata/traefik/data/acme.json
I've included several of the rules
I use in my own setup located at
[!NOTE] The one that makes Authentik work is
middlewares-authentik.yaml
ORforwardAuth-authentik.yaml
. They are the exact same thing, but you can decide which name makes more sense to use. In thecompose.yaml
I am usingmiddlewares-authentik
, but to me it makes more sense to useforwardAuth-authentik
so when you are reading the traefik label's you know what it is supposed to do. Your choice.
Traefik is already proxying the connections to the Authentik container/service. Additional middleware rules and an embedded outpost must be configured to enable authentication with Authentik through Traefik, forwardAuth
.
In order to setup forwardAuth
at a minimum, Traefik requires a declaration. Authentik provides an example, but in accordance with the compose.yaml
the values below should make more sense.
The Forward Authentication WILL NOT work unless the middleware is enabled.
[!WARNING]
"Priority based on rule length" Authentik generates the priority for authentication based on rule length (Traefik label). This means if you have a rule (Traefik label) for Authentik to listen on multiple host names withOR, ||
statements, it will have a higher priority than the embedded outpost. Refer to goauthentik/authentik#2180 about setting the priority for the embedded outpost.
Time to start up the stack and begin configuration. Ensure this command is ran from the same directory as compose.yaml
.
docker compose up -d
Because Authentik uses cookies, I recommend using Incognito for each piece of testing, so you don't have to clear cookies every time or when something is setup incorrectly.
[!WARNING]
While using a container behind Authentik, it prompts for authentication, and then flashes but doesn't load. This generally indicates cookies are messing up the loading. So use INCOGNITO.
With Authentik being reverse proxied through Traefik and the middleware showing as enabled in Traefik's dashboard, then configuration of Authentik can begin.
https://authentik.domain.tld/if/flow/initial-setup/
[!NOTE] If this is the first time logging in you will have to set the password for
akadmin
(default user). If establishing the default credentials fails - the setup is not working correctly.
The default user is akadmin
, which is a super user. This initial setup will setup the Super User's email and Password. You will change the username FROM akadmin
to whatever you want.
The first screen you'll see after setting the password and email is:
akadmin
usernameYou can change the username from akadmin
to whatever.
In the Admin Interface
go to
akadmin
I think this is important for anyone that attempts to set this up.
If you attempt to navigate to a page that IS using Authentik's forwardAuth middleware but haven't finished setting up a provider and application (individual or domain wide catch all) then you will see a screen like this:
In the current version, for this documentation 2024.6.0
, Authentik now includes a Wizard to aid with setting up a Application and Provider instead of manually doing it.
I am going to set up my Individual Application
manually and the Domain Wide / Catch All
using the Wizard. ONLY to show how you can do either method, both work!
[!NOTE] I am using the embedded outpost. The embedded outpost requires version
2021.8.1
or newer. This prevents needing the seperate Forward Auth / Proxy Provider container.[!WARNING] Individual applications have a higher priority than the catch all, so you can set up both!
In order for this to "Catch All" you must set a traefik middleware on each service. Look inside the compose.yaml
. This specific snippet is from the whoami-individual
service inside the authentik/compose.yaml
:
Specifically the middlewares-authentik@file"
line.
labels:
- "traefik.enable=true"
## HTTP Routers
- "traefik.http.routers.whoami-individual-rtr.rule=Host(`whoami-individual.${DOMAINNAME}`)"
## Middlewares
- "traefik.http.routers.whoami-individual-rtr.middlewares=middlewares-authentik@file"
Navigate to:
Domain Wide Forward Auth Catch All
domain-wide-forward-auth-catch-all
empty
any
empty
unchecked
Provider for Domain Wide Forward Auth Catch All
empty
default-provider-authorization-explicit-consent (Authorize Application)
https://authentik.domain.tld
domain.tld
hours=24
When all is done, you should have success. If not, carefully review the previous settings. You most likely forgot https://
in front of authentik.domain.tld
Navigate to the Outposts screen and edit the Embedded Outpost:
Notice how the above picture has Providers
empty?
Update the Outpost to have the Domain Wide Forward Auth Catch All
in Selected Applications
BEFORE Adding
AFTER Adding
Now the Embedded Outpost shows the Provider
for the Catch All rule instead of it being empty/blank:
Now that the catch all rule is in place, validate it using the already running whoami-catchall
container created:
Navigate to whoami-catchall.domain.tld
and it will immediately redirect you to Authentik to login:
Sign in with your username or email address initially created. After inputting username & password, it should show you the "Redirecting" screen prior to actual redirection:
The X-Authentik-Meta-App
will contain information about the specific Application used to get here. Notice that this matches the slug
previously created.
X-Authentik-Meta-App: domain-wide-forward-auth-catch-all
Maybe you don't want to use the wizard, though I'm not sure why. So here's how you can do it without the Wizard.
An Application specific Forward Auth configuration will allow different authentication flows to be selected and not disrupt the default domain authentication flow. For example the default domain authentication flow allows a user to authentication with Authentik using username/password only. An application specific could be used for app with additional security ie an OTP, or local networks only, etc.. In most cases the default authentication flow will serve most homelab uses.
As of version 2022.07.03 authentik still requires /outpost.goauthentik.io/
to be routed IF USING INDIVIDUAL APPLICATIONS INSTEAD OF A SINGLE DOMAIN WIDE CATCH-ALL. At the end of July 2022 BeryJu
has an upcoming fix that should remove the below label.
Note: This does not seem to be required on everyone's setup. Individual Application forwardAuth does not work on mine without this label. I recommend you check your setup both with this label.
[!NOTE]
"providers/proxy: no exposed urls #3151" This PR greatly simplifies the Forward auth setup for traefik and envoy. It'll remove the requirement/outpost.goauthentik.io
to be openly accessible, which makes setup easier and decreases attack surface.
This label is applied to the authentik_server
container. Even if you don't use individual applications, keep this label just in case you DO in the future!
labels:
- "traefik.enable=true"
## Individual Application forwardAuth regex (catch any subdomain using individual application forwardAuth)
- "traefik.http.routers.authentik-output-rtr.rule=HostRegexp(`{subdomain:[a-z0-9-]+}.${DOMAINNAME}`) && PathPrefix(`/outpost.goauthentik.io/`)"
In the Admin Interface, go to:
Select Proxy Provider
Use the following settings:
whoami-individual provider
empty
default-provider-authorization-explicit-consent (Authorize Application)
Forward auth (single application)
https://whoami-individual.domain.tld
hours=24
After hitting Finish it will show that it's not bound to an Application:
In the Admin Interface, go to:
whoami-individual application
whoami-individual-application
empty
whoami-individual provider
empty
any
https://whoami-individual.domain.tld
After hitting Create it will show that it is now bound to the previously created provider:
Navigate to the Outposts screen and edit the Embedded Outpost:
Highlight any application you want the outpost to be able to provide for. In this case Highlight whoami-individual application
BEFORE HIGHLIGHT
Notice that BEFORE highlighting and adding to Selected Applications, it still has only the Domain Wide Forward Auth Catch All
rule in Selected Applications:
AFTER HIGHLIGHT
This will include both the domain wide (catch all) and the individual application bound to this outpost.
After hitting Update the Outpost page will show that the embedded outpost now has both providers bound to it:
Now that the individual application rule is in place, validate it using the already running whoami-individual
container created:
Navigate to whoami-individual.domain.tld
and it will immediately redirect you to Authentik to login:
Sign in with your username or email address initially created. After inputting username & password, it should show you the "Redirecting" screen prior to actual redirection:
The X-Authentik-Meta-App
will contain information about the specific Application used to get here. Notice that this matches the slug
previously created.
X-Authentik-Meta-App: whoami-individual-application
Inside the Admin Interface do the following steps to create an additional user:
Fill in the required information:
Inside the Admin Interface do the following steps to add a user to the Admins
group:
authentik Admins
Next, add an existing user to the Users tab:
Add the user
Inside the Admin Interface do the following:
Read this section before just doing it!
https://docs.goauthentik.io/docs/flow/stages/authenticator_webauthn/#authenticator-attachment
[!WARNING]
To prevent locking yourself out and having to start over by deleting your postgres database, create a backup administrator (as done above) or work on a non-administrator account.[!NOTE]
If you are unable to perform the below steps, skip to the Force Authentication section below.
Recommended to Switch to standard browser / NOT Incognito.
IF you are in the Admin Interface
navigate to the User Interface
via the button at the top left:
Navigate to the MFA Devices
screen:
During setup process, depending on your WebAuthn settings you might get prompted for a PIN:
If you are unsure about this, then review the following Yubikey documentation / explanation (https://support.yubico.com/hc/en-us/articles/4402836718866-Understanding-YubiKey-PINs)
If you are being prompted for a PIN (including setting one up), and you're not sure which PIN it is, most likely it is your YubiKey's FIDO2 PIN.
Now complete the WebAuthn Setup:
Hit next and you'll see that you are about to setup your key:
[!CAUTION]
By performing the setup like this, it asks to create a credential on the Yubikey device itself. If you want to make it where it does NOT create the credential itself skip setup for now and go to theModify WebAuthn Credential Creation Location
section where I will show how to change the save credential to key option. After changing that option, you can revisit setup.
STOP - Read the Above Caution Statement before continuing!
If you're ok with creating the credential on your key, continue!
In order to modify the default settings to prevent saving a credential on the Yubikey itself perform the following steps.
default-authenticator-webauthn-setup
Review the default settings:
Edit the Resident key requirement
Preferred: The authenticator can create and store a dedicated credential, but if it doesn't that's alright too
Unfortunately, if I try to skip the dedicated credential, I am unable to setup a Yubikey. I am going to set this option to:
Discouraged: The authenticator should not create a dedicated credential
User verification
depending on your WebAuthn expertise.I am leaving it default:
Preferred: User verification is preferred if available, but not required
Authentik by default has no preference set for the Authenticator, as shown in the above picture. This can be changed to be explicitly Yubikey
OR Windows Hello/TouchID
. If you do not want to be prompted by Windows Hello, as shown in the Windows Hello section, then set this to A "roaming" authenticator, like a YubiKey
.
If you chose to NOT save your key on the Yubikey like above, then scroll back up to continue the registration / finish it.
During Security Key enrollment, if you are interrupted by Windows Hello shown here:
Press ESC
to continue to actual Yubikey enrollment. This only seems to happen if you have previously setup Windows Hello.
[!NOTE]
If you are prompted for a PIN that you do not know, go to theEnrollment with Credential on Key
section for the Yubikey documentation link to address the PIN. Optionally, you can also Force it to skip Windows Hello and go straight to the Yubikey by modifying thedefault-authenticator-webauthn-setup
, as seen in the(Optional) Authenticator preference
section above.
To configure an authentication a user must be in the state that forces them to add an authentication. In order to do this, I am going to modify the default flow for authentication regarding MFA devices.
default-authentication-mfa-validation
The initial settings for the default-authentication-mfa-validation
stage look like this:
Change the Device Classes
to what options you want you or other users to have (by default). I am only going to REMOVE static tokens.
Modify the Not configured action
to Force the user to configure an authenticator
:
Continue
Force the user to configure an authenticator
After setting the Not configured action
to Force the user to configure an authenticator
it will unlock the Configuration stages
options as seen above.
This section, as it says right below it
Stages used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again.
When multiple stages are selected, the user can choose which one they want to enroll.
- Select:
default-authenticator-totp-setup (TOP Authenticator Setup Stage)
- Select:
default-authenticator-webauthn-setup (WebAuthn Authenticator Setup Stage)
In order to highlight multiple, use the Shift
key.
Hit Update
Open another INCOGNITO browser and navigate back to the whoami-individual
URL or authentik
's URL and sign in.
After entering the username/password a new window pop-up asks to select an authenticator method -- choose default-authenticator-webauthn-setup
. The following steps should match the Yubikey section above.
This will only give you this option if you did not previously register your Yubikey inside of the MFA devices.
View the Default Flows by going to the Admin Interface
authentik-default
Expand down Default flows
Notice that the DEFAULT Authentication flow is default-authentication-flow (Welcome to authentik!)
Navigate to:
In order to view the default default-authentication-flow
.
Why does this matter? To understand the way YOU have this identity tool setup.
graph LR
A[Start] --> B[Authentication];
B --> C[Authorization];
C --> D[Login];
By default the flow for all authentication, default-authentication-flow
, is as follows:
graph LR
A[Start] --> B[Username];
B --> C[Password];
C --> D{MFA Configured?};
D -->|No| F[Login];
D -->|Yes| E[MFA Prompt<br>Forced];
E --> F;
There are two policies for authorization, explicit, default-provider-authorization-explicit-consent
, and implicit, default-provider-authorization-implicit-consent
. By default the explicit policy is used.
Explicit, default-provider-authorization-explicit-consent
, requires a pop-up showing that you accept your information is about to be shared with the site. This could be your email, username or whatever you have setup.
graph LR
A[Start] --> B[Consent];
B --> C[Continue];
Implicit, default-provider-authorization-implicit-consent
, means that by logging in you accept your information (email or username, etc.) will be shared with the site, do not prompt, just continue through.
graph LR
A[Start] --> B[Continue];