How to configure Authentik IdP with docker compose

In this post we will do an initial setup of Authentik IdP (Identity Provider), an excellent piece of software that provides user identification. On top of being an IdP, it also allows us to use it for SSO purposes, which we will utilise to grant access to our users to internal resources. It can also be used to grant access to external resources, but this will not be covered in this post (it also requires us to open the instance to the Internet, so that would be something that you would have to think carefully before doing it).

To start, we will create a docker-compose file that should look something like this:

---
version: '3.4'

services:
  demoauth-db:
    container_name: demoauth-db
    image: docker.io/library/postgres:12
    dns:
      - $DNS_SERVER
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
      start_period: 20s
      interval: 30s
      retries: 5
      timeout: 5s
    volumes:
      - ${AUTHENTIK_PATH}/database:/var/lib/postgresql/data
    environment:
      - TZ=$TIMEZONE
      - POSTGRES_PASSWORD=$PG_PASSWORD
      - POSTGRES_USER=$PG_USER
      - POSTGRES_DB=$PG_DB
    env_file:
      - .env
    networks:
      all-net:

  demoauth-redis:
    image: docker.io/library/redis:alpine
    container_name: demoauth-redis
    dns:
      - $DNS_SERVER
    command: --save 60 1 --loglevel warning
    healthcheck:
      test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
      start_period: 20s
      interval: 30s
      retries: 5
      timeout: 3s
    volumes:
      - ${AUTHENTIK_PATH}/redis:/data
    networks:
      all-net:

  demoauth-app:
    image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-${AUTHENTIK_VERSION}}
    container_name: demoauth-app
    dns:
      - $DNS_SERVER
    command: server
    environment:
      TZ: "$TIMEZONE"
      AUTHENTIK_REDIS__HOST: demoauth-redis
      AUTHENTIK_POSTGRESQL__HOST: demoauth-db
      AUTHENTIK_POSTGRESQL__USER: $PG_USER
      AUTHENTIK_POSTGRESQL__NAME: $PG_DB
      AUTHENTIK_POSTGRESQL__PASSWORD: $PG_PASSWORD
    volumes:
      - ${AUTHENTIK_PATH}/media:/media
      - ${AUTHENTIK_PATH}/custom-templates:/templates
    env_file:
      - .env
    labels:
      - traefik.enable=true
      - traefik.http.services.authentik.loadbalancer.server.port=9000
      - traefik.http.routers.authentik.rule=Host(`idp.demo.networktechguy.com`)
      - traefik.http.routers.authentik.tls.certresolver=leextdns
      - traefik.http.routers.authentik.entrypoints=websecure
    networks:
      ext-net:
      all-net:

  demoauth-worker:
    image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-${AUTHENTIK_VERSION}}
    container_name: demoauth-worker
    dns:
      - $DNS_SERVER
    command: worker
    environment:
      TZ: "$TIMEZONE"
      AUTHENTIK_REDIS__HOST: demoauth-redis
      AUTHENTIK_POSTGRESQL__HOST: demoauth-db
      AUTHENTIK_POSTGRESQL__USER: $PG_USER
      AUTHENTIK_POSTGRESQL__NAME: $PG_DB
      AUTHENTIK_POSTGRESQL__PASSWORD: $PG_PASSWORD
    user: root
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ${AUTHENTIK_PATH}/media:/media
      - ${AUTHENTIK_PATH}/certs:/certs
      - ${AUTHENTIK_PATH}/custom-templates:/templates
    env_file:
      - .env
    networks:
      ext-net:
      all-net:

networks:
  ext-net:
    external: true
  all-net:
    external: true

I've covered a structure of a docker-compose file here, so we will not be going through all the details in this post.

A few things to note:

  • I am using system variables, they should be self-explanatory
  • original docker-compose file can be found here, or downloaded to your Linux system by using wget https://goauthentik.io/docker-compose.yml
  • I am using $DNS_SERVER variable to force the container to use a different DNS server from what my docker host is using
  • I am also using two docker networks, previously defined, named ext-net and all-net; this is not mandatory, I just like to separate containers in different networks

With that out of the way, my .env file looks like this:

# System variables
TIMEZONE=America/Toronto
DNS_SERVER=IP_ADDRESS
AUTHENTIK_PATH=PATH_TO_WHERE_AUTHENTIK_IS

# Database variables
PG_PASSWORD=POSTGRESS_PASSWORD
PG_USER=authentik
PG_DB=demoauth-db


# Authentik variables
AUTHENTIK_VERSION=2024.2.2
AUTHENTIK_SECRET_KEY=SECRET_KEY
AUTHENTIK_ERROR_REPORTING__ENABLED=true
AUTHENTIK_PORT_HTTP=9090
AUTHENTIK_PORT_HTTPS=9443

# SMTP Settings
AUTHENTIK_EMAIL__HOST=IP_ADDRESS
AUTHENTIK_EMAIL__PORT=25
AUTHENTIK_EMAIL__TIMEOUT=10
[email protected]

# DISALLOW User info change
AUTHENTIK_DEFAULT_USER_CHANGE_USERNAME=false
AUTHENTIK_DEFAULT_USER_CHANGE_NAME=false

Please note that you have to replace variables with your own values.

Once everything is in place, you can start your docker-compose file by running docker compose up -d in the directory where your docker-compose.yml file is.

Give it a minute or two for traefik to pick up the container and get the SSL certificate and you should be good to go.

Next, open https://FQDN/if/flow/initial-setup/, in my case that will look like this:

Authentik initial setup dialogue

Fill out the dialogue with your own values and this will then associate your email address and password with admin user called akadmin.

You should be greeted with the following screen when you click on Continue:

Authentik User Interface

Notice that this is a user interface; if you want to administer the system, you need to click on Admin interface button in the top right part of the screen.

Once there, you will be presented with a new screen:

Authentik Admin Interface

From here, we can administer the system and finally use it for something! First things first though. Even though Authentik allows you to import users from another source (such as Active Directory, LDAP, Azure AD - or Entra ID, Facebook, etc.) we will actually use Authentik itself to administer our users.

So, let's create our first user. Click on Directory followed by Users. We will create our first user in the system:

Creating users in Authentik

Click on the Create button in the top middle of the screen and enter all the necessary parameters. Mine looks like this:

Authentik User Creation

You may have noticed that user doesn't have a password field. That is because it is intended for users to set their own password when they login. But to do that, we would have to first modify our flows to allow it, so we will set a password for the user from Admin console. Click on the user and you should be presented with the following screen:

Authentik User Details

You will also notice that I already have a failed login - that is because I immediately tried logging in as this user in an incognito window, but since there is no flow for users to set their passwords, I just got a failed login. So let's resolve this. Click on Set password button on the bottom left side of the screen and you will then be able to set a password for the user:

User Password Update

Once this is done, you should be able to log into the system as a new user:

User Interface

You will also notice that there is no Admin interface button on this screen. That is because user nenad in this case is not part of the superuser group. In my production instance, and in general, I like to have at least two admin users - one, in this case akadmin is the default admin user that comes with the system, and the other one will be nenad once we grant admin privileges to the user. The reason for this is simple - I like to have a default admin user set on a side with a strong password that I don't use on a daily basis. This way, I can have that user in case I mess up the system, a fail-safe if you will. Also, this allows me to have a user that doesn't necessarily have MFA enabled on it, in case I mess that up too. I am definitely not advocating for this approach, especially for systems that are open to the Internet! For those systems, MFA is a must!

So let's go back and login into the system as akadmin and grant superuser privileges to our newly created user. To do that, go back to Directory -> Users -> Groups and click the Add to existing group button:

Add a User to a Group Menu

Click on the + sign and then you should be presented with the following screen:

Adding Groups to a User Menu

Select authentik Admins:

Adding Groups to a User Warning

Notice that when you select authentik Admins group, a warning pops up. This is expected, as you are intentionally granting superuser privileges to the user. Click on Add twice and you should have a new screen under Overview tab that says that you are now a superuser:

User with superuser privileges

And that is it - from this point forward, when you login into the system with your user, you should have the same privileges as akadmin user:

At this point we have a fully functional Authentik instance and in the following posts we will start utilising our new IdP to grant access to our apps, systems and services.