# Migrating users from LDAP to Authentik

Link: [https://blog.cubieserver.de/2022/migrating-users-from-ldap-to-authentik/](https://blog.cubieserver.de/2022/migrating-users-from-ldap-to-authentik/)

<header id="bkmrk-posted-on%C2%A0feb-2%2C-202"><div class="post-meta clearfix"><div class="post-date pull-left">Posted on <time datetime="2022-02-02T00:00:00Z">Feb 2, 2022</time></div><div class="pull-right"><span class="post-tag small">[\#ldap](https://blog.cubieserver.de/tags/ldap/)</span> <span class="post-tag small">[\#authentik](https://blog.cubieserver.de/tags/authentik/)</span> <span class="post-tag small">[\#authz](https://blog.cubieserver.de/tags/authz/)</span></div></div></header><section id="bkmrk-for-several-years-%28t">For several years (*the earliest timestamp I could find is from 2016*), I have been using [OpenLDAP](https://www.openldap.org/) (a.k.a [slapd](https://www.openldap.org/software/man.cgi?query=slapd)) as the source of truth for user accounts in my homelab. The initial setup was tricky – especially figuring out the “memberOf” overlay to get group memberships – but once I had it nailed down and [put it into Puppet manifests](https://git.cubieserver.de/Cubieserver/puppet-control/src/branch/master/site/profile/manifests/openldap.pp), it was rock solid. The setup is still rock solid, but definitely starts showing its age: friendly user-interfaces for self-service are rare (I’ve been using [LTB’s *Self Service Password*](https://github.com/ltb-project/self-service-password), but it only allows users to change their password, not email address etc.), and modern features like multi-factor authentication need to be re-implemented by each application, instead of being centrally managed by the authentication source.

Thus, in 2022 it was time to look for something new. There are lots of choices available in this space, but [Authentik](https://goauthentik.io/) in particular struck me as simple to set up and use. For this reason it seems that in recent months Authentik has become a bit of a “secret tip” in self-hosting circles.

Despite the small number of users of my homelab, I was reluctant to start from scratch with my authentication source. I was looking for a way to automatically import the user accounts from OpenLDAP into Authentik – and it turns out that Authentik makes this super easy, if you know what to look for. The following guide shows how to set up and use an *LDAP Source* in Authentik, and that it can simply be removed again without deleting the user accounts, thereby acting as an import functionality.

## [\# ](https://blog.cubieserver.de/2022/migrating-users-from-ldap-to-authentik/#setup) Setup

My (old) setup consists of an OpenLDAP server (`slapd 2.4.47` on Debian 10 Buster) with TLS encryption (i.e. `ldaps` instead of StartTLS).

Authentik is version `2021.12.5` and installed with their official Helm chart `5.2.1`:

<div class="highlight"><div><table><tbody><tr><td>```
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21

```

</td><td>```yaml
authentik:
  secret_key: "ThisIsNotASecretKey"
  error_reporting:
    enabled: false
  postgresql:
    password: "ThisIsNotASecurePassword"

ingress:
  enabled: true
  hosts:
    - host: auth.example.com
      paths:
        - path: "/"
          pathType: Prefix


postgresql:
  enabled: true
  postgresqlPassword: "ThisIsNotASecurePassword"
redis:
  enabled: true

```

</td></tr></tbody></table>

</div></div>After adding the Helm repository , run `helm install authentik authentik/authentik` and then open `https://auth.example.com/if/flow/initial-setup/` to set a password for the admin user.

## [\# ](https://blog.cubieserver.de/2022/migrating-users-from-ldap-to-authentik/#syncing-with-openldap) Syncing with OpenLDAP

After logging in as the admin user, you should be greeted with the following dashboard. Navigate to the “Directory” section in the left sidebar and choose “Federation &amp; Social Login”. Then, click the blue “Create” button and select “LDAP Source”.

<figure><figcaption>Authentik Dashboard Overview

</figcaption>[![Authentik Dashboard Overview](https://blog.cubieserver.de/2022/migrating-users-from-ldap-to-authentik/authentik-default-dashboard.png)](https://blog.cubieserver.de/2022/migrating-users-from-ldap-to-authentik/authentik-default-dashboard.png)</figure>Give your LDAP Source a human-friendly *name* and a unique identifier (*slug*). Then, scroll down to the *Connection settings* section.

Here is the full configuration I used. Below you will find detailed explanations for each field.

<figure><figcaption>Authentik LDAP Source configuration

</figcaption>[![Authentik LDAP Source configuration](https://blog.cubieserver.de/2022/migrating-users-from-ldap-to-authentik/ldap-source.png)](https://blog.cubieserver.de/2022/migrating-users-from-ldap-to-authentik/ldap-source.png)</figure>For the *Server URI* you can either use `ldap://1.2.3.4` or `ldap://example.com` if your server is un-encrypted *OR* uses StartTLS (in this case tick the checkbox below), or `ldaps://example.com` if your [server uses regular TLS encryption](https://blog.cubieserver.de/2019/openldap-implementation-specific-error-80-when-adding-tls-certificate/). Optionally, you can specify a port if your server uses a non-default port (add `:386` for regular connections or `:686` for TLS-encrypted connections at the end).

If your server uses the encrypted LDAP protocol and does not use a publicly trusted (*self-signed*) TLS certificate, then you first need to import this certificate into Authentik and then select it in *TLS Verification Certificate*. Otherwise, you can leave this field empty.

Enter the *CN* and *Password* of a user account that can [bind to the LDAP server](https://ldap.com/the-ldap-bind-operation/).

Enter the *Base DN* for your LDAP directory – this can be used to only import part of your user tree.

Next, we configure the *LDAP Attribute Mapping* section. To do this correctly, you should first take a look at your LDAP schema to figure out which attributes are present for your users and groups.

If your are running OpenLDAP (like me), one excellent way to do this is simply dumping the entire LDAP database with [slapcat](https://manpages.debian.org/buster/slapd/slapd.8.en.html):

```
slapcat -b "$BASE_DN"

...
dn: cn=Git,ou=Groups,dc=cubieserver,dc=de
cn: Git
objectClass: groupOfNames
objectClass: top
owner: cn=admin,dc=cubieserver,dc=de
structuralObjectClass: groupOfNames
entryUUID: 55e6b8f6-7370-1035-8c1d-b5b0eb6b5c72
creatorsName: cn=admin,dc=cubieserver,dc=de
createTimestamp: 20160229203955Z
member: cn=Mr Cubie,ou=People,dc=cubieserver,dc=de
modifiersName: cn=admin,dc=cubieserver,dc=de
modifyTimestamp: 20170506200330Z

...
dn: cn=Mr Cubie,ou=People,dc=cubieserver,dc=de
objectClass: posixAccount
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
uid: cubie
cn: Mr Cubie
structuralObjectClass: inetOrgPerson
entryUUID: f05f8080-7752-1035-8092-8fc71d8bef3a
creatorsName: cn=admin,dc=cubieserver,dc=de
createTimestamp: 20160305191934Z
mail: cubie@example.com
memberOf: cn=Git,ou=Groups,dc=cubieserver,dc=de
userPassword:: XXXXXXXXXXXXXXXXXXXXXXXXXXXFpHSmg=
modifiersName: cn=admin,dc=cubieserver,dc=de
modifyTimestamp: 20190723062033Z

```

In the example above I have included one user and one group of my schema. Among all the noise, there are a couple of important fields to note here:

- users have `cn`, `uid` and `mail` attributes ⟶ select these fields in *User Property Mappings*.
- groups have just the `cn` attribute ⟶ select this field in *Group Property Mappings*.
- groups have `objectClass: groupOfNames` ⟶ use *Group object filter* `(objectClass=groupOfNames)`.
- users have `objectClass: posixAccount` ⟶ use *User object filter* `(objectClass=posixAccount)`.
- group membership is indicated by the `member` attribute ⟶ use *Group membership field* `member`.
- users are uniquely identified by the `uid` attribute, but groups don’t have that. However, both have the `cn` (*Common Name*) attribute ⟶ use as the *Object uniqueness field*.

Finally, after you filled in all those fields, click the blue *Create* button at the bottom.

Choose the newly created authentication source and click the blue *Run Sync* button. Depending on the size of your LDAP database, this might take a while (in my case it’s pretty insignificant). Authentik will helpfully display the number of synced users, groups and group memberships. If there are any errors, it will also report them here. In that case, you need to go back to edit your LDAP source and fiddle with the attributes and mappings.

<figure><figcaption>Successful LDAP Synchronization

</figcaption>[![Successful LDAP Synchronization](https://blog.cubieserver.de/2022/migrating-users-from-ldap-to-authentik/successful-sync.png)](https://blog.cubieserver.de/2022/migrating-users-from-ldap-to-authentik/successful-sync.png)</figure>After a successful synchronization, you should see the users and groups by clicking on *Users* under *Directory* in the left sidebar. Here you should check that the user attributes have been imported fully and mapped correctly.

<figure><figcaption>Users after import into Authentik

</figcaption>[![Users after import into Authentik](https://blog.cubieserver.de/2022/migrating-users-from-ldap-to-authentik/imported-users.png)](https://blog.cubieserver.de/2022/migrating-users-from-ldap-to-authentik/imported-users.png)</figure>## [\# ](https://blog.cubieserver.de/2022/migrating-users-from-ldap-to-authentik/#removing-the-sync) Removing the Sync

After you verified all users, groups and membership have been imported correctly, you can return to the *Federation &amp; Social Login* and simply remove the LDAP Source created previously.

*Yes, that’s it.* I’m not sure if its a feature or a bug (because the first time I did this I was expecting all the LDAP users to be deleted from the database again, since the process is called *Synchronization* and not *Import* or *Migration*), but I’m really happy about this behavior. Now I can simply turn off my OpenLDAP server after 6 years of service – it has served me well and I hope Authentik will serve me just as long.

</section><footer id="bkmrk-author%3A-%C2%A0%C2%A0jack-hensc"><section class="author-info"><div class="author-container"><div class="avatar author-avatar">![Author Avatar](https://blog.cubieserver.de/images/wheel.jpg)</div><div class="name">Author: [<span class="author-name text-primary">Jack Henschel</span>](https://blog.cubieserver.de/)</div><div class="contact">[ Contact me](mailto:jack.henschel@mailbox.org)</div><div class="bio">Cloud computing engineer, IT security specialist, avid cyclist.</div></div></section></footer>