forked from Fachschaft/nixConfig
Add mail forwarding based on alias files
This commit is contained in:
parent
d7b8f935cd
commit
7796b7aa00
6 changed files with 275 additions and 0 deletions
|
@ -53,6 +53,12 @@
|
||||||
_module.args.pkgs = import inputs.nixpkgs {
|
_module.args.pkgs = import inputs.nixpkgs {
|
||||||
inherit system;
|
inherit system;
|
||||||
config.permittedInsecurePackages = ["jitsi-meet-1.0.8043"];
|
config.permittedInsecurePackages = ["jitsi-meet-1.0.8043"];
|
||||||
|
|
||||||
|
overlays = [
|
||||||
|
(_: _: {
|
||||||
|
alias-to-sieve = inputs.alias-to-sieve.packages.x86_64-linux.default; # add custom package to convert alias files to sieve scripts on the stalwart machine
|
||||||
|
})
|
||||||
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,28 @@
|
||||||
enable = true;
|
enable = true;
|
||||||
# see passwd on azathoth for plaintext or machine secret in encoded format for HTTP Basic AUTH
|
# see passwd on azathoth for plaintext or machine secret in encoded format for HTTP Basic AUTH
|
||||||
stalwartAdminHash = "$argon2i$v=19$m=4096,t=3,p=1$d0hYOTkzclpzSmFTZUplWnhVeWE$I7q9uB19RWL0oZKaPlMPSlGfFp6FQ/vrx80FFKCsalg";
|
stalwartAdminHash = "$argon2i$v=19$m=4096,t=3,p=1$d0hYOTkzclpzSmFTZUplWnhVeWE$I7q9uB19RWL0oZKaPlMPSlGfFp6FQ/vrx80FFKCsalg";
|
||||||
|
domains = [
|
||||||
|
# lists.mathebau.de is forwarded to another VM and does not need to be listed here.
|
||||||
|
{
|
||||||
|
domain = "matheball.de";
|
||||||
|
allowlistPass = config.sops.secrets."allowlistPass/matheball".path;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
domain = "mathebau.de";
|
||||||
|
allowlistPass = config.sops.secrets."allowlistPass/mathebau".path;
|
||||||
|
virt_aliases = config.sops.secrets."mathebau.aliases".path;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
domain = "mathechor.de";
|
||||||
|
allowlistPass = config.sops.secrets."allowlistPass/mathechor".path;
|
||||||
|
virt_aliases = config.sops.secrets."mathechor.aliases".path;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
domain = "koma89.tu-darmstadt.de";
|
||||||
|
allowlistPass = config.sops.secrets."allowlistPass/koma".path;
|
||||||
|
virt_aliases = config.sops.secrets."koma.aliases".path;
|
||||||
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
networking.hostName = "kaalut";
|
networking.hostName = "kaalut";
|
||||||
|
@ -19,6 +41,25 @@
|
||||||
system.stateVersion = "24.05";
|
system.stateVersion = "24.05";
|
||||||
|
|
||||||
sops.secrets = {
|
sops.secrets = {
|
||||||
|
# Virtual alias file
|
||||||
|
"mathebau.aliases" = {
|
||||||
|
sopsFile = ./mathebau.aliases.yaml;
|
||||||
|
owner = "stalwart-mail";
|
||||||
|
group = "stalwart-mail";
|
||||||
|
mode = "0440";
|
||||||
|
};
|
||||||
|
"mathechor.aliases" = {
|
||||||
|
sopsFile = ./mathechor.aliases.yaml;
|
||||||
|
owner = "stalwart-mail";
|
||||||
|
group = "stalwart-mail";
|
||||||
|
mode = "0440";
|
||||||
|
};
|
||||||
|
"koma.aliases" = {
|
||||||
|
sopsFile = ./koma.aliases.yaml;
|
||||||
|
owner = "stalwart-mail";
|
||||||
|
group = "stalwart-mail";
|
||||||
|
mode = "0440";
|
||||||
|
};
|
||||||
backupKey = {
|
backupKey = {
|
||||||
sopsFile = ./backupKey.yaml;
|
sopsFile = ./backupKey.yaml;
|
||||||
owner = "root";
|
owner = "root";
|
||||||
|
|
48
nixos/machines/kaalut/koma.aliases.yaml
Normal file
48
nixos/machines/kaalut/koma.aliases.yaml
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
koma.aliases: ENC[AES256_GCM,data:r9dJzjUrv9BBr6emtHuIm71OamwTQdxdAbWuh62ZPG/tbvg8YimMvUno1WXn6EXn+0q2Gf+r4UiB6RJLD62D+JU+lEAKg9LKfX+578M4eCIbwRqkHWQYAtT/V3nB8L7/dqcvdatF90+50w==,iv:SL13OY8XUNdVBkZlKBfqwzT5LTtZcykyGIK+nHHOa10=,tag:Yyu2/ZqLotmFD+cMwtXYlA==,type:str]
|
||||||
|
sops:
|
||||||
|
kms: []
|
||||||
|
gcp_kms: []
|
||||||
|
azure_kv: []
|
||||||
|
hc_vault: []
|
||||||
|
age:
|
||||||
|
- recipient: age1rasjnr2tlv9y70sj0z0hwpgpxdc974wzg5umtx2pnc6z0p05u3js6r8sln
|
||||||
|
enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBBS283ZTdKVTVLaDRDV1N5
|
||||||
|
SGhJQjJWdXJzc1l5OWtCWVdueTJMdjZpUjJzCmtUZFRYR0JXTW15Z0NyMktEbW5w
|
||||||
|
dkk1TjF0dVQ3MlFhNUFTbU0vMFdySWcKLS0tIDZPQmxSVGYzT2dDM244ek95dk9n
|
||||||
|
SnhtQWJic3B2YTM1ZlE3SHVRSjl1YVkKgUXW7JW3WSM5EusBoxQMsBRGwIqqi7Lo
|
||||||
|
DgWLq/P1rruuqRAS8hl4cht3jz6PlCJgVh2xpaM/kfkFS8ZuhVFw4g==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
- recipient: age1epz92k2rkp43hkrg3u0jgkzhnkwx8y43kag7rvfzwl9wcddelvusyetxl7
|
||||||
|
enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBKdmcyM3hSUFdlM25UUndu
|
||||||
|
RUhzdEhsakdEdytBUGRyRTFXRzdYK2RBR0dnCmJqOTlvYkZkeld3eDYvRmRmUU5u
|
||||||
|
aHArR0FkZWRtT0hoNTZpS1JmaTRHencKLS0tIGVVSWN0NWQyQWdrcXdQUnQxUjdu
|
||||||
|
MWFZWVQ3RmZZS3FnRkJPdDRrOTZrWG8KVgFqfeBLw5gTBKugfnC4a5OLwOhosSgy
|
||||||
|
3hXbGMrJiBDwOS+70H3L+IwiNSoJ6mL+ufShCTq8wER2L9GTteI8gg==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
- recipient: age1dhzugelagj6vge5jjxwwn0522ngf7fhxn04sxy2tm8557rtme5tstprwnj
|
||||||
|
enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAzamM5TDVQM0hnZklsbncx
|
||||||
|
SlBMM0NpcnBBai94czV5WE1Md21EeE1kVXpFClpDVTRqYm5rWFhjVjRPQm1IVWxW
|
||||||
|
WTNlZFo4Y3VVNjZhckZ0RFVlQlV0OEEKLS0tIGJOR3k0OUorYTNXL01KQWJBUzVD
|
||||||
|
V0xidWR0SnBDM01hRlkrTlY4eEIrc1EK1Hye/jrQebkEDQ8muJpgHqBLefjnEJPF
|
||||||
|
GxdANetJLuZeeiOUjaUcbP6tecqZpiWN8fFEXrjNL4vnrHvJ+bR1aA==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
- recipient: age1ktwclxa640l89le6yecm8v2z6hmwr4lusd6x9gyzamhv57887szqtqp59a
|
||||||
|
enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBqQURCeGJBYytCdlhrWjF5
|
||||||
|
c1ZrbEFENDF5bTNMaE52SE5CS1dVdWJCNlFzClZtK1QxOWY0dEVRRWY4MEtlZ1N1
|
||||||
|
eGlaYXVLMUJiUi9FckdNcllBRCt4cmMKLS0tIEZuOTZQTm9vWHQ4Y3Z6RVloT0VL
|
||||||
|
OW5ZQWIvU2x1OEN6OW84K0dqRmhGNUUKOA3ugnG/ZD7m1DKrFjpZ8opPnjPtLaQx
|
||||||
|
t8qgGuQIoX6KeUb+YybRAOAPPzl51/m9GSUB43Eanm/tVJpdaew7/g==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
lastmodified: "2025-02-25T17:41:29Z"
|
||||||
|
mac: ENC[AES256_GCM,data:lZ9AXtJzVuc8Jg9L0aGhS18cs8pTjOG/xNP2tG25/7/PEdEV1SNwbxubGQOFAHrNbiDbmJMKJq96mhV8e3tHszlrzQnU1uyu9MrWiAYwV3CjmwSqC4J9ezSm/AY9e9+OWKn6sb4RVsz9A7aDGUhhoZMycnPNRKlpTuzdTIJK98o=,iv:LxSsZoHkJ2HFXBLWkw+SUb/LYW2ciE1DtzpoV4YLOwQ=,tag:QeYmreRGZk4PqlLWJLLD8g==,type:str]
|
||||||
|
pgp: []
|
||||||
|
unencrypted_suffix: _unencrypted
|
||||||
|
version: 3.9.4
|
48
nixos/machines/kaalut/mathebau.aliases.yaml
Normal file
48
nixos/machines/kaalut/mathebau.aliases.yaml
Normal file
File diff suppressed because one or more lines are too long
48
nixos/machines/kaalut/mathechor.aliases.yaml
Normal file
48
nixos/machines/kaalut/mathechor.aliases.yaml
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
mathechor.aliases: ENC[AES256_GCM,data:VKEGY6KVtgKApnV7N2e2cqy9erDWQ2fb88Gwcpp5th/t0VGp16KGDtGiuQXhY80j6dDIcQMd9bLHzqAzc4+i/WhmEPhiXUkGiEKuarMfvqNl1LBlXFCoIrUXMMSIqab9q+fE3ignVQapE/YZt9aniyvg1prcmBcwIy9rDoHkiTY006ux5CM+vX0F60ADX8Nf6Qmn/JncPxXgq2jYsBxjXPj7BwJaair/+nxrbVf0,iv:Elj1NDeR1fdIIjIbjvkV3BmcVAKjwdMfknuNxMXJsa4=,tag:AkXWQ8sTMLsd7a+MfRcF/w==,type:str]
|
||||||
|
sops:
|
||||||
|
kms: []
|
||||||
|
gcp_kms: []
|
||||||
|
azure_kv: []
|
||||||
|
hc_vault: []
|
||||||
|
age:
|
||||||
|
- recipient: age1rasjnr2tlv9y70sj0z0hwpgpxdc974wzg5umtx2pnc6z0p05u3js6r8sln
|
||||||
|
enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjMlRsWnkrREVaQitsWHMy
|
||||||
|
WHZFVG1qN25QbWFHcUxNS1Z0SFRDd1oxeG5RCi8wNUhkeWh2VjI4ZGowM1ExaExh
|
||||||
|
SE1yVGFTUHZadUdDL3pxaGdKTHQ0VTgKLS0tIHVNM2xlOFNNS3dFalJqZUtPODRn
|
||||||
|
b2NOTHpXSUVyaFRJNG5ONCt0TTVjOEkKYld7KN995QxdrGBVRYgCxO7kGwsiq+cp
|
||||||
|
iQJTjMdoFygIrTkgE5Rj89/GCiVe0+yAWJuQF7PEnC3cyq0M1g+fzw==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
- recipient: age1epz92k2rkp43hkrg3u0jgkzhnkwx8y43kag7rvfzwl9wcddelvusyetxl7
|
||||||
|
enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBPRFJCeXhwQVFSWmgzNHBu
|
||||||
|
SHlTTGtiRkI5bmhKa1B0QTZMY3FERmlUd0FBCk1vOUpydEFZUExpR2hpWm9mRHpE
|
||||||
|
dk9MQ042K0FpSVJ3dUlQcktGT2k1VjAKLS0tIHpGRmwzNE01YkV1TW94RkNmMjN4
|
||||||
|
YnNXZUlta3NMVW9Cc3V2T0t4R01RSlkKNTW3gnF49BuPwF3jwciOYThJe+gJa0a6
|
||||||
|
WKYt+aJuHi0a4y5rS/wfttij+hS5vYVNOrgfJ5bGinkNuAygA2hMOg==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
- recipient: age1dhzugelagj6vge5jjxwwn0522ngf7fhxn04sxy2tm8557rtme5tstprwnj
|
||||||
|
enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB6MjZOR1dwb3RjZnlNNW4v
|
||||||
|
SzJnT1BRVktWNDI5S2Z2NnhQQzdNeS9ralI0CnN0SU9ESEV3ZCtRQmpZK3VZOGYx
|
||||||
|
Y3FVUy9zY3RZcGxyVmttVzFJL1haYWsKLS0tIENGRW1KZkpUdldOZWgzSXVoenpX
|
||||||
|
dTVpNUpWallSTzJ3cEZJTXk3c2t1czgKzJCwhMspzAsjzwSRdSPUoseEAsKp8HFy
|
||||||
|
cL9if92ar68HMHTdoy0Zvy+5AbxKUxgXZ2t8cDgkL8bNG5Ri2xYaUA==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
- recipient: age1ktwclxa640l89le6yecm8v2z6hmwr4lusd6x9gyzamhv57887szqtqp59a
|
||||||
|
enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtNm5xUGkrK1dYd2ZtamFW
|
||||||
|
NXpNMEtvNTl3U3MzeVNSbVJOdGdlWGsxRHlZCllQVmNtYzBJNDc2Y0dmUlNsbTF5
|
||||||
|
RHB4QWZ1VGNFVkx1Q0hNK3FDTTRrUlkKLS0tIG9hbldDeHk0YmVZV2IwMXNpYStU
|
||||||
|
Q29uVHBCb2pTeWVJVmVXbWpycnFneWMKnDmu5917dddV8vjO0L8OP3wXMjDi46Ro
|
||||||
|
b9eOY8l74jm4sTxyKNvnkEjD6iHn1t7f8J7HAbWrpZY+J0i77nrzQw==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
lastmodified: "2024-11-23T09:05:51Z"
|
||||||
|
mac: ENC[AES256_GCM,data:Xnulo0681LtgH9SZt9DL3nd9bSDH+TCQDvbKdggVBJ66rxBiKmlbu5MAblAWqxbdZ6EelldaVeX9OaL2rYJoYbTWxzw2iuPieldp3Ah3PsTI2C8W+UD9KVHcB+3AMOmVmJZzFlZvTwyfPfZRNNb0HAijkN97P3fP0r1Iqf3YjiI=,iv:vhu38HM4e+PyyChXvI87LWSGtKQQiXUr4MKrI7kotzk=,tag:eNuQD74kUO+duqEXNbLJBw==,type:str]
|
||||||
|
pgp: []
|
||||||
|
unencrypted_suffix: _unencrypted
|
||||||
|
version: 3.9.1
|
|
@ -1,4 +1,6 @@
|
||||||
/*
|
/*
|
||||||
|
* Forwarding mails: Update the Sops-secrets in the machine directory, rebuild on the VM and deploy.
|
||||||
|
* Everything else should happen automatically but new redirects might take up to two hours due HRZ infrastructure.
|
||||||
* Using the web admin interface: Set your SSH to do portforwarding of some local port to port 80 of the VM and
|
* Using the web admin interface: Set your SSH to do portforwarding of some local port to port 80 of the VM and
|
||||||
* and use your personal admin account or create one using the fallback admin password.
|
* and use your personal admin account or create one using the fallback admin password.
|
||||||
* Create users with mail boxes: Go to the admin interface and create them.
|
* Create users with mail boxes: Go to the admin interface and create them.
|
||||||
|
@ -9,6 +11,7 @@
|
||||||
{
|
{
|
||||||
config,
|
config,
|
||||||
lib,
|
lib,
|
||||||
|
pkgs,
|
||||||
...
|
...
|
||||||
}: let
|
}: let
|
||||||
inherit
|
inherit
|
||||||
|
@ -26,6 +29,25 @@ in {
|
||||||
type = str;
|
type = str;
|
||||||
description = "String containing the hashed fallback admin password";
|
description = "String containing the hashed fallback admin password";
|
||||||
};
|
};
|
||||||
|
domains = mkOption {
|
||||||
|
type = listOf (lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
domain = mkOption {
|
||||||
|
description = "Domain name that we serve. We also push its addresses to HRZ.";
|
||||||
|
type = strMatching "^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$"; #Regex from https://www.oreilly.com/library/view/regular-expressions-cookbook/9781449327453/ch08s15.html
|
||||||
|
};
|
||||||
|
allowlistPass = mkOption {
|
||||||
|
description = "Password file for the HRZ API that gets a list of mailaddresses that we serve";
|
||||||
|
type = path;
|
||||||
|
};
|
||||||
|
virt_aliases = mkOption {
|
||||||
|
description = "File path to a virtual alias file applicable for this domain";
|
||||||
|
type = path;
|
||||||
|
default = "/dev/null"; # there might not be an alias file and reading an empty one works with our implementation
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
|
@ -127,6 +149,32 @@ in {
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Stalwart gets its configuration from two places: A TOML configuration file that we control in this module
|
||||||
|
# and from a database that can be configured from web management interface or via Rest API.
|
||||||
|
# We here define what comes from the TOML-file and especially add "sieve.trusted.scripts.*" to the default ones
|
||||||
|
# because only TOML-based keys may use macros to load files from disk.
|
||||||
|
# We want this to be able to load our sieve-script for mail forwarding.
|
||||||
|
config.local-keys =
|
||||||
|
[
|
||||||
|
"store.*"
|
||||||
|
"directory.*"
|
||||||
|
"tracer.*"
|
||||||
|
"server.*"
|
||||||
|
"!server.blocked-ip.*"
|
||||||
|
"authentication.fallback-admin.*"
|
||||||
|
"cluster.node-id"
|
||||||
|
"storage.data"
|
||||||
|
"storage.blob"
|
||||||
|
"storage.lookup"
|
||||||
|
"storage.fts"
|
||||||
|
"storage.directory"
|
||||||
|
"lookup.default.hostname"
|
||||||
|
"certificate.*"
|
||||||
|
] # the default ones
|
||||||
|
++ ["sieve.trusted.scripts.*"]; #for macros to be able to include our redirection script
|
||||||
|
sieve.trusted.scripts.redirects.contents = "%{file:/tmp/virt_aliases}%"; # generated redirect script
|
||||||
|
session.data.script = "'redirects'";
|
||||||
|
|
||||||
authentication.fallback-admin = {
|
authentication.fallback-admin = {
|
||||||
user = "admin";
|
user = "admin";
|
||||||
# see passwd on azathoth for plaintext or machine secret in encoded format for HTTP Basic AUTH
|
# see passwd on azathoth for plaintext or machine secret in encoded format for HTTP Basic AUTH
|
||||||
|
@ -149,6 +197,42 @@ in {
|
||||||
files = ["/root/.ssh/known_hosts"]; # for the backup server bragi
|
files = ["/root/.ssh/known_hosts"]; # for the backup server bragi
|
||||||
};
|
};
|
||||||
|
|
||||||
|
systemd = {
|
||||||
|
services = {
|
||||||
|
"stalwart-mail" = {
|
||||||
|
restartTriggers = lib.attrsets.mapAttrsToList (_: aliaslist: aliaslist.sopsFile) config.sops.secrets; # restart if secrets, especially alias files, have changed.
|
||||||
|
serviceConfig.PrivateTmp = lib.mkForce false; # enable access to generated Sieve script
|
||||||
|
};
|
||||||
|
"virt-aliases-generator" = {
|
||||||
|
description = "Virtual Aliases Generator: Generate a sieve script from the virtual alias file";
|
||||||
|
script = lib.strings.concatStringsSep "" (["${pkgs.alias-to-sieve}/bin/alias_to_sieve "] ++ map (x: "${x.virt_aliases} ${x.domain} ") cfg.domains ++ ["> /tmp/virt_aliases"]);
|
||||||
|
wantedBy = ["stalwart-mail.service"]; # Rerun on stalwart restart because forwardings may have changed.
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
User = "stalwart-mail";
|
||||||
|
NoNewPrivileges = true;
|
||||||
|
# See https://www.man7.org/linux/man-pages/man5/systemd.exec.5.html
|
||||||
|
PrivateTmp = false;
|
||||||
|
ProtectHome = true;
|
||||||
|
ReadOnlyPaths = "/";
|
||||||
|
ReadWritePaths = "/tmp";
|
||||||
|
InaccessiblePaths = "-/lost+found";
|
||||||
|
PrivateDevices = true;
|
||||||
|
PrivateUsers = true;
|
||||||
|
ProtectHostname = true;
|
||||||
|
ProtectClock = true;
|
||||||
|
ProtectKernelTunables = true;
|
||||||
|
ProtectKernelModules = true;
|
||||||
|
ProtectKernelLogs = true;
|
||||||
|
ProtectControlGroups = true;
|
||||||
|
LockPersonality = true;
|
||||||
|
MemoryDenyWriteExecute = true;
|
||||||
|
RestrictRealtime = true;
|
||||||
|
RestrictSUIDSGID = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
# Backups
|
# Backups
|
||||||
services.borgbackup.jobs.mail = {
|
services.borgbackup.jobs.mail = {
|
||||||
paths = [
|
paths = [
|
||||||
|
|
Loading…
Add table
Reference in a new issue