diff --git a/flake.lock b/flake.lock index 765bc8b..5fc1bf6 100644 --- a/flake.lock +++ b/flake.lock @@ -10,11 +10,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1745630506, - "narHash": "sha256-bHCFgGeu8XjWlVuaWzi3QONjDW3coZDqSHvnd4l7xus=", + "lastModified": 1762618334, + "narHash": "sha256-wyT7Pl6tMFbFrs8Lk/TlEs81N6L+VSybPfiIgzU8lbQ=", "owner": "ryantm", "repo": "agenix", - "rev": "96e078c646b711aee04b82ba01aefbff87004ded", + "rev": "fcdea223397448d35d9b31f798479227e80183f6", "type": "github" }, "original": { @@ -68,11 +68,11 @@ ] }, "locked": { - "lastModified": 1746695594, - "narHash": "sha256-pAAWYs3S+/tY65vemHZdVSXpeIz4JINEJZoPoBjr8JU=", + "lastModified": 1763651264, + "narHash": "sha256-8vvwZbw0s7YvBMJeyPVpWke6lg6ROgtts5N2/SMCcv4=", "owner": "nix-community", "repo": "disko", - "rev": "6bb82b77ce140137177e30df067759931ab60a73", + "rev": "e86a89079587497174ccab6d0d142a65811a4fd9", "type": "github" }, "original": { @@ -105,11 +105,11 @@ "flake-compat": { "flake": false, "locked": { - "lastModified": 1696426674, - "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "lastModified": 1747046372, + "narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=", "owner": "edolstra", "repo": "flake-compat", - "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885", "type": "github" }, "original": { @@ -121,11 +121,11 @@ "flake-compat_2": { "flake": false, "locked": { - "lastModified": 1696426674, - "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "lastModified": 1761588595, + "narHash": "sha256-XKUZz9zewJNUj46b4AJdiRZJAvSZ0Dqj2BNfXvFlJC4=", "owner": "edolstra", "repo": "flake-compat", - "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "rev": "f387cd2afec9419c8ee37694406ca490c3f34ee5", "type": "github" }, "original": { @@ -152,6 +152,32 @@ "type": "github" } }, + "git-hooks": { + "inputs": { + "flake-compat": [ + "snm", + "flake-compat" + ], + "gitignore": "gitignore_2", + "nixpkgs": [ + "snm", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1763319842, + "narHash": "sha256-YG19IyrTdnVn0l3DvcUYm85u3PaqBt6tI6VvolcuHnA=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "7275fa67fbbb75891c16d9dee7d88e58aea2d761", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "git-hooks.nix", + "type": "github" + } + }, "gitignore": { "inputs": { "nixpkgs": [ @@ -173,6 +199,28 @@ "type": "github" } }, + "gitignore_2": { + "inputs": { + "nixpkgs": [ + "snm", + "git-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, "home-manager": { "inputs": { "nixpkgs": [ @@ -201,11 +249,11 @@ ] }, "locked": { - "lastModified": 1746719124, - "narHash": "sha256-KOL73WIjO00ds1oIe+5HAcGcpd/TfE6dymmmYbiSlYM=", + "lastModified": 1763906693, + "narHash": "sha256-inm7paa3myo8gE4TzjM8OPvsEg8xocWreIZBgBPEKgo=", "owner": "nix-community", "repo": "home-manager", - "rev": "3c59c5132b64e885faca381e713b579dcbddba75", + "rev": "3d6c1c8fa0bea3a1a7ba23d6fa5993116766073b", "type": "github" }, "original": { @@ -286,11 +334,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1746461020, - "narHash": "sha256-7+pG1I9jvxNlmln4YgnlW4o+w0TZX24k688mibiFDUE=", + "lastModified": 1763678758, + "narHash": "sha256-+hBiJ+kG5IoffUOdlANKFflTT5nO3FrrR2CA3178Y5s=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "3730d8a308f94996a9ba7c7138ede69c1b9ac4ae", + "rev": "117cc7f94e8072499b0a7aa4c52084fa4e11cc9b", "type": "github" }, "original": { @@ -300,21 +348,6 @@ "type": "github" } }, - "nixpkgs-24_11": { - "locked": { - "lastModified": 1734083684, - "narHash": "sha256-5fNndbndxSx5d+C/D0p/VF32xDiJCJzyOqorOYW4JEo=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "314e12ba369ccdb9b352a4db26ff419f7c49fa84", - "type": "github" - }, - "original": { - "id": "nixpkgs", - "ref": "nixos-24.11", - "type": "indirect" - } - }, "nixpkgs-docs": { "locked": { "lastModified": 1705957679, @@ -365,17 +398,18 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1732014248, - "narHash": "sha256-y/MEyuJ5oBWrWAic/14LaIr/u5E0wRVzyYsouYY3W6w=", + "lastModified": 1763553727, + "narHash": "sha256-4aRqRkYHplWk0mrtoF5i3Uo73E3niOWiUZU8kmPm9hQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "23e89b7da85c3640bbc2173fe04f4bd114342367", + "rev": "094318ea16502a7a81ce90dd3638697020f030a2", "type": "github" }, "original": { - "id": "nixpkgs", - "ref": "nixos-unstable", - "type": "indirect" + "owner": "NixOS", + "ref": "nixos-unstable-small", + "repo": "nixpkgs", + "type": "github" } }, "nmd": { @@ -441,11 +475,11 @@ ] }, "locked": { - "lastModified": 1746537231, - "narHash": "sha256-Wb2xeSyOsCoTCTj7LOoD6cdKLEROyFAArnYoS+noCWo=", + "lastModified": 1763741496, + "narHash": "sha256-uIRqs/H18YEtMOn1OkbnPH+aNTwXKx+iU3qnxEkVUd0=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "fa466640195d38ec97cf0493d6d6882bc4d14969", + "rev": "20e71a403c5de9ce5bd799031440da9728c1cda1", "type": "github" }, "original": { @@ -488,15 +522,15 @@ "inputs": { "blobs": "blobs", "flake-compat": "flake-compat_2", - "nixpkgs": "nixpkgs_2", - "nixpkgs-24_11": "nixpkgs-24_11" + "git-hooks": "git-hooks", + "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1746637515, - "narHash": "sha256-bUq2uHmsfY3SpJrR4dpncITykufTiD2320JsOKgIYl0=", + "lastModified": 1763564778, + "narHash": "sha256-HSWMOylEaTtVgzIjpTbjcjVLXHDwNyV081eVUBfAcMs=", "owner": "simple-nixos-mailserver", "repo": "nixos-mailserver", - "rev": "a7d2b05a9920d90f5eb8076f449acdb6c1ad79ca", + "rev": "4987d275a90392347f84923cd4cd8efcf0aa7a22", "type": "gitlab" }, "original": { @@ -508,11 +542,11 @@ }, "stable": { "locked": { - "lastModified": 1746557022, - "narHash": "sha256-QkNoyEf6TbaTW5UZYX0OkwIJ/ZMeKSSoOMnSDPQuol0=", + "lastModified": 1751274312, + "narHash": "sha256-/bVBlRpECLVzjV19t5KMdMFWSwKLtb5RyXdjz3LJT+g=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1d3aeb5a193b9ff13f63f4d9cc169fb88129f860", + "rev": "50ab793786d9de88ee30ec4e4c24fb4236fc2674", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 1f9095c..23f2062 100644 --- a/flake.nix +++ b/flake.nix @@ -28,16 +28,6 @@ inputs.nixpkgs.follows = "nixpkgs-droid"; }; - # emacs = { - # url = "github:nix-community/emacs-overlay"; - # inputs.nixpkgs.follows = "nixpkgs"; - # }; - # - # simplex-chat = { - # url = "github:simplex-chat/simplex-chat"; - # inputs.nixpkgs.follows = "nixpkgs"; - # }; - # age for nix to store encrypted passwords conveniently agenix = { url = "github:ryantm/agenix"; @@ -129,6 +119,10 @@ modules = [ ./hosts/igor ]; }; + homeConfigurations."alex@dregil" = home-manager.lib.homeManagerConfiguration { + + }; + nixOnDroidConfigurations.default = with inputs; nix-on-droid.lib.nixOnDroidConfiguration { diff --git a/home/alex/cli.nix b/home/alex/cli.nix index b408b76..b4833b9 100644 --- a/home/alex/cli.nix +++ b/home/alex/cli.nix @@ -186,7 +186,16 @@ in }; }; - ssh.enable = true; + ssh = { + enable = true; + enableDefaultConfig = false; + matchBlocks = { + "*" = { + controlMaster = "auto"; + controlPersist = "10m"; + }; + }; + }; texlive.enable = true; }; diff --git a/home/alex/default.nix b/home/alex/default.nix index 8e99ff4..62ee3b3 100644 --- a/home/alex/default.nix +++ b/home/alex/default.nix @@ -5,9 +5,6 @@ inputs, ... }: -let - electron-overlay = final: prev: { electron = final.electron_25; }; -in { imports = [ ]; diff --git a/home/alex/home.nix b/home/alex/home.nix index 59d08a6..3d8b050 100644 --- a/home/alex/home.nix +++ b/home/alex/home.nix @@ -9,19 +9,19 @@ imports = [ ./cli.nix ./programs/rofi - ./programs/xmonad - #./programs/i3 + # ./programs/xmonad + # ./programs/i3 ./programs/jitsi-meet ./programs/simplex-chat ./programs/zathura ./programs/autorandr - ./services/polybar - ./services/dunst - ./services/udiskie + # ./services/polybar + # ./services/dunst + # ./services/udiskie # ./services/picom - ./services/screen-locker - ./services/blueman-applet - ./services/network-manager + # ./services/screen-locker + # ./services/blueman-applet + # ./services/network-manager ./services/syncthing ./services/git-sync ./modules/email.nix @@ -45,6 +45,7 @@ # social discord # talk to other people google-chrome + signal-desktop # system tools uhk-agent # my keyboard @@ -53,6 +54,8 @@ parallel-disk-usage gdu + gnomeExtensions.paperwm + # gaming support stable.bottles wine64Packages.stagingFull @@ -99,7 +102,7 @@ { enable = true; loginExtra = auth-socket-env; - initExtra = auth-socket-env; + initContent = auth-socket-env; }; }; diff --git a/home/alex/modules/email.nix b/home/alex/modules/email.nix index 95e8a09..71bcbd3 100644 --- a/home/alex/modules/email.nix +++ b/home/alex/modules/email.nix @@ -35,6 +35,9 @@ in enable = true; hooks.preNew = "mbsync --all"; }; + programs.mu = { + enable = true; + }; accounts.email = { accounts.failco = mkAccount "me@failco.de" // { diff --git a/home/alex/programs/emacs/default.nix b/home/alex/programs/emacs/default.nix index 1707339..d94091f 100644 --- a/home/alex/programs/emacs/default.nix +++ b/home/alex/programs/emacs/default.nix @@ -23,9 +23,4 @@ in defaultEditor = true; startWithUserSession = true; }; - - xdg.configFile.doom = { - target = "doom"; - source = ./doom; - }; } diff --git a/home/alex/programs/emacs/doom/config.el b/home/alex/programs/emacs/doom/config.el index c5ee5c8..39c5a5e 100644 --- a/home/alex/programs/emacs/doom/config.el +++ b/home/alex/programs/emacs/doom/config.el @@ -321,6 +321,18 @@ (("C-c n d" . #'denote-open-or-create-with-command)) ) +(use-package! denote-org + :after denote) + +(use-package! denote-journal + :after denote) + +(use-package! denote-menu + :after denote) + +(use-package! denote-sequence + :after denote) + (use-package! org-super-agenda :after org-agenda :init @@ -375,7 +387,7 @@ :after denote) (use-package! cov) -(use-package! casual-suite) + ;(use-package! casual-suite) (map! :desc "Move workspace to the left" :leader :n "TAB <" #'+workspace/swap-left) (map! :desc "Move workspace to the left" :leader :n "TAB >" #'+workspace/swap-right) diff --git a/home/alex/programs/emacs/doom/init.el b/home/alex/programs/emacs/doom/init.el index a42d272..c76a1cf 100644 --- a/home/alex/programs/emacs/doom/init.el +++ b/home/alex/programs/emacs/doom/init.el @@ -177,8 +177,8 @@ (zig +lsp +tree-sitter) ; C, but simpler :email - ;; (mu4e +org +gmail) - (notmuch +org +afew) + (mu4e +org +gmail +mbsync) + ;; (notmuch +org +afew) ;;(wanderlust +gmail) :app diff --git a/home/alex/programs/emacs/doom/packages.el b/home/alex/programs/emacs/doom/packages.el index c1ac1df..3589576 100644 --- a/home/alex/programs/emacs/doom/packages.el +++ b/home/alex/programs/emacs/doom/packages.el @@ -53,8 +53,10 @@ ;; :recipe (:host github :repo "username/repo" ;; :files ("some-file.el" "src/lisp/*.el"))) -(unpin! compat) - ;(unpin! with-editor ghub) +;;(unpin! compat) +;;(unpin! with-editor ghub) + +;;(package! transient :pin "25b994a565ce8035330b0a3071ee430c0282349e") ; 0.8.8 (package! ormolu) (package! org-gtd @@ -68,7 +70,13 @@ (package! emacsql-sqlite3) (package! nov) (package! org-present) + (package! denote) +(package! denote-org) +(package! denote-journal) +(package! denote-menu) +(package! denote-sequence) + (package! org-super-agenda) (package! org-modern) (package! org-ql) diff --git a/home/alex/programs/git/default.nix b/home/alex/programs/git/default.nix index 1551ded..070984a 100644 --- a/home/alex/programs/git/default.nix +++ b/home/alex/programs/git/default.nix @@ -1,4 +1,9 @@ -{ config, lib, pkgs, ... }: +{ + config, + lib, + pkgs, + ... +}: { programs.git = { @@ -17,48 +22,62 @@ key = "41A6D13FECA21280"; signByDefault = false; }; - delta = { enable = true; }; - # TODO create option for my own account meta data - userEmail = "me@failco.de"; - userName = "Alexander Kobjolke"; - extraConfig = { - pull = { rebase = true; }; - merge = { conflictstyle = "diff3"; }; - submodule = { recurse = true; }; - }; + settings = { + pull = { + rebase = true; + }; + merge = { + conflictstyle = "diff3"; + }; + submodule = { + recurse = true; + }; + user = { + # TODO create option for my own account meta data + email = "me@failco.de"; + name = "Alexander Kobjolke"; + }; + alias = { + a = "add"; + c = "commit"; + ca = "commit --amend"; + can = "commit --amend --no-edit"; + cl = "clone"; + cm = "commit -m"; + co = "checkout"; + cp = "cherry-pick"; + cpx = "cherry-pick -x"; + d = "diff"; + f = "fetch"; + fo = "fetch origin"; + fu = "fetch upstream"; + lol = "log --graph --decorate --pretty=oneline --abbrev-commit"; + lola = "log --graph --decorate --pretty=oneline --abbrev-commit --all"; + pl = "pull"; + pr = "pull -r"; + ps = "push"; + psf = "push -f"; + rb = "rebase"; + rbi = "rebase -i"; + r = "remote"; + ra = "remote add"; + rr = "remote rm"; + rv = "remote -v"; + rs = "remote show"; + st = "status"; + }; - aliases = { - a = "add"; - c = "commit"; - ca = "commit --amend"; - can = "commit --amend --no-edit"; - cl = "clone"; - cm = "commit -m"; - co = "checkout"; - cp = "cherry-pick"; - cpx = "cherry-pick -x"; - d = "diff"; - f = "fetch"; - fo = "fetch origin"; - fu = "fetch upstream"; - lol = "log --graph --decorate --pretty=oneline --abbrev-commit"; - lola = "log --graph --decorate --pretty=oneline --abbrev-commit --all"; - pl = "pull"; - pr = "pull -r"; - ps = "push"; - psf = "push -f"; - rb = "rebase"; - rbi = "rebase -i"; - r = "remote"; - ra = "remote add"; - rr = "remote rm"; - rv = "remote -v"; - rs = "remote show"; - st = "status"; + init.defaultBranch = "main"; }; - extraConfig = { init.defaultBranch = "main"; }; }; - programs.git-cliff = { enable = true; }; + programs.delta = { + enable = true; + enableGitIntegration = true; + }; + + programs.git-cliff = { + enable = true; + }; } diff --git a/home/alex/programs/jujutsu/default.nix b/home/alex/programs/jujutsu/default.nix index f7b6642..bcb67f6 100644 --- a/home/alex/programs/jujutsu/default.nix +++ b/home/alex/programs/jujutsu/default.nix @@ -9,8 +9,8 @@ programs.jujutsu = { enable = true; settings = { - user.name = config.programs.git.userName; - user.email = config.programs.git.userEmail; + user.name = config.programs.git.settings.user.name; + user.email = config.programs.git.settings.user.email; ui.default-command = "log"; aliases.init = [ "git" diff --git a/home/alex/programs/shell/default.nix b/home/alex/programs/shell/default.nix index 3866337..48b25b9 100644 --- a/home/alex/programs/shell/default.nix +++ b/home/alex/programs/shell/default.nix @@ -14,7 +14,14 @@ programs.zsh = { enable = true; + enableCompletion = true; autosuggestion.enable = true; + syntaxHighlighting.enable = true; + + initContent = '' + [ $TERM = "dumb" ] && unsetopt zle && PS1='$ ' + ''; + oh-my-zsh = { enable = true; plugins = [ diff --git a/home/alex/programs/xmonad/default.nix b/home/alex/programs/xmonad/default.nix index 486cc14..9256cb8 100644 --- a/home/alex/programs/xmonad/default.nix +++ b/home/alex/programs/xmonad/default.nix @@ -1,5 +1,9 @@ -{ config, lib, pkgs, ... }: - +{ + config, + lib, + pkgs, + ... +}: { config.xsession.windowManager.xmonad = { enable = true; @@ -8,5 +12,8 @@ }; # control backlight - config.home.packages = [ pkgs.xorg.xbacklight pkgs.scrot ]; + config.home.packages = [ + pkgs.xorg.xbacklight + pkgs.scrot + ]; } diff --git a/hosts/dregil/configuration.nix b/hosts/dregil/configuration.nix index f89f65e..3001398 100644 --- a/hosts/dregil/configuration.nix +++ b/hosts/dregil/configuration.nix @@ -50,11 +50,7 @@ in extraLocaleSettings = { TIME_STYLE = "iso"; }; - supportedLocales = [ - "C.UTF-8/UTF-8" - "en_US.UTF-8/UTF-8" - "de_DE.UTF-8/UTF-8" - ]; + extraLocales = "all"; }; console = { diff --git a/hosts/thrall/default.nix b/hosts/thrall/default.nix index cc9024d..164a582 100644 --- a/hosts/thrall/default.nix +++ b/hosts/thrall/default.nix @@ -324,6 +324,7 @@ in address = "127.0.0.1"; port = 3002; consumptionDirIsPublic = true; + configureTika = true; settings = { PAPERLESS_OCR_LANGUAGE = "deu+eng"; PAPERLESS_OCR_USER_ARGS = ''{"invalidate_digital_signatures": true}''; @@ -412,6 +413,7 @@ in mailserver = { enable = true; + stateVersion = 3; fqdn = "thrall.failco.de"; domains = [ "failco.de" @@ -459,6 +461,9 @@ in ]; "anne@kobjolke.de" = "anne.kobjolke@gmail.com"; "alexander@kobjolke.de" = "alex@kobjolke.de"; + "ida@kobjolke.de" = "alex@kobjolke.de"; + "klara@kobjolke.de" = "alex@kobjolke.de"; + "charlie@kobjolke.de" = "alex@kobjolke.de"; }; certificateScheme = "acme-nginx"; diff --git a/modules/nix-config.nix b/modules/nix-config.nix index 80b1825..09a5343 100644 --- a/modules/nix-config.nix +++ b/modules/nix-config.nix @@ -26,8 +26,14 @@ keep-outputs = true; keep-derivations = true; - trusted-substituters = [ "https://devenv.cachix.org" ]; - trusted-public-keys = [ "devenv.cachix.org-1:w1cLUi8dv3hnoSPGAuibQv+f9TZLr6cv/Hm9XgU50cw=" ]; + trusted-substituters = [ + "https://devenv.cachix.org" + "https://nixcache.reflex-frp.org" + ]; + trusted-public-keys = [ + "devenv.cachix.org-1:w1cLUi8dv3hnoSPGAuibQv+f9TZLr6cv/Hm9XgU50cw=" + "ryantrinkle.com-1:JJiAKaRv9mWgpVAz8dwewnZe0AzzEAzPkagE9SP5NWI=" + ]; trusted-users = [ "root" "alex" diff --git a/modules/wm/x.nix b/modules/wm/x.nix index d186430..aa86b29 100644 --- a/modules/wm/x.nix +++ b/modules/wm/x.nix @@ -26,11 +26,10 @@ enable = true; greeters.slick.enable = true; }; - - desktopManager.xfce.enable = true; - desktopManager.gnome.enable = true; }; + desktopManager.gnome.enable = true; + # Enable touchpad support (enabled default in most desktopManager). libinput = { enable = true; diff --git a/scripts/nixos-mailserver-migration-03.py b/scripts/nixos-mailserver-migration-03.py new file mode 100755 index 0000000..6aedad4 --- /dev/null +++ b/scripts/nixos-mailserver-migration-03.py @@ -0,0 +1,142 @@ +#!/usr/bin/env nix-shell +#!nix-shell -i python3 -p python3 + +import argparse +import os +import shutil +import sys +from enum import Enum +from pathlib import Path +from pwd import getpwnam + + +class FolderLayout(Enum): + Default = 1 + Folder = 2 + + +def check_user(vmail_root: Path): + owner = vmail_root.owner() + owner_uid = getpwnam(owner).pw_uid + + if os.geteuid() == owner_uid: + return + + try: + print( + f"Trying to switch effective user id to {owner_uid} ({owner})", + file=sys.stderr, + ) + os.seteuid(owner_uid) + return + except PermissionError: + print( + f"Failed switching to virtual mail user. Please run this script under it, for example by using `sudo -u {owner}`)", + file=sys.stderr, + ) + sys.exit(1) + + +def is_maildir_related(path: Path, layout: FolderLayout) -> bool: + if path.name in [ + "subscriptions" + # https://doc.dovecot.org/2.3/admin_manual/mailbox_formats/maildir/#imap-uid-mapping + "dovecot-uidlist", + # https://doc.dovecot.org/2.3/admin_manual/mailbox_formats/maildir/#imap-keywords + "dovecot-keywords", + ]: + return True + if not path.is_dir(): + return False + if path.name in ["cur", "new", "tmp"]: + return True + if layout is FolderLayout.Default and path.name.startswith("."): + return True + if layout is FolderLayout.Folder: + if path.name in ["mail"]: + return False + return True + + return False + + +def mkdir(dst: Path, dry_run: bool = True): + print(f'mkdir "{dst}"') + if not dry_run: + # u+rwx, setgid + dst.mkdir(mode=0o2700) + + +def move(src: Path, dst: Path, dry_run: bool = True): + print(f'mv "{src}" "{dst}"') + if not dry_run: + src.rename(dst) + + +def delete(dst: Path, dry_run: bool = True): + if not dst.exists(): + return + + if dst.is_dir(): + print(f'rm --recursive "{dst}"') + if not dry_run: + shutil.rmtree(dst) + else: + print(f'rm "{dst}"') + if not dry_run: + dst.unlink() + + +def main(vmail_root: Path, layout: FolderLayout, dry_run: bool = True): + maildirs = {path.parent for path in vmail_root.glob("*/*/cur")} + maybe_delete = [] + + # The old maildir will be the new home directory + for homedir in maildirs: + maildir = homedir / "mail" + mkdir(maildir, dry_run) + + for path in homedir.iterdir(): + if is_maildir_related(path, layout): + move(path, maildir / path.name, dry_run) + else: + maybe_delete.append(path) + + # Files that are part of the previous home directory, but now obsolete + for path in [ + vmail_root / ".dovecot.lda-dupes", + vmail_root / ".dovecot.lda-dupes.locks", + ]: + delete(path, dry_run) + + # The remaining files are likely obsolete, but should still be checked with care + for path in maybe_delete: + print(f"# rm {str(path)}") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description=""" + NixOS Mailserver Migration #3: Dovecot mail directory migration + (https://nixos-mailserver.readthedocs.io/en/latest/migrations.html#dovecot-mail-directory-migration) + """ + ) + parser.add_argument( + "vmail_root", type=Path, help="Path to the `mailserver.mailDirectory`" + ) + parser.add_argument( + "--layout", + choices=["default", "folder"], + required=True, + help="Folder layout: 'default' unless `mailserver.useFsLayout` was enabled, then'folder'", + ) + parser.add_argument( + "--execute", action="store_true", help="Actually perform changes" + ) + + args = parser.parse_args() + + layout = FolderLayout.Default if args.layout == "default" else FolderLayout.Folder + + check_user(args.vmail_root) + main(args.vmail_root, layout, not args.execute)