aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--flake.lock48
-rw-r--r--hosts/by-name/server2/configuration.nix20
-rw-r--r--hosts/by-name/server3/configuration.nix15
-rw-r--r--modules/by-name/co/constants/module.nix17
-rw-r--r--modules/by-name/sh/sharkey/module.nix297
-rw-r--r--modules/by-name/st/stalwart-mail/module.nix72
-rw-r--r--modules/by-name/st/stalwart-mail/settings.nix9
-rw-r--r--modules/by-name/ta/taskchampion-sync/module.nix10
-rw-r--r--pkgs/by-name/sh/sharkey/package.nix4
-rw-r--r--pkgs/by-name/sh/sharkey/unstable_package.nix176
-rw-r--r--pkgs/by-name/st/stalwart-mail-free/package.nix4
-rw-r--r--tests/by-name/em/email-dns/nodes/mail_server.nix6
-rw-r--r--tests/by-name/em/email-dns/nodes/name_server.nix232
-rw-r--r--tests/by-name/em/email-dns/nodes/user.nix6
-rw-r--r--tests/by-name/em/email-dns/test.nix34
-rw-r--r--tests/by-name/em/email-http/nodes/name_server.nix210
-rw-r--r--tests/by-name/em/email-http/test.nix123
-rw-r--r--tests/by-name/sh/sharkey/test.nix118
-rw-r--r--tests/common/acme/scripts.nix30
-rw-r--r--tests/common/acme/server.nix (renamed from tests/common/acme/default.nix)27
-rw-r--r--tests/common/dns/client.nix10
-rw-r--r--tests/common/dns/server.nix43
-rwxr-xr-xupdate.sh3
-rw-r--r--zones/vhack.eu/zone.nix3
24 files changed, 975 insertions, 542 deletions
diff --git a/flake.lock b/flake.lock
index a23f22a..75b1bc4 100644
--- a/flake.lock
+++ b/flake.lock
@@ -43,11 +43,11 @@
},
"crane": {
"locked": {
- "lastModified": 1742394900,
- "narHash": "sha256-vVOAp9ahvnU+fQoKd4SEXB2JG2wbENkpqcwlkIXgUC0=",
+ "lastModified": 1745022865,
+ "narHash": "sha256-tXL4qUlyYZEGOHUKUWjmmcvJjjLQ+4U38lPWSc8Cgdo=",
"owner": "ipetkov",
"repo": "crane",
- "rev": "70947c1908108c0c551ddfd73d4f750ff2ea67cd",
+ "rev": "25ca4c50039d91ad88cc0b8feacb9ad7f748dedf",
"type": "github"
},
"original": {
@@ -111,11 +111,11 @@
]
},
"locked": {
- "lastModified": 1741786315,
- "narHash": "sha256-VT65AE2syHVj6v/DGB496bqBnu1PXrrzwlw07/Zpllc=",
+ "lastModified": 1745224732,
+ "narHash": "sha256-0OWgbEKhpMLpk3WQi3ugOwxWW4Y6JVpKiQ+o0nuNzus=",
"owner": "nix-community",
"repo": "disko",
- "rev": "0d8c6ad4a43906d14abd5c60e0ffe7b587b213de",
+ "rev": "1770bf1ae5da05564f86b969ef21c7228cc1a70b",
"type": "github"
},
"original": {
@@ -214,11 +214,11 @@
},
"nixpkgs": {
"locked": {
- "lastModified": 1743036386,
- "narHash": "sha256-W1Qap/jwnpvWPXC+cUp0PlaZsJO05sfQfzffRrYW7YY=",
+ "lastModified": 1745186762,
+ "narHash": "sha256-vn1ixtFWtellgcZpdIoxCVu9agdK3647hi7lcc/58eQ=",
"owner": "NixOS",
"repo": "nixpkgs",
- "rev": "1751c9cb80247edc5fed79b90211a92c56bf91e6",
+ "rev": "c16961fda203155a314b0c75c13961c29e9ea7b0",
"type": "github"
},
"original": {
@@ -245,11 +245,11 @@
},
"nixpkgs-unstable": {
"locked": {
- "lastModified": 1743039536,
- "narHash": "sha256-O3GFPU0Uyv80LKVMMukVqrfxSzWKkBwQIHN2UnRSCZk=",
+ "lastModified": 1745215074,
+ "narHash": "sha256-JjkdlVI9BImDV5RrCiJk17cMSIqbefUXBM9trHRif+c=",
"owner": "NixOS",
"repo": "nixpkgs",
- "rev": "0ab4a506520ea9247e673e9849ecf84c72f88be2",
+ "rev": "78e2cd1a1590f8c70b329cbc7d13bb2ab5b5a16c",
"type": "github"
},
"original": {
@@ -278,11 +278,11 @@
]
},
"locked": {
- "lastModified": 1741508717,
- "narHash": "sha256-iQf1WdNxaApOFHIx4RLMRZ4f8g+8Xp0Z1/E/Mz2rLxY=",
+ "lastModified": 1744897914,
+ "narHash": "sha256-GIVU92o2TZBnKQXTb76zpQbWR4zjU2rFqWKNIIpXnqA=",
"owner": "yaxitech",
"repo": "ragenix",
- "rev": "2a2bea99d74927e54adf53cbf113219def67d5c9",
+ "rev": "40f2e17ecaeab4d78ec323e96a04548c0aaa5223",
"type": "github"
},
"original": {
@@ -317,11 +317,11 @@
]
},
"locked": {
- "lastModified": 1743042789,
- "narHash": "sha256-yPlxN0r3pQjUIwyX/qeWSTdpHjWy/AfmM0PK1bYkO18=",
+ "lastModified": 1745289264,
+ "narHash": "sha256-7nt+UJ7qaIUe2J7BdnEEph9n2eKEwxUwKS/QIr091uA=",
"owner": "oxalica",
"repo": "rust-overlay",
- "rev": "b4d2dee9d16e7725b71969f28862ded3a94a7934",
+ "rev": "3b7171858c20d5293360042936058fb0c4cb93a9",
"type": "github"
},
"original": {
@@ -342,11 +342,11 @@
"nixpkgs-24_11": "nixpkgs-24_11"
},
"locked": {
- "lastModified": 1742413977,
- "narHash": "sha256-NkhM9GVu3HL+MiXtGD0TjuPCQ4GFVJPBZ8KyI2cFDGU=",
+ "lastModified": 1745164839,
+ "narHash": "sha256-+0T3pBcl5BD3qHB2nGfwwnRhb4EeNlJEI0BUm5fXPmE=",
"owner": "simple-nixos-mailserver",
"repo": "nixos-mailserver",
- "rev": "b4fbffe79c00f19be94b86b4144ff67541613659",
+ "rev": "42651ce2d337921c99ae0c293ed9af49f7a89c6a",
"type": "gitlab"
},
"original": {
@@ -378,11 +378,11 @@
]
},
"locked": {
- "lastModified": 1742982148,
- "narHash": "sha256-aRA6LSxjlbMI6MmMzi/M5WH/ynd8pK+vACD9za3MKLQ=",
+ "lastModified": 1744961264,
+ "narHash": "sha256-aRmUh0AMwcbdjJHnytg1e5h5ECcaWtIFQa6d9gI85AI=",
"owner": "numtide",
"repo": "treefmt-nix",
- "rev": "61c88349bf6dff49fa52d7dfc39b21026c2a8881",
+ "rev": "8d404a69efe76146368885110f29a2ca3700bee6",
"type": "github"
},
"original": {
diff --git a/hosts/by-name/server2/configuration.nix b/hosts/by-name/server2/configuration.nix
index ba0de14..24513f4 100644
--- a/hosts/by-name/server2/configuration.nix
+++ b/hosts/by-name/server2/configuration.nix
@@ -83,6 +83,26 @@
};
redlib.enable = true;
rust-motd.enable = true;
+ sharkey = {
+ enable = true;
+ fqdn = "sharkey.vhack.eu";
+ settings = {
+ id = "aidx";
+
+ maxNoteLength = 8192;
+ maxFileSize = 1024 * 1024 * 1024;
+ proxyRemoteFiles = true;
+
+ # > At the suggestion of Sharkey maintainers,
+ # > this allows the server to run multiple workers
+ # > and without this (and postgres tuning), the instance runs slowly.
+ # Copied from: https://github.com/sodiboo/system/blob/b63c7b27f49043e8701b3ff5e1441cd27d5a2fff/sharkey.mod.nix#L21-L23
+ clusterLimit = 3;
+
+ signToActivityPubGet = true;
+ CheckActivityPubGetSigned = false;
+ };
+ };
taskchampion-sync.enable = true;
users.enable = true;
};
diff --git a/hosts/by-name/server3/configuration.nix b/hosts/by-name/server3/configuration.nix
index 7f5bce5..17085e8 100644
--- a/hosts/by-name/server3/configuration.nix
+++ b/hosts/by-name/server3/configuration.nix
@@ -71,6 +71,7 @@
enable = true;
fqdn = "mail.vhack.eu";
admin = "admin@vhack.eu";
+ initialAdminPassword = "$6$k/JGlODSgRyb6dG2$KV78QYipkS423WQQoQIcEWNFZdq4uuS5uIpJUNL1WLmXsD3b6KuLtt18TNU24Hnpup5TbMM5vtui/I.vGAybS/";
security = {
dkimKeys = let
loadKey = name: {
@@ -84,19 +85,7 @@
verificationMode = "strict";
};
openFirewall = true;
- principals = [
- {
- class = "individual";
- name = "soispha";
- secret = "$2b$05$XX36sJuHNbTFvi8DFldscOeQBHahluSkiUqD9QGzQaET7NJusSuQW";
- email = [
- "soispha@vhack.eu"
- "abuse@vhack.eu"
- "postmaster@vhack.eu"
- "admin@vhack.eu"
- ];
- }
- ];
+ principals = null;
};
postgresql.enable = true;
rust-motd.enable = true;
diff --git a/modules/by-name/co/constants/module.nix b/modules/by-name/co/constants/module.nix
index 9db6445..2115a37 100644
--- a/modules/by-name/co/constants/module.nix
+++ b/modules/by-name/co/constants/module.nix
@@ -25,6 +25,7 @@
config.vhack.constants = {
ids.uids = {
# Keep this sorted with `!sort --numeric-sort --key=2 --field-separator="="`
+ systemd-coredump = 151; # GROUP
opendkim = 221;
mautrix-whatsapp = 222;
etebase-server = 223;
@@ -43,16 +44,22 @@
nscd = 330;
sshd = 331;
systemd-oom = 332;
+ resolvconf = 333; # GROUP
nix-sync = 334;
nextcloud = 335;
redis-nextcloud = 336;
taskchampion = 337;
+ stalwart-mail-certificates = 338; # GROUP
+ sharkey = 339;
+ redis-sharkey = 340;
# As per the NixOS file, the uids should not be greater or equal to 400;
};
ids.gids = let
inherit (config.vhack.constants.ids) uids;
in {
+ # Please add your groups to the users and inherit them here.
+ # This avoids having an user/group id mismatch.
inherit
(uids)
acme
@@ -76,13 +83,13 @@
sshd
stalwart-mail
systemd-oom
+ sharkey
+ redis-sharkey
+ systemd-coredump # matches systemd-coredump user
+ resolvconf # This group is not matched to an user?
+ stalwart-mail-certificates # This group is used to connect nginx and stalwart-mail
;
- # Keep this sorted with `!sort --numeric-sort --key=2 --field-separator="="`
- systemd-coredump = 151; # matches systemd-coredump user
- resolvconf = 333; # This group is not matched to an user?
- stalwart-mail-certificates = 338; # This group is used to connect nginx and stalwart-mail
-
# The gid should match the uid. Thus should not be >= 400;
};
};
diff --git a/modules/by-name/sh/sharkey/module.nix b/modules/by-name/sh/sharkey/module.nix
new file mode 100644
index 0000000..a2f5445
--- /dev/null
+++ b/modules/by-name/sh/sharkey/module.nix
@@ -0,0 +1,297 @@
+# Source: https://github.com/sodiboo/system/blob/b63c7b27f49043e8701b3ff5e1441cd27d5a2fff/sharkey/module.nix
+{
+ config,
+ lib,
+ pkgs,
+ vhackPackages,
+ ...
+}: let
+ cfg = config.vhack.sharkey;
+
+ createDB = cfg.database.host == "127.0.0.1" && cfg.database.createLocally;
+
+ settingsFormat = pkgs.formats.yaml {};
+ configFile = settingsFormat.generate "sharkey-config.yml" cfg.settings;
+in {
+ options.vhack.sharkey = {
+ enable = lib.mkEnableOption "sharkey";
+
+ fqdn = lib.mkOption {
+ description = "The fully qualified domain name of this instance.";
+ type = lib.types.str;
+ example = "sharkey.shonk.social";
+ };
+
+ package = lib.mkOption {
+ type = lib.types.package;
+ default = vhackPackages.sharkey;
+ defaultText = lib.literalExpression "vhackPackages.sharkey";
+ description = "Sharkey package to use.";
+ };
+
+ dataDirectory = lib.mkOption {
+ type = lib.types.path;
+ default = "/var/lib/sharkey";
+ description = "The directory where sharkey stores it's data.";
+
+ # This is already set in the package.
+ readOnly = true;
+ };
+
+ database = {
+ createLocally = lib.mkOption {
+ description = "Whether to enable local db creation.";
+ type = lib.types.bool;
+ default = true;
+ };
+
+ host = lib.mkOption {
+ type = lib.types.str;
+ default = "127.0.0.1";
+ description = "The database host.";
+ };
+
+ port = lib.mkOption {
+ type = lib.types.port;
+ default = 5432;
+ description = "The database port.";
+ };
+
+ name = lib.mkOption {
+ type = lib.types.str;
+ default = "sharkey";
+ description = "The database name in postgresql.";
+ };
+ };
+
+ settings = lib.mkOption {
+ inherit (settingsFormat) type;
+ default = {};
+ description = ''
+ Configuration for Sharkey, see
+ <link xlink:href="https://activitypub.software/TransFem-org/Sharkey/-/blob/develop/.config/example.yml"/>
+ for supported settings.
+ '';
+ };
+ };
+
+ config = lib.mkIf cfg.enable {
+ environment.systemPackages = [cfg.package];
+
+ vhack = {
+ nginx.enable = true;
+
+ sharkey.settings = {
+ id = "aidx";
+
+ url = "https://${cfg.fqdn}/";
+ port = 5312;
+
+ db = {
+ inherit (cfg.database) host port;
+ db = cfg.database.name;
+ user = cfg.database.name;
+ pass = "sharkey-password";
+ };
+ redis = {
+ path = config.services.redis.servers."sharkey".unixSocket;
+ };
+ };
+
+ persist.directories = [
+ {
+ directory = "${config.services.redis.servers."sharkey".settings.dir}";
+ user = "sharkey";
+ group = "redis-sharey";
+ mode = "0770";
+ }
+ {
+ directory = "${cfg.dataDirectory}";
+ user = "sharkey";
+ group = "sharkey";
+ mode = "0770";
+ }
+ ];
+ };
+
+ services = {
+ nginx.virtualHosts."${cfg.fqdn}" = {
+ locations."/" = {
+ proxyPass = "http://127.0.0.1:${toString cfg.settings.port}";
+ proxyWebsockets = true;
+ };
+
+ # proxy_set_header Host $host;
+ # proxy_http_version 1.1;
+ # proxy_redirect off;
+ #
+ # # If it's behind another reverse proxy or CDN, remove the following.
+ # proxy_set_header X-Real-IP $remote_addr;
+ # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ # proxy_set_header X-Forwarded-Proto https;
+ #
+ # # For WebSocket
+ # proxy_set_header Upgrade $http_upgrade;
+ # proxy_set_header Connection $connection_upgrade;
+ #
+ # # Cache settings
+ # proxy_cache cache1;
+ # proxy_cache_lock on;
+ # proxy_cache_use_stale updating;
+ # proxy_force_ranges on;
+ # add_header X-Cache $upstream_cache_status;
+
+ enableACME = true;
+ forceSSL = true;
+ };
+
+ postgresql = lib.mkIf createDB {
+ enable = true;
+ settings.port = cfg.database.port;
+ ensureUsers = [
+ {
+ inherit (cfg.database) name;
+ ensureDBOwnership = true;
+ }
+ ];
+ ensureDatabases = [cfg.database.name];
+ };
+
+ redis = {
+ servers."sharkey" = {
+ enable = true;
+
+ user = "sharkey";
+
+ # Disable TCP listening. (We have a UNIX socket)
+ port = 0;
+ bind = null;
+
+ settings = {
+ protected-mode = true;
+ enable-protected-configs = false;
+ enable-debug-command = false;
+ enable-module-command = false;
+
+ supervised = "systemd";
+ stop-writes-on-bgsave-error = true;
+ sanitize-dump-payload = "clients";
+ };
+ };
+ };
+ };
+
+ systemd.services.postgresql.postStart = ''
+ $PSQL -tAc "ALTER ROLE ${cfg.database.name} WITH ENCRYPTED PASSWORD 'sharkey-password';"
+ '';
+
+ systemd.services.sharkey = {
+ requires =
+ [
+ "redis-sharkey.service"
+ "network-online.target"
+ ]
+ ++ lib.optionals createDB ["postgresql.service"];
+
+ after =
+ [
+ "redis-sharkey.service"
+ "network-online.target"
+ ]
+ ++ lib.optionals createDB ["postgresql.service"];
+
+ wantedBy = ["multi-user.target"];
+
+ environment = {
+ MISSKEY_CONFIG_YML = "${configFile}";
+ NODE_ENV = "production";
+ };
+
+ serviceConfig = {
+ Type = "simple";
+
+ StateDirectory = "sharkey";
+ StateDirectoryMode = "0700";
+ CacheDirectory = "sharkey";
+ RuntimeDirectory = "sharkey";
+ RuntimeDirectoryMode = "0700";
+ ExecStart = "${lib.getExe cfg.package} migrateandstart";
+
+ TimeoutSec = 60;
+ Restart = "no";
+
+ StandardOutput = "journal";
+ StandardError = "journal";
+ SyslogIdentifier = "sharkey";
+
+ User = "sharkey";
+ Group = "sharkey";
+
+ # Bind standard privileged ports
+ AmbientCapabilities = [];
+ CapabilityBoundingSet = [];
+
+ ReadWritePaths = [
+ "${cfg.dataDirectory}"
+ ];
+
+ # Hardening
+ DeviceAllow = [""];
+ LockPersonality = true;
+ # Probably needed for v8's JIT (crashes with it on).
+ MemoryDenyWriteExecute = false;
+ PrivateDevices = true;
+ PrivateUsers = true;
+ ProcSubset = "pid";
+ PrivateTmp = true;
+ ProtectClock = true;
+ ProtectControlGroups = true;
+ ProtectHome = true;
+ ProtectHostname = true;
+ ProtectKernelLogs = true;
+ ProtectKernelModules = true;
+ ProtectKernelTunables = true;
+ ProtectProc = "invisible";
+ ProtectSystem = "strict";
+ RestrictAddressFamilies = [
+ "AF_UNIX" # Local communication unix(7)
+ "AF_INET" # IPv4 Internet protocols ip(7)
+ "AF_INET6" # IPv6 Internet protocols ipv6(7)
+ # Needed for nodes `os.networkInterfaces()` function.
+ "AF_NETLINK" # Kernel user interface device netlink(7)
+ ];
+ RestrictNamespaces = true;
+ RestrictRealtime = true;
+ RestrictSUIDSGID = true;
+ SystemCallArchitectures = "native";
+ SystemCallFilter = [
+ "@system-service"
+ "~@privileged"
+ "~@mount"
+ ];
+ UMask = "0077";
+ };
+ };
+
+ users = {
+ groups.sharkey = {
+ gid = config.vhack.constants.ids.gids.sharkey;
+ };
+ users.sharkey = {
+ isSystemUser = true;
+ group = "sharkey";
+ uid = config.vhack.constants.ids.uids.sharkey;
+ home = cfg.package;
+ packages = [cfg.package];
+ };
+
+ groups.redis-sharkey = {
+ gid = config.vhack.constants.ids.gids.redis-sharkey;
+ };
+ users.redis-sharkey = {
+ group = "redis-sharkey";
+ uid = config.vhack.constants.ids.uids.redis-sharkey;
+ };
+ };
+ };
+}
diff --git a/modules/by-name/st/stalwart-mail/module.nix b/modules/by-name/st/stalwart-mail/module.nix
index cc4acc9..396116d 100644
--- a/modules/by-name/st/stalwart-mail/module.nix
+++ b/modules/by-name/st/stalwart-mail/module.nix
@@ -10,6 +10,33 @@
configFormat = pkgs.formats.toml {};
configFile = configFormat.generate "stalwart-mail.toml" topCfg.settings;
+
+ hashedPassword = let
+ prefix = pre: lib.types.strMatching "^${lib.strings.escapeRegex pre}.*";
+ in
+ lib.types.oneOf [
+ (prefix "$argon2")
+ (prefix "$pbkdf2")
+ (prefix "$scrypt")
+ (prefix "$2") # bcrypt
+ (prefix "$6$") # sha-512
+ (prefix "$5$") # sha-256
+ (prefix "$sha1")
+ (prefix "$1") # md5
+ (prefix "_") # BSDi crypt
+ (prefix "{SHA}") # base64 sha
+ (prefix "{SSHA}") # base64 salted sha
+
+ # unix crypt
+ (prefix "{CRYPT}")
+ (prefix "{crypt}")
+
+ # Plain text
+ (prefix "{PLAIN}")
+ (prefix "{plain}")
+ (prefix "{CLEAR}")
+ (prefix "{clear}")
+ ];
in {
imports = [
./settings.nix
@@ -24,14 +51,20 @@ in {
description = ''
Email address to advertise as administrator. This is the address, where dkim, spv
etc. refusal reports are sent to.
-
- The format should be: `mailto:<name>@<domain>`
'';
type = lib.types.str;
- example = "mailto:dmarc+rua@example.com";
+ example = "dmarc+rua@example.com";
default = "";
};
+ initialAdminPassword = lib.mkOption {
+ type = hashedPassword;
+ description = ''
+ The hash of the password for the admin account, used to bootstrap account
+ creation.
+ '';
+ };
+
fqdn = lib.mkOption {
type = lib.types.str;
example = "mail.foss-syndicate.org";
@@ -61,32 +94,7 @@ in {
};
secret = lib.mkOption {
- type = let
- prefix = pre: lib.types.strMatching "^${lib.strings.escapeRegex pre}.*";
- in
- lib.types.oneOf [
- (prefix "$argon2")
- (prefix "$pbkdf2")
- (prefix "$scrypt")
- (prefix "$2") # bcrypt
- (prefix "$6$") # sha-512
- (prefix "$5$") # sha-256
- (prefix "$sha1")
- (prefix "$1") # md5
- (prefix "_") # BSDi crypt
- (prefix "{SHA}") # base64 sha
- (prefix "{SSHA}") # base64 salted sha
-
- # unix crypt
- (prefix "{CRYPT}")
- (prefix "{crypt}")
-
- # Plain text
- (prefix "{PLAIN}")
- (prefix "{plain}")
- (prefix "{CLEAR}")
- (prefix "{clear}")
- ];
+ type = hashedPassword;
description = ''
Sets the password for the user account.
Passwords can be stored hashed or in plain text (not recommended).
@@ -188,7 +196,11 @@ in {
};
nginx.virtualHosts."${cfg.fqdn}" = {
- locations."/".proxyPass = "http://${builtins.elemAt config.services.stalwart-mail.settings.server.listener.http.bind 0}";
+ locations."/" = {
+ proxyPass = "http://${builtins.elemAt config.services.stalwart-mail.settings.server.listener.http.bind 0}";
+ recommendedProxySettings = true;
+ };
+
useACMEHost = "${cfg.fqdn}";
forceSSL = true;
};
diff --git a/modules/by-name/st/stalwart-mail/settings.nix b/modules/by-name/st/stalwart-mail/settings.nix
index 907cea9..765d8db 100644
--- a/modules/by-name/st/stalwart-mail/settings.nix
+++ b/modules/by-name/st/stalwart-mail/settings.nix
@@ -100,7 +100,7 @@ in {
from-name = "'TLS Report'";
from-address = "'noreply-tls@${cfg.fqdn}'";
org-name = "'Foss Syndicate Mail Handling'";
- contact-info = "'${cfg.admin}'";
+ contact-info = "'mailto:${cfg.admin}'";
send = "daily";
max-size = 26214400; # 25 MiB
sign = lib.mkIf (cfg.security != null) "'${cfg.fqdn}'";
@@ -110,7 +110,7 @@ in {
from-name = "'DMARC Report'";
from-address = "'noreply-dmarc@${cfg.fqdn}'";
org-name = "'Foss Syndicate Mail Handling'";
- contact-info = "'${cfg.admin}'";
+ contact-info = "'mailto:${cfg.admin}'";
send = "weekly";
max-size = 26214400; # 25MiB
sign = lib.mkIf (cfg.security != null) "'${cfg.fqdn}'";
@@ -541,6 +541,11 @@ in {
};
};
+ authentication.fallback-admin = {
+ user = cfg.admin;
+ secret = cfg.initialAdminPassword;
+ };
+
certificate = {
"default" = {
cert = "%{file:${config.security.acme.certs.${cfg.fqdn}.directory}/fullchain.pem}%";
diff --git a/modules/by-name/ta/taskchampion-sync/module.nix b/modules/by-name/ta/taskchampion-sync/module.nix
index 2fa0a3f..1870186 100644
--- a/modules/by-name/ta/taskchampion-sync/module.nix
+++ b/modules/by-name/ta/taskchampion-sync/module.nix
@@ -4,6 +4,7 @@
...
}: let
cfg = config.vhack.taskchampion-sync;
+ dataDirectory = "/var/lib/taskchampion-sync-server";
in {
options.vhack.taskchampion-sync = {
enable = lib.mkEnableOption "taskchampion-sync";
@@ -16,13 +17,18 @@ in {
};
vhack.persist.directories = [
- "/var/lib/taskchampion-sync-server"
+ {
+ directory = dataDirectory;
+ user = "taskchampion";
+ group = "taskchampion";
+ mode = "0700";
+ }
];
services.taskchampion-sync-server = {
enable = true;
openFirewall = true;
- dataDir = "/var/lib/taskchampion-sync-server";
+ dataDir = dataDirectory;
};
};
}
diff --git a/pkgs/by-name/sh/sharkey/package.nix b/pkgs/by-name/sh/sharkey/package.nix
new file mode 100644
index 0000000..22261fa
--- /dev/null
+++ b/pkgs/by-name/sh/sharkey/package.nix
@@ -0,0 +1,4 @@
+{pkgsUnstable}:
+# NOTE(@bpeetz): The package was written for unstable, and I don't see a reason to migrate
+# it back, considering that 25.05 is right around the corner. <2025-04-22>
+pkgsUnstable.callPackage ./unstable_package.nix {}
diff --git a/pkgs/by-name/sh/sharkey/unstable_package.nix b/pkgs/by-name/sh/sharkey/unstable_package.nix
new file mode 100644
index 0000000..3922ca0
--- /dev/null
+++ b/pkgs/by-name/sh/sharkey/unstable_package.nix
@@ -0,0 +1,176 @@
+# Source: https://github.com/sodiboo/system/blob/b63c7b27f49043e8701b3ff5e1441cd27d5a2fff/sharkey/package.nix
+{
+ lib,
+ stdenv,
+ fetchFromGitLab,
+ # Build time
+ makeWrapper,
+ copyDesktopItems,
+ jq,
+ moreutils,
+ cacert,
+ python3,
+ pkg-config,
+ # Run time
+ bash,
+ jemalloc,
+ ffmpeg-headless,
+ nodejs,
+ pnpm_9,
+ glib,
+ vips,
+ pixman,
+ pango,
+ cairo,
+}:
+stdenv.mkDerivation (finalAttrs: {
+ pname = "sharkey";
+ version = "2025.2.2";
+
+ src = fetchFromGitLab {
+ owner = "TransFem-org";
+ repo = "Sharkey";
+ domain = "activitypub.software";
+ rev = finalAttrs.version;
+ hash = "sha256-KVr4KLtJ22LEk94GuxeTk8/GcFs7oU/gkoVTvrgbYBg=";
+ fetchSubmodules = true;
+ };
+
+ pnpmDeps = stdenv.mkDerivation {
+ pname = "${finalAttrs.pname}-pnpm-deps";
+ inherit (finalAttrs) src version;
+
+ nativeBuildInputs = [
+ jq
+ moreutils
+ pnpm_9
+ cacert
+ ];
+
+ # https://github.com/NixOS/nixpkgs/blob/763e59ffedb5c25774387bf99bc725df5df82d10/pkgs/applications/misc/pot/default.nix#L56
+ installPhase = ''
+ export HOME=$(mktemp --directory)
+
+ pnpm config set store-dir $out
+ pnpm config set side-effects-cache false
+ pnpm install --force --frozen-lockfile --ignore-scripts
+ '';
+
+ fixupPhase = ''
+ rm --recursive --force $out/v3/tmp
+ for f in $(find $out -name "*.json"); do
+ sed --in-place --regexp-extended --expression='s/"checkedAt":[0-9]+,//g' "$f"
+ jq --sort-keys . "$f" | sponge "$f"
+ done
+ '';
+
+ dontBuild = true;
+ outputHashMode = "recursive";
+ outputHash = "sha256-XWcDchvrYSJr0s/DMb8FIEK7MdE6aC2bAbrW88Ig4ug=";
+ };
+
+ nativeBuildInputs = [
+ copyDesktopItems
+ pnpm_9
+ nodejs
+ makeWrapper
+ python3
+ pkg-config
+ ];
+
+ buildInputs = [
+ glib
+ vips
+
+ pixman
+ pango
+ cairo
+ ];
+
+ configurePhase = ''
+ runHook preConfigure
+
+ export HOME=$(mktemp --directory)
+ export STORE_PATH=$(mktemp --directory)
+
+ export npm_config_nodedir=${nodejs}
+
+ cp --no-target-directory --recursive "$pnpmDeps" "$STORE_PATH"
+ chmod --recursive +w "$STORE_PATH"
+
+ pnpm config set store-dir "$STORE_PATH"
+ pnpm install --offline --frozen-lockfile --ignore-scripts
+
+ (
+ cd node_modules/.pnpm/node_modules/v-code-diff
+ pnpm run postinstall
+ )
+ (
+ cd node_modules/.pnpm/node_modules/re2
+ pnpm run rebuild
+ )
+ (
+ cd node_modules/.pnpm/node_modules/sharp
+ pnpm run install
+ )
+ (
+ cd node_modules/.pnpm/node_modules/canvas
+ pnpm run install
+ )
+
+ runHook postConfigure
+ '';
+
+ buildPhase = ''
+ runHook preBuild
+
+ pnpm build
+
+ runHook postBuild
+ '';
+
+ installPhase = let
+ libPath = lib.makeLibraryPath [
+ jemalloc
+ ffmpeg-headless
+ stdenv.cc.cc.lib
+ ];
+
+ binPath = lib.makeBinPath [
+ bash
+ pnpm_9
+ nodejs
+ ];
+ in
+ # bash
+ ''
+ runHook preInstall
+
+ mkdir --parents $out/Sharkey
+
+ ln --symbolic /var/lib/sharkey $out/Sharkey/files
+ ln --symbolic /run/sharkey $out/Sharkey/.config
+ cp --recursive * $out/Sharkey
+
+ # We cannot `--set` the PATH, because sharkey runs shellscripts at start (and maybe
+ # at other times), which need these things.
+ makeWrapper ${lib.getExe pnpm_9} $out/bin/sharkey \
+ --chdir $out/Sharkey \
+ --prefix PATH : ${binPath} \
+ --prefix LD_LIBRARY_PATH : ${libPath}
+
+ runHook postInstall
+ '';
+
+ passthru = {
+ inherit (finalAttrs) pnpmDeps;
+ };
+
+ meta = {
+ description = "🌎 A Sharkish microblogging platform 🚀";
+ homepage = "https://joinsharkey.org";
+ license = lib.licenses.gpl3Only;
+ platforms = ["x86_64-linux" "aarch64-linux"];
+ mainProgram = "sharkey";
+ };
+})
diff --git a/pkgs/by-name/st/stalwart-mail-free/package.nix b/pkgs/by-name/st/stalwart-mail-free/package.nix
index bb2c1db..19405c7 100644
--- a/pkgs/by-name/st/stalwart-mail-free/package.nix
+++ b/pkgs/by-name/st/stalwart-mail-free/package.nix
@@ -24,7 +24,7 @@ in
} "stalwart-mail passthru";
useFetchCargoVendor = true;
- cargoHash = "sha256-Qg01QXP/ImRCUw3aXcZbnM1hysHUwozCdQ7LecjUa0o=";
+ cargoHash = "sha256-FCRsmH9ZGYaf9ss3ECjZQkknIxAaDj9cedW32dWmBGY=";
# The tests should check if this works.
# And this shaves of around 50% of the build time.
@@ -40,7 +40,7 @@ in
(prev.postUnpack or "")
+ ''
cp --recursive "${mail-send}" ./source/crates/mail-send
- chmod -R +w "./source/crates/mail-send"
+ chmod --recursive +w "./source/crates/mail-send"
'';
cargoPatches =
diff --git a/tests/by-name/em/email-dns/nodes/mail_server.nix b/tests/by-name/em/email-dns/nodes/mail_server.nix
index 89dbc4a..279d289 100644
--- a/tests/by-name/em/email-dns/nodes/mail_server.nix
+++ b/tests/by-name/em/email-dns/nodes/mail_server.nix
@@ -14,6 +14,7 @@
++ [
../../../../../modules
../../../../common/acme/client.nix
+ ../../../../common/dns/client.nix
];
environment.systemPackages = [
@@ -21,11 +22,6 @@
pkgs.openssl
];
- networking.nameservers = lib.mkForce [
- nodes.name_server.networking.primaryIPAddress
- nodes.name_server.networking.primaryIPv6Address
- ];
-
age.identityPaths = ["${../../../../common/email/hostKey}"];
vhack = {
diff --git a/tests/by-name/em/email-dns/nodes/name_server.nix b/tests/by-name/em/email-dns/nodes/name_server.nix
index 48ce496..d9d3617 100644
--- a/tests/by-name/em/email-dns/nodes/name_server.nix
+++ b/tests/by-name/em/email-dns/nodes/name_server.nix
@@ -140,13 +140,9 @@ in {
++ [
../../../../../modules
../../../../common/acme/client.nix
+ ../../../../common/dns/server.nix
];
- networking.nameservers = lib.mkForce [
- nodes.name_server.networking.primaryIPAddress
- nodes.name_server.networking.primaryIPv6Address
- ];
-
services.nginx = {
logError = "stderr debug";
virtualHosts = let
@@ -175,145 +171,121 @@ in {
nginx = {
enable = true;
};
- dns = {
- enable = true;
- openFirewall = true;
- interfaces = [
- nodes.name_server.networking.primaryIPAddress
- nodes.name_server.networking.primaryIPv6Address
- ];
-
- zones = let
- stsZone = {
- SOA = {
- nameServer = "ns";
- adminEmail = "admin@server.com";
- serial = 2025012301;
- };
+ dns.zones = let
+ stsZone = {
+ SOA = {
+ nameServer = "ns";
+ adminEmail = "admin@server.com";
+ serial = 2025012301;
+ };
- useOrigin = false;
+ useOrigin = false;
- A = [
- nodes.name_server.networking.primaryIPAddress
- ];
- AAAA = [
- nodes.name_server.networking.primaryIPv6Address
- ];
+ A = [
+ nodes.name_server.networking.primaryIPAddress
+ ];
+ AAAA = [
+ nodes.name_server.networking.primaryIPv6Address
+ ];
+ };
+ in {
+ "arpa" = {
+ SOA = {
+ nameServer = "ns";
+ adminEmail = "admin@server.com";
+ serial = 2025012301;
};
- in {
- "arpa" = {
- SOA = {
- nameServer = "ns";
- adminEmail = "admin@server.com";
- serial = 2025012301;
- };
- useOrigin = false;
+ useOrigin = false;
- PTR = [
- {
- name = "acme.test";
- ip.v4 = nodes.acme.networking.primaryIPAddress;
- }
- {
- name = "acme.test";
- ip.v6 = nodes.acme.networking.primaryIPv6Address;
- }
+ PTR = [
+ {
+ name = "acme.test";
+ ip.v4 = nodes.acme.networking.primaryIPAddress;
+ }
+ {
+ name = "acme.test";
+ ip.v6 = nodes.acme.networking.primaryIPv6Address;
+ }
- {
- name = "alice.com";
- ip.v4 = nodes.alice.networking.primaryIPAddress;
- }
- {
- name = "alice.com";
- ip.v6 = nodes.alice.networking.primaryIPv6Address;
- }
+ {
+ name = "alice.com";
+ ip.v4 = nodes.alice.networking.primaryIPAddress;
+ }
+ {
+ name = "alice.com";
+ ip.v6 = nodes.alice.networking.primaryIPv6Address;
+ }
- {
- name = "bob";
- ip.v4 = nodes.bob.networking.primaryIPAddress;
- }
- {
- name = "bob";
- ip.v6 = nodes.bob.networking.primaryIPv6Address;
- }
+ {
+ name = "bob";
+ ip.v4 = nodes.bob.networking.primaryIPAddress;
+ }
+ {
+ name = "bob";
+ ip.v6 = nodes.bob.networking.primaryIPv6Address;
+ }
- {
- name = "mail1.server.com";
- ip.v4 = nodes.mail1_server.networking.primaryIPAddress;
- }
- {
- name = "mail1.server.com";
- ip.v6 = nodes.mail1_server.networking.primaryIPv6Address;
- }
+ {
+ name = "mail1.server.com";
+ ip.v4 = nodes.mail1_server.networking.primaryIPAddress;
+ }
+ {
+ name = "mail1.server.com";
+ ip.v6 = nodes.mail1_server.networking.primaryIPv6Address;
+ }
- {
- name = "mail2.server.com";
- ip.v4 = nodes.mail2_server.networking.primaryIPAddress;
- }
- {
- name = "mail2.server.com";
- ip.v6 = nodes.mail2_server.networking.primaryIPv6Address;
- }
+ {
+ name = "mail2.server.com";
+ ip.v4 = nodes.mail2_server.networking.primaryIPAddress;
+ }
+ {
+ name = "mail2.server.com";
+ ip.v6 = nodes.mail2_server.networking.primaryIPv6Address;
+ }
- {
- name = "ns.server.com";
- ip.v4 = nodes.name_server.networking.primaryIPAddress;
- }
- {
- name = "ns.server.com";
- ip.v6 = nodes.name_server.networking.primaryIPv6Address;
- }
- ];
- };
-
- "alice.com" = mkZone "alice" nodes lib nodes.mail2_server.vhack.stalwart-mail;
- "mta-sts.alice.com" = stsZone;
- "bob.com" = mkZone "bob" nodes lib nodes.mail1_server.vhack.stalwart-mail;
- "mta-sts.bob.com" = stsZone;
- "mail1.server.com" = mkServerZone "mail1" nodes lib;
- "mail2.server.com" = mkServerZone "mail2" nodes lib;
- "ns.server.com" = {
- SOA = {
- nameServer = "ns";
- adminEmail = "admin@server.com";
- serial = 2025012301;
- };
- useOrigin = false;
+ {
+ name = "ns.server.com";
+ ip.v4 = nodes.name_server.networking.primaryIPAddress;
+ }
+ {
+ name = "ns.server.com";
+ ip.v6 = nodes.name_server.networking.primaryIPv6Address;
+ }
+ ];
+ };
- A = [
- nodes.name_server.networking.primaryIPAddress
- ];
- AAAA = [
- nodes.name_server.networking.primaryIPv6Address
- ];
+ "alice.com" = mkZone "alice" nodes lib nodes.mail2_server.vhack.stalwart-mail;
+ "mta-sts.alice.com" = stsZone;
+ "bob.com" = mkZone "bob" nodes lib nodes.mail1_server.vhack.stalwart-mail;
+ "mta-sts.bob.com" = stsZone;
+ "mail1.server.com" = mkServerZone "mail1" nodes lib;
+ "mail2.server.com" = mkServerZone "mail2" nodes lib;
+ "ns.server.com" = {
+ SOA = {
+ nameServer = "ns";
+ adminEmail = "admin@server.com";
+ serial = 2025012301;
};
- "acme.test" = {
- SOA = {
- nameServer = "ns";
- adminEmail = "admin@server.com";
- serial = 2025012301;
- };
- useOrigin = false;
+ useOrigin = false;
- A = [
- nodes.acme.networking.primaryIPAddress
- ];
- AAAA = [
- nodes.acme.networking.primaryIPv6Address
- ];
+ A = [
+ nodes.name_server.networking.primaryIPAddress
+ ];
+ AAAA = [
+ nodes.name_server.networking.primaryIPv6Address
+ ];
+ };
+ "server.com" = {
+ SOA = {
+ nameServer = "ns";
+ adminEmail = "admin@server.com";
+ serial = 2025012301;
};
- "server.com" = {
- SOA = {
- nameServer = "ns";
- adminEmail = "admin@server.com";
- serial = 2025012301;
- };
- useOrigin = false;
- NS = [
- "ns.server.com."
- ];
- };
+ useOrigin = false;
+ NS = [
+ "ns.server.com."
+ ];
};
};
};
diff --git a/tests/by-name/em/email-dns/nodes/user.nix b/tests/by-name/em/email-dns/nodes/user.nix
index 55a4609..fba02ce 100644
--- a/tests/by-name/em/email-dns/nodes/user.nix
+++ b/tests/by-name/em/email-dns/nodes/user.nix
@@ -9,6 +9,7 @@
}: {
imports = [
../../../../common/acme/client.nix
+ ../../../../common/dns/client.nix
];
environment.systemPackages = [
@@ -20,11 +21,6 @@
pkgs.openssl
];
- networking.nameservers = lib.mkForce [
- nodes.name_server.networking.primaryIPAddress
- nodes.name_server.networking.primaryIPv6Address
- ];
-
users.users."${user}" = {isNormalUser = true;};
systemd.tmpfiles.rules = [
diff --git a/tests/by-name/em/email-dns/test.nix b/tests/by-name/em/email-dns/test.nix
index 0e4d9a0..f0399a5 100644
--- a/tests/by-name/em/email-dns/test.nix
+++ b/tests/by-name/em/email-dns/test.nix
@@ -31,9 +31,9 @@ in
lib,
...
}: {
- imports = [../../../common/acme];
- networking.nameservers = lib.mkForce [
- nodes.name_server.networking.primaryIPAddress
+ imports = [
+ ../../../common/acme/server.nix
+ ../../../common/dns/client.nix
];
};
@@ -89,7 +89,8 @@ in
exit 1
}
'';
- inherit (pkgs) lib;
+
+ acme_scripts = import ../../../common/acme/scripts.nix {inherit pkgs;};
in
/*
python
@@ -121,30 +122,7 @@ in
with subtest("Add pebble ca key to all services"):
for node in [name_server, mail1_server, mail2_server, alice, bob]:
- node.succeed("${pkgs.writeShellScript "fetch-and-set-ca" ''
- set -xe
-
- # Fetch the randomly generated ca certificate
- curl https://acme.test:15000/roots/0 > /tmp/ca.crt
- curl https://acme.test:15000/intermediates/0 >> /tmp/ca.crt
-
- # Append it to the various system stores
- # The file paths are from <nixpgks>/modules/security/ca.nix
- for cert_path in "ssl/certs/ca-certificates.crt" "ssl/certs/ca-bundle.crt" "pki/tls/certs/ca-bundle.crt"; do
- cert_path="/etc/$cert_path"
-
- mv "$cert_path" "$cert_path.old"
- cat "$cert_path.old" > "$cert_path"
- cat /tmp/ca.crt >> "$cert_path"
- done
-
- export NIX_SSL_CERT_FILE=/tmp/ca.crt
- export SSL_CERT_FILE=/tmp/ca.crt
-
- # TODO
- # # P11-Kit trust source.
- # environment.etc."ssl/trust-source".source = "$${cacertPackage.p11kit}/etc/ssl/trust-source";
- ''}")
+ node.succeed("${acme_scripts.add_pebble_acme_ca}")
with subtest("Both mailserver successfully started all services"):
import json
diff --git a/tests/by-name/em/email-http/nodes/name_server.nix b/tests/by-name/em/email-http/nodes/name_server.nix
deleted file mode 100644
index a7e3ce9..0000000
--- a/tests/by-name/em/email-http/nodes/name_server.nix
+++ /dev/null
@@ -1,210 +0,0 @@
-{extraModules}: {
- config,
- lib,
- nodes,
- pkgs,
- ...
-}: let
- keyAlgoToKeyType = keyAlgo:
- if keyAlgo == "ed25519-sha256"
- then "ed25519"
- else if keyAlgo == "rsa-sha-256" || keyAlgo == "rsa-sha-1"
- then "rsa"
- else builtins.throw "Impossible";
-
- mkZone = user: nodes: lib: cfg: {
- SOA = {
- nameServer = "ns.server.com";
- adminEmail = "${user}@${user}.com";
- serial = 2024012301;
- };
-
- MX = [
- {
- preference = 10;
- exchange = "${cfg.fqdn}.";
- }
- ];
-
- # https://www.rfc-editor.org/rfc/rfc8461.html#section-3.1
- # Also see the policy in the hmtl part.
- MTA-STS = [
- {
- id = "20250228Z";
- }
- ];
-
- # https://www.rfc-editor.org/rfc/rfc7208.html
- # https://en.wikipedia.org/wiki/Sender_Policy_Framework
- TXT = [
- (builtins.concatStringsSep " "
- [
- "v=spf1" # The version.
- "+mx" # Allow mail from this domain MX record.
- "-all" # Reject all other emails if the previous mechanism did not match.
- ])
- ];
-
- # https://www.rfc-editor.org/rfc/rfc6376.html#section-3.6.1
- # https://www.rfc-editor.org/rfc/rfc6376.html#section-7.5
- DKIM = [
- {
- selector = "mail";
- k = keyAlgoToKeyType cfg.security.dkimKeys."${user}.com".keyAlgorithm;
- p = cfg.security.dkimKeys."${user}.com".dkimPublicKey;
- s = ["email"];
- t = ["s"];
- }
- ];
-
- # https://www.rfc-editor.org/rfc/rfc7489.html#section-6.3
- DMARC = [
- {
- adkim = "strict";
- aspf = "strict";
- fo = ["0" "1" "d" "s"];
- p = "quarantine";
- rua = cfg.admin;
- ruf = [cfg.admin];
- }
- ];
-
- A = [
- nodes.${user}.networking.primaryIPAddress
- ];
- AAAA = [
- nodes.${user}.networking.primaryIPv6Address
- ];
- };
- mkServerZone = serverName: nodes: lib: let
- cfg = nodes."${serverName}_server".vhack.stalwart-mail;
- in {
- SOA = {
- nameServer = "ns.server.com";
- adminEmail = "admin@server.com";
- serial = 2024012301;
- };
- MX = [
- {
- preference = 10;
- exchange = "${serverName}.server.com.";
- }
- ];
-
- # https://www.rfc-editor.org/rfc/rfc6376.html#section-3.6.1
- # https://www.rfc-editor.org/rfc/rfc6376.html#section-7.5
- DKIM = [
- {
- selector = "mail";
- k = keyAlgoToKeyType cfg.security.dkimKeys."${serverName}.server.com".keyAlgorithm;
- p = cfg.security.dkimKeys."${serverName}.server.com".dkimPublicKey;
- s = ["email"];
- t = ["s"];
- }
- ];
-
- # https://www.rfc-editor.org/rfc/rfc7489.html#section-6.3
- DMARC = [
- {
- adkim = "strict";
- aspf = "strict";
- fo = ["0" "1" "d" "s"];
- p = "reject";
- rua = cfg.admin;
- ruf = [cfg.admin];
- }
- ];
-
- # https://www.rfc-editor.org/rfc/rfc7208.html
- # NOTE(@bpeetz): This server might not be directly sending mail, but it is still required for
- # the SMTP EHLO check. <2025-02-25>
- TXT = [
- (builtins.concatStringsSep " "
- [
- "v=spf1" # The version.
- "+mx" # Allow mail from this domain MX record.
- "-all" # Reject all other emails if the previous mechanism did not match.
- ])
- ];
-
- A = [
- nodes."${serverName}_server".networking.primaryIPAddress
- ];
- AAAA = [
- nodes."${serverName}_server".networking.primaryIPv6Address
- ];
- };
-in {
- imports =
- extraModules
- ++ [
- ../../../../../modules
- ../../../../common/acme/client.nix
- ];
-
- networking.nameservers = lib.mkForce [
- nodes.name_server.networking.primaryIPAddress
- nodes.name_server.networking.primaryIPv6Address
- ];
-
- vhack = {
- nginx = {
- enable = true;
- };
- dns = {
- enable = true;
- openFirewall = true;
- interfaces = [
- nodes.name_server.networking.primaryIPAddress
- nodes.name_server.networking.primaryIPv6Address
- ];
-
- zones = {
- "bob.com" = mkZone "bob" nodes lib nodes.mail_server.vhack.stalwart-mail;
- "mail.server.com" = mkServerZone "mail" nodes lib;
- "ns.server.com" = {
- SOA = {
- nameServer = "ns";
- adminEmail = "admin@server.com";
- serial = 2025012301;
- };
- useOrigin = false;
-
- A = [
- nodes.name_server.networking.primaryIPAddress
- ];
- AAAA = [
- nodes.name_server.networking.primaryIPv6Address
- ];
- };
- "acme.test" = {
- SOA = {
- nameServer = "ns";
- adminEmail = "admin@server.com";
- serial = 2025012301;
- };
- useOrigin = false;
-
- A = [
- nodes.acme.networking.primaryIPAddress
- ];
- AAAA = [
- nodes.acme.networking.primaryIPv6Address
- ];
- };
- "server.com" = {
- SOA = {
- nameServer = "ns";
- adminEmail = "admin@server.com";
- serial = 2025012301;
- };
-
- useOrigin = false;
- NS = [
- "ns.server.com."
- ];
- };
- };
- };
- };
-}
diff --git a/tests/by-name/em/email-http/test.nix b/tests/by-name/em/email-http/test.nix
index 2c7921d..f508b9f 100644
--- a/tests/by-name/em/email-http/test.nix
+++ b/tests/by-name/em/email-http/test.nix
@@ -31,13 +31,38 @@ in
lib,
...
}: {
- imports = [../../../common/acme];
- networking.nameservers = lib.mkForce [
- nodes.name_server.networking.primaryIPAddress
+ imports = [
+ ../../../common/acme/server.nix
+ ../../../common/dns/client.nix
];
};
- name_server = import ./nodes/name_server.nix {inherit extraModules;};
+ name_server = {nodes, ...}: {
+ imports =
+ extraModules
+ ++ [
+ ../../../common/acme/client.nix
+ ../../../common/dns/server.nix
+ ];
+
+ vhack.dns.zones = {
+ "mail.server.com" = {
+ SOA = {
+ nameServer = "ns";
+ adminEmail = "admin@server.com";
+ serial = 2025012301;
+ };
+ useOrigin = false;
+
+ A = [
+ nodes.mail_server.networking.primaryIPAddress
+ ];
+ AAAA = [
+ nodes.mail_server.networking.primaryIPv6Address
+ ];
+ };
+ };
+ };
mail_server = mkMailServer "mail" null;
@@ -45,66 +70,46 @@ in
};
# TODO(@bpeetz): This test should also test the http JMAP features of stalwart-mail. <2025-04-12>
- testScript = _:
- /*
- python
- */
- ''
- # Start dependencies for the other services
- acme.start()
- acme.wait_for_unit("pebble.service")
- name_server.start()
- name_server.wait_for_unit("nsd.service")
-
- # Start the actual testing machines
- start_all()
-
- mail_server.wait_for_unit("stalwart-mail.service")
- mail_server.wait_for_open_port(993) # imap
- mail_server.wait_for_open_port(465) # smtp
-
- bob.wait_for_unit("multi-user.target")
-
- with subtest("Add pebble ca key to all services"):
- for node in [name_server, mail_server, bob]:
- node.succeed("${pkgs.writeShellScript "fetch-and-set-ca" ''
- set -xe
-
- # Fetch the randomly generated ca certificate
- curl https://acme.test:15000/roots/0 > /tmp/ca.crt
- curl https://acme.test:15000/intermediates/0 >> /tmp/ca.crt
+ testScript = _: let
+ acme_scripts = import ../../../common/acme/scripts.nix {inherit pkgs;};
+ in
+ /*
+ python
+ */
+ ''
+ # Start dependencies for the other services
+ acme.start()
+ acme.wait_for_unit("pebble.service")
+ name_server.start()
+ name_server.wait_for_unit("nsd.service")
- # Append it to the various system stores
- # The file paths are from <nixpgks>/modules/security/ca.nix
- for cert_path in "ssl/certs/ca-certificates.crt" "ssl/certs/ca-bundle.crt" "pki/tls/certs/ca-bundle.crt"; do
- cert_path="/etc/$cert_path"
+ # Start the actual testing machines
+ start_all()
- mv "$cert_path" "$cert_path.old"
- cat "$cert_path.old" > "$cert_path"
- cat /tmp/ca.crt >> "$cert_path"
- done
+ mail_server.wait_for_unit("stalwart-mail.service")
+ mail_server.wait_for_open_port(993) # imap
+ mail_server.wait_for_open_port(465) # smtp
- export NIX_SSL_CERT_FILE=/tmp/ca.crt
- export SSL_CERT_FILE=/tmp/ca.crt
+ bob.wait_for_unit("multi-user.target")
- # TODO
- # # P11-Kit trust source.
- # environment.etc."ssl/trust-source".source = "$${cacertPackage.p11kit}/etc/ssl/trust-source";
- ''}")
+ with subtest("Add pebble ca key to all services"):
+ for node in [name_server, mail_server, bob]:
+ node.wait_for_unit("network-online.target")
+ node.succeed("${acme_scripts.add_pebble_acme_ca}")
- with subtest("The mailserver successfully started all services"):
- import json
- def all_services_running(host):
- (status, output) = host.systemctl("list-units --state=failed --plain --no-pager --output=json")
- host_failed = json.loads(output)
- assert len(host_failed) == 0, f"Expected zero failing services, but found: {json.dumps(host_failed, indent=4)}"
- all_services_running(mail_server)
+ with subtest("The mailserver successfully started all services"):
+ import json
+ def all_services_running(host):
+ (status, output) = host.systemctl("list-units --state=failed --plain --no-pager --output=json")
+ host_failed = json.loads(output)
+ assert len(host_failed) == 0, f"Expected zero failing services, but found: {json.dumps(host_failed, indent=4)}"
+ all_services_running(mail_server)
- with subtest("Bob can use the self-service interface"):
- bob.succeed("${pkgs.writeShellScript "check-self-service" ''
- curl mail.server.com --location --output /home/bob/output.html;
- ''}")
+ with subtest("Bob can use the self-service interface"):
+ bob.succeed("${pkgs.writeShellScript "check-self-service" ''
+ curl mail.server.com --location --output /home/bob/output.html;
+ ''}")
- bob.copy_from_vm("/home/bob", "")
- '';
+ bob.copy_from_vm("/home/bob", "")
+ '';
}
diff --git a/tests/by-name/sh/sharkey/test.nix b/tests/by-name/sh/sharkey/test.nix
new file mode 100644
index 0000000..40efe17
--- /dev/null
+++ b/tests/by-name/sh/sharkey/test.nix
@@ -0,0 +1,118 @@
+{
+ nixos-lib,
+ pkgsUnstable,
+ nixpkgs-unstable,
+ vhackPackages,
+ pkgs,
+ extraModules,
+ nixLib,
+ ...
+}:
+nixos-lib.runTest {
+ hostPkgs = pkgs; # the Nixpkgs package set used outside the VMs
+
+ name = "sharkey";
+
+ node = {
+ specialArgs = {inherit pkgsUnstable extraModules vhackPackages nixpkgs-unstable nixLib;};
+
+ # Use the nixpkgs as constructed by the `nixpkgs.*` options
+ pkgs = null;
+ };
+
+ nodes = {
+ acme = {...}: {
+ imports = [
+ ../../../common/acme/server.nix
+ ../../../common/dns/client.nix
+ ];
+ };
+ name_server = {nodes, ...}: {
+ imports =
+ extraModules
+ ++ [
+ ../../../common/acme/client.nix
+ ../../../common/dns/server.nix
+ ];
+
+ vhack.dns.zones = {
+ "sharkey.server" = {
+ SOA = {
+ nameServer = "ns";
+ adminEmail = "admin@server.com";
+ serial = 2025012301;
+ };
+ useOrigin = false;
+
+ A = [
+ nodes.server.networking.primaryIPAddress
+ ];
+ AAAA = [
+ nodes.server.networking.primaryIPv6Address
+ ];
+ };
+ };
+ };
+
+ server = {config, ...}: {
+ imports =
+ extraModules
+ ++ [
+ ../../../../modules
+ ../../../common/acme/client.nix
+ ../../../common/dns/client.nix
+ ];
+
+ vhack = {
+ persist.enable = true;
+ nginx.enable = true;
+ sharkey = {
+ enable = true;
+ fqdn = "sharkey.server";
+ };
+ };
+ };
+
+ client = {...}: {
+ imports = [
+ ../../../common/acme/client.nix
+ ../../../common/dns/client.nix
+ ];
+ };
+ };
+
+ testScript = {nodes, ...}: let
+ acme_scripts = import ../../../common/acme/scripts.nix {inherit pkgs;};
+ in
+ /*
+ python
+ */
+ ''
+ # Start dependencies for the other services
+ acme.start()
+ acme.wait_for_unit("pebble.service")
+ name_server.start()
+ name_server.wait_for_unit("nsd.service")
+
+ # Start the actual testing machines
+ start_all()
+
+
+ with subtest("Add pebble ca key to all services"):
+ for node in [name_server, server, client]:
+ node.wait_for_unit("network-online.target")
+ node.succeed("${acme_scripts.add_pebble_acme_ca}")
+
+ server.wait_for_unit("sharkey.service")
+
+ with subtest("All services running"):
+ import json
+ def all_services_running(host):
+ (status, output) = host.systemctl("list-units --state=failed --plain --no-pager --output=json")
+ host_failed = json.loads(output)
+ assert len(host_failed) == 0, f"Expected zero failing services, but found: {json.dumps(host_failed, indent=4)}"
+ all_services_running(server)
+
+ client.wait_until_succeeds("curl --silent https://sharkey.server | grep 'Thank you for using Sharkey!'")
+ '';
+}
diff --git a/tests/common/acme/scripts.nix b/tests/common/acme/scripts.nix
new file mode 100644
index 0000000..2228823
--- /dev/null
+++ b/tests/common/acme/scripts.nix
@@ -0,0 +1,30 @@
+{pkgs}:
+/*
+* Extra functions useful for the test script.
+*/
+{
+ add_pebble_acme_ca = pkgs.writeShellScript "fetch-and-set-ca" ''
+ set -xe
+
+ # Fetch the randomly generated ca certificate
+ curl https://acme.test:15000/roots/0 > /tmp/ca.crt
+ curl https://acme.test:15000/intermediates/0 >> /tmp/ca.crt
+
+ # Append it to the various system stores
+ # The file paths are from <nixpgks>/modules/security/ca.nix
+ for cert_path in "ssl/certs/ca-certificates.crt" "ssl/certs/ca-bundle.crt" "pki/tls/certs/ca-bundle.crt"; do
+ cert_path="/etc/$cert_path"
+
+ mv "$cert_path" "$cert_path.old"
+ cat "$cert_path.old" > "$cert_path"
+ cat /tmp/ca.crt >> "$cert_path"
+ done
+
+ export NIX_SSL_CERT_FILE=/tmp/ca.crt
+ export SSL_CERT_FILE=/tmp/ca.crt
+
+ # TODO
+ # # P11-Kit trust source.
+ # environment.etc."ssl/trust-source".source = "$${cacertPackage.p11kit}/etc/ssl/trust-source";
+ '';
+}
diff --git a/tests/common/acme/default.nix b/tests/common/acme/server.nix
index 236ba6a..997c944 100644
--- a/tests/common/acme/default.nix
+++ b/tests/common/acme/server.nix
@@ -1,28 +1,5 @@
-# The certificate for the ACME service is exported as:
-#
-# config.test-support.acme.caCert
-#
-# This value can be used inside the configuration of other test nodes to inject
-# the test certificate into security.pki.certificateFiles or into package
-# overlays.
-#
-# {
-# acme = { nodes, lib, ... }: {
-# imports = [ ./common/acme/server ];
-# networking.nameservers = lib.mkForce [
-# nodes.mydnsresolver.networking.primaryIPAddress
-# ];
-# };
-#
-# dnsmyresolver = ...;
-# }
-#
-# Keep in mind, that currently only _one_ resolver is supported, if you have
-# more than one resolver in networking.nameservers only the first one will be
-# used.
-#
-# Also make sure that whenever you use a resolver from a different test node
-# that it has to be started _before_ the ACME service.
+# Add this node as acme server.
+# This also needs a DNS server.
{
config,
pkgs,
diff --git a/tests/common/dns/client.nix b/tests/common/dns/client.nix
new file mode 100644
index 0000000..52f3267
--- /dev/null
+++ b/tests/common/dns/client.nix
@@ -0,0 +1,10 @@
+{
+ lib,
+ nodes,
+ ...
+}: {
+ networking.nameservers = lib.mkForce [
+ nodes.name_server.networking.primaryIPAddress
+ nodes.name_server.networking.primaryIPv6Address
+ ];
+}
diff --git a/tests/common/dns/server.nix b/tests/common/dns/server.nix
new file mode 100644
index 0000000..0c8d72c
--- /dev/null
+++ b/tests/common/dns/server.nix
@@ -0,0 +1,43 @@
+{
+ lib,
+ nodes,
+ ...
+}: {
+ imports = [
+ ../../../modules
+ ];
+
+ networking.nameservers = lib.mkForce [
+ nodes.name_server.networking.primaryIPAddress
+ nodes.name_server.networking.primaryIPv6Address
+ ];
+
+ vhack = {
+ dns = {
+ enable = true;
+ openFirewall = true;
+ interfaces = [
+ nodes.name_server.networking.primaryIPAddress
+ nodes.name_server.networking.primaryIPv6Address
+ ];
+
+ zones = {
+ "acme.test" = {
+ SOA = {
+ nameServer = "ns";
+ adminEmail = "admin@server.com";
+ serial = 2025012301;
+ };
+ useOrigin = false;
+
+ A = [
+ nodes.acme.networking.primaryIPAddress
+ ];
+ AAAA = [
+ nodes.acme.networking.primaryIPv6Address
+ ];
+ };
+ };
+ };
+ };
+}
diff --git a/update.sh b/update.sh
index c43b80b..e22f4ea 100755
--- a/update.sh
+++ b/update.sh
@@ -3,12 +3,13 @@ __update_sh_run() {
__update_sh_command="$1"
shift 1
- printf "\033[35;1m> \033[0m\033[35;1m%s\033[0m\n" "Running '$(basename "$__update_sh_command")' .."
+ printf "\033[35;1m> \033[0m\033[35;1m%s\033[0m\n" "Running '$(basename "$__update_sh_command") $*' .."
"$__update_sh_command" "$@"
unset __update_sh_command
}
+__update_sh_run nix flake update
__update_sh_run ./pkgs/update_pkgs.sh "$@"
# vim: ft=sh
diff --git a/zones/vhack.eu/zone.nix b/zones/vhack.eu/zone.nix
index d647174..696d1df 100644
--- a/zones/vhack.eu/zone.nix
+++ b/zones/vhack.eu/zone.nix
@@ -38,7 +38,7 @@ in {
adminEmail = "dns-admin@foss-syndicate.org";
# NOTE(@bpeetz): ALWAYS change the serial number, when you change something in the
# zone file! <2025-04-01>
- serial = mkSerial 2025 04 11 01;
+ serial = mkSerial 2025 04 23 01;
};
useOrigin = false;
@@ -157,6 +157,7 @@ in {
redlib.CNAME = ["server2.vhack.eu."];
nextcloud.CNAME = ["server2.vhack.eu."];
+ sharkey.CNAME = ["server2.vhack.eu."];
mastodon.CNAME = ["server3.vhack.eu."];
matrix.CNAME = ["server3.vhack.eu."];