chore: Update inputs
This commit is contained in:
parent
524cf30e8d
commit
73c23c3539
4 changed files with 181 additions and 33 deletions
60
flake.lock
generated
60
flake.lock
generated
|
|
@ -10,11 +10,11 @@
|
|||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1747575206,
|
||||
"narHash": "sha256-NwmAFuDUO/PFcgaGGr4j3ozG9Pe5hZ/ogitWhY+D81k=",
|
||||
"lastModified": 1750173260,
|
||||
"narHash": "sha256-9P1FziAwl5+3edkfFcr5HeGtQUtrSdk/MksX39GieoA=",
|
||||
"owner": "ryantm",
|
||||
"repo": "agenix",
|
||||
"rev": "4835b1dc898959d8547a871ef484930675cb47f1",
|
||||
"rev": "531beac616433bac6f9e2a19feb8e99a22a66baf",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -68,11 +68,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1749436314,
|
||||
"narHash": "sha256-CqmqU5FRg5AadtIkxwu8ulDSOSoIisUMZRLlcED3Q5w=",
|
||||
"lastModified": 1751607816,
|
||||
"narHash": "sha256-5PtrwjqCIJ4DKQhzYdm8RFePBuwb+yTzjV52wWoGSt4=",
|
||||
"owner": "nix-community",
|
||||
"repo": "disko",
|
||||
"rev": "dfa4d1b9c39c0342ef133795127a3af14598017a",
|
||||
"rev": "da6109c917b48abc1f76dd5c9bf3901c8c80f662",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -165,11 +165,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1742649964,
|
||||
"narHash": "sha256-DwOTp7nvfi8mRfuL1escHDXabVXFGT1VlPD1JHrtrco=",
|
||||
"lastModified": 1749636823,
|
||||
"narHash": "sha256-WUaIlOlPLyPgz9be7fqWJA5iG6rHcGRtLERSCfUDne4=",
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"rev": "dcf5072734cb576d2b0c59b2ac44f5050b5eac82",
|
||||
"rev": "623c56286de5a3193aa38891a6991b28f9bab056",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -249,11 +249,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1749628652,
|
||||
"narHash": "sha256-f8jDF4G9m7pPySeQc6KskqMgtcJq6X1o2CytMx66qAE=",
|
||||
"lastModified": 1751760902,
|
||||
"narHash": "sha256-qBGNn7T/zOgUDQTo/RM/D2oxMkB2x36j3ajvpVanEVs=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "450f06ec3cd0d86f67db58a7245db8848773e895",
|
||||
"rev": "8b0180dde1d6f4cf632e046309e8f963924dfbd0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -334,11 +334,11 @@
|
|||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1749285348,
|
||||
"narHash": "sha256-frdhQvPbmDYaScPFiCnfdh3B/Vh81Uuoo0w5TkWmmjU=",
|
||||
"lastModified": 1751637120,
|
||||
"narHash": "sha256-xVNy/XopSfIG9c46nRmPaKfH1Gn/56vQ8++xWA8itO4=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "3e3afe5174c561dee0df6f2c2b2236990146329f",
|
||||
"rev": "5c724ed1388e53cc231ed98330a60eb2f7be4be3",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -350,11 +350,11 @@
|
|||
},
|
||||
"nixpkgs-25_05": {
|
||||
"locked": {
|
||||
"lastModified": 1747610100,
|
||||
"narHash": "sha256-rpR5ZPMkWzcnCcYYo3lScqfuzEw5Uyfh+R0EKZfroAc=",
|
||||
"lastModified": 1749727998,
|
||||
"narHash": "sha256-mHv/yeUbmL91/TvV95p+mBVahm9mdQMJoqaTVTALaFw=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "ca49c4304acf0973078db0a9d200fd2bae75676d",
|
||||
"rev": "fd487183437963a59ba763c0cc4f27e3447dd6dd",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -414,11 +414,11 @@
|
|||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1747179050,
|
||||
"narHash": "sha256-qhFMmDkeJX9KJwr5H32f1r7Prs7XbQWtO0h3V0a0rFY=",
|
||||
"lastModified": 1749285348,
|
||||
"narHash": "sha256-frdhQvPbmDYaScPFiCnfdh3B/Vh81Uuoo0w5TkWmmjU=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "adaa24fbf46737f3f1b5497bf64bae750f82942e",
|
||||
"rev": "3e3afe5174c561dee0df6f2c2b2236990146329f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -491,11 +491,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1749636823,
|
||||
"narHash": "sha256-WUaIlOlPLyPgz9be7fqWJA5iG6rHcGRtLERSCfUDne4=",
|
||||
"lastModified": 1750779888,
|
||||
"narHash": "sha256-wibppH3g/E2lxU43ZQHC5yA/7kIKLGxVEnsnVK1BtRg=",
|
||||
"owner": "cachix",
|
||||
"repo": "pre-commit-hooks.nix",
|
||||
"rev": "623c56286de5a3193aa38891a6991b28f9bab056",
|
||||
"rev": "16ec914f6fb6f599ce988427d9d94efddf25fe6d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -543,11 +543,11 @@
|
|||
"nixpkgs-25_05": "nixpkgs-25_05"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1749244584,
|
||||
"narHash": "sha256-BGmEptAyP2NrP4gX7VMYWo53h5e8r2iE/uo2+YPMcfo=",
|
||||
"lastModified": 1751772161,
|
||||
"narHash": "sha256-CxekYKL+M4VGb1pQk7lVDRe1x3th/5Du2xq/X1nNors=",
|
||||
"owner": "simple-nixos-mailserver",
|
||||
"repo": "nixos-mailserver",
|
||||
"rev": "8b27add0883067e990bff4f847b6f7b6f53324b9",
|
||||
"rev": "6004878dc6c1cb1c0cedd8c10a59d416c8dad9c9",
|
||||
"type": "gitlab"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -559,11 +559,11 @@
|
|||
},
|
||||
"stable": {
|
||||
"locked": {
|
||||
"lastModified": 1749488106,
|
||||
"narHash": "sha256-b9GIWdF/8jKpCC5JIMgDLZgwe8cEbty2fyTyo1eDFfI=",
|
||||
"lastModified": 1751274312,
|
||||
"narHash": "sha256-/bVBlRpECLVzjV19t5KMdMFWSwKLtb5RyXdjz3LJT+g=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "8fe3e32e7f210522377c3bcff80931a3284ace6a",
|
||||
"rev": "50ab793786d9de88ee30ec4e4c24fb4236fc2674",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
|
|||
|
|
@ -412,7 +412,7 @@ in
|
|||
|
||||
mailserver = {
|
||||
enable = true;
|
||||
stateVersion = 1;
|
||||
stateVersion = 3;
|
||||
fqdn = "thrall.failco.de";
|
||||
domains = [
|
||||
"failco.de"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
142
scripts/nixos-mailserver-migration-03.py
Executable file
142
scripts/nixos-mailserver-migration-03.py
Executable file
|
|
@ -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)
|
||||
Loading…
Add table
Add a link
Reference in a new issue