Design choice of `switch-to-configuration`

The order of activation steps is unlikely to be changed. No particular order is ideal.

The main way to prevent such issues is to move configuration files to /nix/store.

Another one, is to use systemd service with stopIfChanged = true;. It is default btw, but sometimes it is set to false. What happens during activation of a changed service with stopIfChanged = true;? It is stopped with code from old configuration, and started with code from new configuration.

Unfortunately for you, firewall service has reloadIfChanged = true;, which disables the stop logic above. It won’t run stop commands from old configuration, it will only run reload command from new configuration. NB: systemd: Interactions of `restartIfChanged, reloadIfChanged, stopIfChanged` is fragile · Issue #49528 · NixOS/nixpkgs · GitHub

It also runs your extraStopCommands but somewhere in the middle - https://github.com/NixOS/nixpkgs/blob/57a4956bc257c11e1478d16c64e1243305b1385c/nixos/modules/services/networking/firewall.nix#L240-L262 . But because your new configuration doesn’t include extraStopCommands, they won’t be executed.

So easy way to fix that would be override and set systemd.services.firewall.reloadIfChanged = lib.mkForce false;. Then stop commands will be executed on all firewall changes.