Ich hatte in den letzten Wochen - wenig überraschend 😉 - etwas Zeit um mich mit meiner privaten IT-Infrastruktur zu beschäftigen. Die eine Sache die mich da schon seit längerem störte war die Sache mit der Authentifizierung: Die einzelnen Dienste haben sich keine gemeinsame Datenbank für die Authentifizierung geteilt. Diese habe ich für die meisten Services geändert, u.a. Jitsi Meet, Traefik und eben auch dovecot.

Mein bisheriges Setup umfasste eine dovecot-Installation, um Mails abzurufen, und auch als SASL-Backend für den Versand von Mails via Postfix. Ich habe dabei eine PostgreSQL-Datenbank als Backend genutzt und die Passwort-Änderungen in der Webmail-Oberfläche Roundcube via Password Plugin abgehandelt.

Insgesamt hat das gut funktioniert, aber im Laufe der Zeit begann ich damit, immer mehr Dienste selber zu hosten, unter anderem Nextcloud, und irgendwann kam dann halt der Wunsch auf, nur noch ein Login für die ganzen Services zu haben. Jetzt geht das in die andere Richtung relativ einfach, es gibt ein ganze Reihe von Möglichkeiten, gegen externe Datenquellen zu Authentifizieren, und gerade IMAP funktioniert ganz ohne Umstände. Nachdem Nextcloud nun aber selbst auch über ein brauchbare Webmail-Oberfläche verfügt dachte ich mir, ich dreh das einfach um.

Mein Nextcloud-Deployment läuft als Docker-Container (php-fpm-alpine-Image), und in diesem Setup verwendet Nextcloud das Hashing-Verfahren Argon2 zur Speicherung von Passwörtern, welches auch dovecot unterstützt.

Jetzt muss man das ganze also nur noch “zamdübeln”.

Achtung

Das folgende erhebt wie immer keinen Anspruch darauf, eine Anleitung zu sein.

Meine bisherige Konfiguration für dovecat sah folgendermaßen aus:

1
2
3
4
password_query = \
  SELECT password, userdb_quota_rule, \
  '/srv/mail/' || login userdb_home, login AS user FROM users \
  WHERE (login = '%u' OR address = '%u') AND active = true

Das dazu passende Schema enthielt Daten wie diese hier:

1
2
3
4
5
# select * from users;
 id | login |           address    |                                               password                                                |  quota_rule  | active
----+-------+----------------------+-------------------------------------------------------------------------------------------------------+--------------+--------
  1 | user1 | user1@billigmail.org | {SSHA512}VGo5SRldoraau7nqWYfEiXWI/IAVON8PnWkEoicsSGPljOqGqhLh1cQr8f9oHSfGNepE0GMCnpJD+1aAJAUXU+0vwnM= | *:storage=4G | t
  2 | user2 | user2@billigmai.org  | {SSHA512}eVlfbP4Q0py7+Ex7ibGjNcXBEaEYJslMnTfYVW1mFHhfdLy+JWTloXWOseQgYRYKuwl8OK0E4G6q8cMCcoTVSuNu7Oc= | *:storage=8G | t

Ich hatte mir jetzt mehrere Optionen angesehen, um diese Daten via Nextcloud zu managen, u.a. das Verwenden der in Nextcloud hinterlegten eMail-Adresse als address-Feld, was aber doof gewesen wäre, weil es dann schwierig wäre, sein Passwort zu recovern. Was dagegen sinnvoll für mich klang war, einfach die Quotas aus Nextcloud auch nochmal auf IMAP anzuwenden, und so habe ich mich dafür entschieden, die Felder login, address und active auch weiterhin in einer kleinen Tabelle zu pflegen - es ist jetzt nicht so, als hätte ich jeden Tag 100 neue User. Die sauberste Lösung wäre wahrscheinlich eine kleine Nextcloud-App, die diese Daten pro User in den Preferences speichert.

Anyways, den View erstellte ich dann folgendermaßen:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
CREATE VIEW dovecot_view AS SELECT
  ocu.uid_lower AS login,
  du.address,
  CONCAT('{ARGON2I}', SUBSTR(ocu.password, 3)) AS password,
  CASE
    WHEN ocp.configvalue = 'none' OR ocp.configvalue = 'default' THEN '*:storage=8G'
    ELSE CONCAT('*:storage=', SPLIT_PART(ocp.configvalue, ' ', 1), 'G')
  END AS userdb_quota_rule,
  du.active,
FROM oc_users ocu
RIGHT JOIN dovecot_users du ON ocu.uid_lower=du.login
JOIN oc_preferences ocp ON ocu.uid = ocp.userid
WHERE ocp.appid = 'files' and ocp.configkey = 'quota';

Das ganze sieht dann folgendermaßen aus:

1
2
3
4
5
select * from dovecot_view ;
 login |           address    |                                                 password                                                  | userdb_quota_rule | active
-------+----------------------+-----------------------------------------------------------------------------------------------------------+-------------------+--------
 user1 | user1@billigmail.org | {ARGON2I}$argon2i$v=19$m=65536,t=4,p=1$SkxJbjUyT0QTZXJvWTQ2Mg$z6BBNVlipGe/NiEPN454N1QDjEZmi5VVzs7JF+cwwKQ | *:storage=8G      | t
 user2 | user2@billigmail.org | {ARGON2I}$argon2i$v=19$m=65536,t=4,p=1$VkxhZ0ZnQQTEZRJXQ0FDTg$+hnyo2cObw0fZKNVJ0g39365345WtoQuqw0NxI+pq0M | *:storage=5G      | t

Und schon hat man eine Kombination Username/Passwort weniger. Als angenehmen Nebeneffekt konnte ich damit Roundcube abschalten, und da das die letzte Sache war, die auf den Mailserver-VMs noch PHP gebraucht hat, ist das jetzt auch weg.

Wie man vielleicht sieht hat sich hier auch sonst einiges getan: Am auffälligsten ist vermutlich das neu Blog-Theme, aber auch in der Infrastruktur dahinter hat sich viel getan - aber dazu ein andermal mehr.

Bleibt gesund!