.. SPDX-License-Identifier: GPL-3.0-or-later .. SPDX-FileCopyrightText: Martin Weinelt .. SPDX-FileCopyrightText: Emily Lange .. SPDX-FileCopyrightText: The NixOS Mailserver contributors Migrations ========== With mail server configuration best practices changing over time we might need to make changes that require you to complete manual migration steps before you can deploy a new version of NixOS mailserver. The initial :option:`mailserver.stateVersion` value should be copied from the setup guide that you used to initially set up your mail server. If in doubt you can always initialize it at ``1`` and walk through all assertions, that might apply to your setup. NixOS 26.05 ----------- .. _migration-5: #5 Sieve script directory migration ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Sieve scripts managed by users via ManageSieve were previously stored in ``/var/sieve`` (or via the now-removed option ``mailserver.sieveDirectory``). This setup partially mirrored the mail directory structure in ``/var/vmail`` (``mailserver.storage.path``), which proved to be fragile and error-prone. Thanks to a `prior migration`_, we can now migrate these directories into each user’s home directory, aligning with upstream recommendations — almost nine years later. .. _prior migration: #dovecot-mail-directory-migration This migration is only required if you have :option:`mailserver.enableManageSieve` enabled. 1. If you are coming from ``25.11`` and are using LDAP, temporarily disable :option:`mailserver.enableManageSieve` by setting it to ``false``, deploy, and only then continue with this migration. If you are not coming from ``25.11`` or are not using LDAP, continue with this migration as is. 2. Copy the migration script to your mailserver and make it executable: .. code-block:: console cd /tmp wcurl https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/raw/main/migrations/nixos-mailserver-migration-05.py chmod +x nixos-mailserver-migration-05.py 3. Stop the ``postfix.service``. .. code-block:: bash systemctl stop postfix.service 4. Create a backup or snapshot of your ``mailserver.sieveDirectory``, so you can restore should anything go wrong. 5. Run the migration script and pass your ``mailserver.sieveDirectory`` as argument: The script should be run under the user who owns the ``mailserver.sieveDirectory``. If run as root it will automatically switch into the appropriate user by itself. The script will not modify your data unless called with ``--execute``. The migration script finds all Sieve script directories in ``/var/sieve/`` (or any other ``mailserver.sieveDirectory``), for example that of ``bob`` at ``/var/vmail/bob@example.com``. It then takes ``bob@example.com`` and looks up the home directory for ``bob``. Finally, it starts suggesting the necessary move operations to migrate the Sieve directory to ``/var/vmail/example.com/bob/sieve`` and symlinks the active script to ``/var/vmail/example.com/bob/.dovecot.sieve``. Example: .. code-block:: bash ./nixos-mailserver-migration-05.py \ /var/sieve 6. Review the script output. The script can highlight various inconsistencies and problems, that should be reviewed and acted upon. If in doubt, join our community chat for help before applying any changes. 7. Rerun the command with ``--execute`` or run the proposed commands manually. 8. Update the ``mailserver.stateVersion`` to ``5``. 9. The previous Sieve directory (``mailserver.sieveDirectory``) should now be safe to delete. 10. If you temporarily disabled :option:`mailserver.enableManageSieve` in step 1, re-enable it now by setting it back to ``true``. .. _migration-4: #4 Dovecot LDAP UUID-based home directories ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LDAP Support in NixOS mailserver was introduced during the 23.11 release cycle and came with a number of flaws that we are correcting now, three years later. This particular migration is needed because up until now we were relying on email addresses to construct the Dovecot home directory path (``var/vmail/ldap/user@example.com``) which is fragile: addresses can change, requiring manual homedir relocation. Switching to UUID-based homedirs (``/var/vmail/ldap/``) ensures stable, unique paths and applies well-known best practices to mailserver management. This migration is only required if you have :option:`mailserver.ldap.enable` enabled. 1. Copy the migration script to your mailserver and make it executable: .. code-block:: console cd /tmp wcurl https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/raw/main/migrations/nixos-mailserver-migration-04.py chmod +x nixos-mailserver-migration-04.py 2. Stop the ``dovecot.service``. .. code-block:: bash systemctl stop dovecot.service 3. Create a backup or snapshot of your :option:`mailserver.storage.path`, so you can restore should anything go wrong. 4. Run the migration script and pass the required arguments to enable LDAP lookups: The script should be run under the user who owns the :option:`mailserver.storage.path`. If run as root it will automatically switch into the appropriate user by itself. The script will not modify your data unless called with ``--execute``. The migration script finds all Dovecot home directories in ``/var/vmail/ldap/`` (or any other :option:`mailserver.storage.path`), for example that of bob at ``/var/vmail/ldap/bob@example.com``. It then takes ``bob@example.com`` and queries the LDAP server for ``mail=bob@example.com`` to retrieve the UUID attribute. Finally it starts suggesting the necessary move operations to arrive at ``/var/vmail/ldap/f3b4e8ea-087f-42cc-95f0-cbfd99386092`` for bob. Example: .. code-block:: bash ./nixos-mailserver-migration-04.py \ --ldap-uri ldaps://ldap1.example.com --ldap-bind-dn cn=mail,ou=accounts,dc=example,dc=com \ --ldap-bind-pw-file /run/keys/ldap-bind-pw \ --ldap-base ou=people,ou=accounts,dc=example,dc=com \ --ldap-scope sub \ --ldap-filter "(mail=%s)" \ --ldap-attr-uuid entryUUID \ /var/vmail For the ``--ldap-attr-uuid`` parameter we expect a long-term stable identifier, ideally a UUID field. The exact attribute name depends on your LDAP implementation, for example: - Authentik: ``uid`` `[1]`_ - Kanidm: ``uuid`` `[2]`_ - Keycloak ``entryUUID`` - OpenLDAP: ``entryUUID`` (`RFC4530`_) If your LDAP provider isn't listed you can determine the correct attribute by querying a user entry with ``ldapsearch``. Finally, configure :option:`mailserver.ldap.attributes.uuid` accordingly. Add ``--ldap-starttls`` if you use the the `ldap://` URI scheme and require explicit TLS. .. _[1]: https://docs.goauthentik.io/add-secure-apps/providers/ldap#users .. _[2]: https://kanidm.github.io/kanidm/stable/integrations/ldap.html#data-mapping .. _RFC4530: https://www.rfc-editor.org/rfc/rfc4530.html 5. Review the script output. It's primary job is to determine the UUID for an LDAP account, so that it can rename the Dovecot home directory from mail address to UUID within the same directory. The script can highlight various inconsistencies and problems, that should be reviewed and acted upon. If in doubt, join our community chat for help before applying any changes. 6. Rerun the command with ``--execute`` or run the proposed commands manually. 7. Update the ``mailserver.stateVersion`` to ``4``. NixOS 25.11 ----------- #3 Dovecot mail directory migration ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The way the Dovecot home directory for login accounts were previously set up resulted in shared home directories for all those users. This is not a supported Dovecot configuration. To resolve this we migrated the home directory into the individual `domain/localpart` subdirectory below the `mailserver.mailDirectory`. But since this now overlaps with the location of the Maildir, it must be migrated into the `mail/` directory below the home directory. And while the LDAP home directory is not affected we use this migration to keep the Maildir configurations of LDAP users in sync with those of local accounts. This is a big step forward, since we can now more cleanly colocate other data directories, like sieve in the home directory, which in turn simplifies backups. This migration is required for every configuration. For remediating this issue the following steps are required: 1. Copy the `migration script `_ script to your mailserver and make it executable: .. code-block:: bash wcurl https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/raw/main/migrations/nixos-mailserver-migration-03.py chmod +x nixos-mailserver-migration-03.py 2. Stop the ``dovecot.service``. .. code-block:: bash systemctl stop dovecot.service 3. Create a backup or snapshot of your ``mailserver.mailDirectory``, so you can restore should anything go wrong. 4. Run the migration script under your virtual mail user with the following arguments: - ``--layout default`` unless ``useFSLayout`` is enabled, then ``--layout folder`` - The value of ``mailserver.mailDirectory``, which defaults to ``/var/vmail`` The script should be run under the user who owns the ``mailDirectory``. If run as root it will try to switch into the appropriate user by itself. The script will not modify your data unless called with ``--execute``. Example: .. code-block:: bash ./nixos-mailserver-migration-03.py --layout default /var/vmail 5. Review the commands. They should be - create a ``mail`` directory for each account, - move maildir contents from the parent directory into it, - suggest removal of files that do not belong to the maildir - their removal is not mandatory and the script **will not** remove them when called with ``--execute`` - review these items carefully if you want to remove them yourself - remove obsolete files from the old home directory location 6. Rerun the command with ``--execute`` or run the commands manually. 7. Update the ``mailserver.stateVersion`` to ``3``. #2 Dovecot LDAP home directory migration ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The Dovecot configuration for LDAP home directories previously did not respect the ``mailserver.mailDirectory`` setting. This means that home directories were unconditionally located at ``/var/vmail/ldap/%{user}``. This migration is required if you both: * enabled the LDAP integration (``mailserver.ldap.enable``) * and customized the default mail directory (``mailserver.mailDirectory != "/var/vmail"``) For remediating this issue the following steps are required: 1. Stop ``dovecot.service``. 2. Move ``/var/vmail/ldap`` below your ``mailserver.mailDirectory``. 3. Update the ``mailserver.stateVersion`` to ``2``. #1 Initialization ^^^^^^^^^^^^^^^^^ This option was introduced in the NixOS 25.11 release cycle, in which case you can safely initialize its value at `1`. .. code-block:: nix mailserver.stateVersion = 1;