Introduce stateVersion concept

With upcoming changes to the dovecot home and maildirectories we need to
introduce a way to nudge users to inform themselves about manual
migration steps they might need to carry out.
This commit is contained in:
Martin Weinelt 2025-05-22 02:45:55 +02:00
parent f7a221bc69
commit 4225cc759f
No known key found for this signature in database
GPG Key ID: 87C1E9888F856759
9 changed files with 91 additions and 4 deletions

View File

@ -25,6 +25,20 @@ in
options.mailserver = {
enable = mkEnableOption "nixos-mailserver";
stateVersion = mkOption {
type = types.nullOr types.ints.positive;
default = null;
description = ''
Tracking stateful version changes as an incrementing number.
When a new release comes out we may require manual migration steps to
be completed, before the new version can be put into production.
If your `stateVersion` is too low one or multiple assertions may
trigger to give a hint on what migrations are missing.
'';
};
openFirewall = mkOption {
type = types.bool;
default = true;

View File

@ -64,3 +64,36 @@ To build the documentation, you need to enable `Nix Flakes
$ nix build .#documentation
$ xdg-open result/index.html
Manual migrations
-----------------
We need to take great care around providing a migration story around breaking
changes. If manual intervention becomes necessary we provide the `stateVersion`
option, to notify the user that they need to complete a migration before
they deploy an update.
If that is the case for your change, find the highest `stateVersion` that is
being asserted on in `mail-server/assertions.nix`. Then pick the next number
and add a new assertion, write a good summary what about the issue and what
remediation steps are necessary. Finally reference the URL to the specific
section on the migration page in the documentation.
.. code-block:: nix
{
assertions = [
{
assertion = config.mailserver.stateVersion < 1;
message = "Migration step required: Move files from this location to that location, then bump the `stateVersion` to `1`. Check https://nixos-mailserver.readthedocs.io/en/latest/migrations.html for more details."
}
];
}
The setup guide should always reference the latest `stateVersion`, since we
don't require any migration steps for new setups.
The migration documentation should paint a more complete picture about the steps
that need to be carried out and why this has become necessary. Make sure to
referenc the correct anchor in the URL you put into the assertionn message.

View File

@ -18,6 +18,7 @@ Welcome to NixOS Mailserver's documentation!
faq
release-notes
options
migrations
.. toctree::
:maxdepth: 1

22
docs/migrations.rst Normal file
View File

@ -0,0 +1,22 @@
Migrations
==========
With mailserver configuration best practices changing over time migrations are
a required step to complete before updating to a new version of NixOS
mailserver.
The initial `mailserver.stateVersion` value should be copied from the setup
guide that you used to initially set up your mailserver. If in doubt you can
always initialize it at `1` and walk through all assertions, that might apply
to your setup.
NixOS 25.11
-----------
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;

View File

@ -72,6 +72,7 @@ common ones.
mailserver = {
enable = true;
stateVersion = 1;
fqdn = "mail.example.com";
domains = [ "example.com" ];

View File

@ -1,6 +1,11 @@
{ config, lib, ... }:
{
assertions = lib.optionals config.mailserver.ldap.enable [
assertions = lib.optionals config.mailserver.enable [
{
assertion = config.mailserver.stateVersion != null;
message = "The `mailserver.stateVersion` option is not set. Check https://nixos-mailserver.readthedocs.io/en/latest/migrations.html to determine the proper value to initialize it at.";
}
] ++ lib.optionals config.mailserver.ldap.enable [
{
assertion = config.mailserver.loginAccounts == {};
message = "When the LDAP support is enable (mailserver.ldap.enable = true), it is not possible to define mailserver.loginAccounts";

View File

@ -1,3 +1,8 @@
{
security.dhparams.defaultBitSize = 2048; # minimum size required by dovecot
# Update this to the latest stateVersion when introducing a new migration step
# https://nixos-mailserver.readthedocs.io/en/latest/migrations.html
mailserver.stateVersion = 1;
# minimum size required by dovecot
security.dhparams.defaultBitSize = 2048;
}

View File

@ -18,7 +18,10 @@
name = "minimal";
nodes.machine = {
imports = [ ./../default.nix ];
imports = [
../default.nix
./lib/config.nix
];
};
testScript = ''

View File

@ -16,7 +16,10 @@ let
password = pkgs.writeText "password" "password";
domainGenerator = domain: { pkgs, ... }: {
imports = [../default.nix];
imports = [
../default.nix
./lib/config.nix
];
environment.systemPackages = with pkgs; [ netcat ];
virtualisation.memorySize = 1024;
mailserver = {