diff --git a/checks/deltachat/default.nix b/checks/deltachat/default.nix index afd376845..0183e13a3 100644 --- a/checks/deltachat/default.nix +++ b/checks/deltachat/default.nix @@ -1,28 +1,50 @@ -(import ../lib/container-test.nix) ( - { pkgs, ... }: +{ + pkgs, + nixosLib, + clan-core, + ... +}: +nixosLib.runTest ( + { ... }: { + imports = [ + clan-core.modules.nixosVmTest.clanTest + ]; + + hostPkgs = pkgs; + name = "deltachat"; - nodes.machine = - { self, ... }: - { - imports = [ - self.clanModules.deltachat - self.nixosModules.clanCore - { - clan.core.settings.directory = ./.; - } - ]; + clan = { + directory = ./.; + modules."@clan/deltachat" = ../../clanServices/deltachat/default.nix; + inventory = { + machines.server = { }; + + instances = { + deltachat-test = { + module.name = "@clan/deltachat"; + roles.default.machines."server".settings = { }; + }; + }; }; + }; + + nodes = { + server = { }; + }; + testScript = '' start_all() - machine.wait_for_unit("maddy") + + server.wait_for_unit("maddy") + # imap - machine.succeed("${pkgs.netcat}/bin/nc -z -v ::1 143") + server.succeed("${pkgs.netcat}/bin/nc -z -v ::1 143") # smtp submission - machine.succeed("${pkgs.netcat}/bin/nc -z -v ::1 587") + server.succeed("${pkgs.netcat}/bin/nc -z -v ::1 587") # smtp - machine.succeed("${pkgs.netcat}/bin/nc -z -v ::1 25") + server.succeed("${pkgs.netcat}/bin/nc -z -v ::1 25") ''; } ) diff --git a/checks/deltachat/sops/users/admin/key.json b/checks/deltachat/sops/users/admin/key.json new file mode 100644 index 000000000..e408aa96b --- /dev/null +++ b/checks/deltachat/sops/users/admin/key.json @@ -0,0 +1,4 @@ +{ + "publickey": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg", + "type": "age" +} diff --git a/checks/flake-module.nix b/checks/flake-module.nix index 622cbf60f..66ebb0ab3 100644 --- a/checks/flake-module.nix +++ b/checks/flake-module.nix @@ -38,8 +38,8 @@ in }; nixosTests = lib.optionalAttrs (pkgs.stdenv.isLinux) { - # Deltachat is currently marked as broken - # deltachat = import ./deltachat nixosTestArgs; + # Deltachat test + deltachat = import ./deltachat nixosTestArgs; # Base Tests secrets = self.clanLib.test.baseTest ./secrets nixosTestArgs; diff --git a/clanModules/deltachat/README.md b/clanModules/deltachat/README.md index 1315011fd..e3822c310 100644 --- a/clanModules/deltachat/README.md +++ b/clanModules/deltachat/README.md @@ -1,5 +1,7 @@ --- description = "Email-based instant messaging for Desktop." +categories = ["Social"] +features = [ "inventory", "deprecated" ] --- !!! info diff --git a/clanModules/deltachat/default.nix b/clanModules/deltachat/roles/default.nix similarity index 100% rename from clanModules/deltachat/default.nix rename to clanModules/deltachat/roles/default.nix diff --git a/clanServices/deltachat/default.nix b/clanServices/deltachat/default.nix new file mode 100644 index 000000000..ef8506f78 --- /dev/null +++ b/clanServices/deltachat/default.nix @@ -0,0 +1,164 @@ +{ ... }: +{ + _class = "clan.service"; + manifest.name = "clan-core/deltachat"; + manifest.description = "Email-based instant messaging for Desktop"; + manifest.categories = [ "Social" ]; + + roles.default = { + interface = + { ... }: + { + options = { }; + }; + + perInstance = + { settings, ... }: + { + nixosModule = + { config, pkgs, ... }: + { + networking.firewall.interfaces."zt+".allowedTCPPorts = [ 25 ]; # smtp with other hosts + environment.systemPackages = [ pkgs.deltachat-desktop ]; + + services.maddy = + let + domain = "${config.clan.core.settings.machine.name}.local"; + in + { + enable = true; + primaryDomain = domain; + config = '' + # Minimal configuration with TLS disabled, adapted from upstream example + # configuration here https://github.com/foxcpp/maddy/blob/master/maddy.conf + # Do not use this in unencrypted networks! + + auth.pass_table local_authdb { + table sql_table { + driver sqlite3 + dsn credentials.db + table_name passwords + } + } + + storage.imapsql local_mailboxes { + driver sqlite3 + dsn imapsql.db + } + + table.chain local_rewrites { + optional_step regexp "(.+)\+(.+)@(.+)" "$1@$3" + optional_step static { + entry postmaster postmaster@$(primary_domain) + } + optional_step file /etc/maddy/aliases + } + + msgpipeline local_routing { + destination postmaster $(local_domains) { + modify { + replace_rcpt &local_rewrites + } + deliver_to &local_mailboxes + } + default_destination { + reject 550 5.1.1 "User doesn't exist" + } + } + + smtp tcp://[::]:25 { + limits { + all rate 20 1s + all concurrency 10 + } + dmarc yes + check { + require_mx_record + dkim + spf + } + source $(local_domains) { + reject 501 5.1.8 "Use Submission for outgoing SMTP" + } + default_source { + destination postmaster $(local_domains) { + deliver_to &local_routing + } + default_destination { + reject 550 5.1.1 "User doesn't exist" + } + } + } + + submission tcp://[::1]:587 { + limits { + all rate 50 1s + } + auth &local_authdb + source $(local_domains) { + check { + authorize_sender { + prepare_email &local_rewrites + user_to_email identity + } + } + destination postmaster $(local_domains) { + deliver_to &local_routing + } + default_destination { + modify { + dkim $(primary_domain) $(local_domains) default + } + deliver_to &remote_queue + } + } + default_source { + reject 501 5.1.8 "Non-local sender domain" + } + } + + target.remote outbound_delivery { + limits { + destination rate 20 1s + destination concurrency 10 + } + mx_auth { + dane + mtasts { + cache fs + fs_dir mtasts_cache/ + } + local_policy { + min_tls_level encrypted + min_mx_level none + } + } + } + + target.queue remote_queue { + target &outbound_delivery + autogenerated_msg_domain $(primary_domain) + bounce { + destination postmaster $(local_domains) { + deliver_to &local_routing + } + default_destination { + reject 550 5.0.0 "Refusing to send DSNs to non-local addresses" + } + } + } + + imap tcp://[::1]:143 { + auth &local_authdb + storage &local_mailboxes + } + ''; + ensureAccounts = [ "user@${domain}" ]; + ensureCredentials = { + "user@${domain}".passwordFile = pkgs.writeText "dummy" "foobar"; + }; + }; + }; + }; + }; +} diff --git a/clanServices/deltachat/flake-module.nix b/clanServices/deltachat/flake-module.nix new file mode 100644 index 000000000..7cd0e8295 --- /dev/null +++ b/clanServices/deltachat/flake-module.nix @@ -0,0 +1,6 @@ +{ lib, ... }: +{ + clan.modules = { + deltachat = lib.modules.importApply ./default.nix { }; + }; +} diff --git a/clanServices/flake-module.nix b/clanServices/flake-module.nix index f430446d8..e00a8c5a1 100644 --- a/clanServices/flake-module.nix +++ b/clanServices/flake-module.nix @@ -2,6 +2,7 @@ { imports = [ ./admin/flake-module.nix + ./deltachat/flake-module.nix ./hello-world/flake-module.nix ./wifi/flake-module.nix ./borgbackup/flake-module.nix diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 72f5db72f..f9d515f6e 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -84,6 +84,7 @@ nav: - Overview: reference/clanServices/index.md - reference/clanServices/admin.md - reference/clanServices/borgbackup.md + - reference/clanServices/deltachat.md - reference/clanServices/hello-world.md - reference/clanServices/wifi.md - Clan Modules: diff --git a/lib/clanTest/flake-module.nix b/lib/clanTest/flake-module.nix index 11f784fbf..9446647aa 100644 --- a/lib/clanTest/flake-module.nix +++ b/lib/clanTest/flake-module.nix @@ -73,10 +73,12 @@ in ${self.legacyPackages.${hostPkgs.system}.setupNixInNix} cp -r ${testSrc} ./src chmod +w -R ./src + mkdir -p ./src/sops ./src/vars # create dirs case the test has no vars find ./src/sops ./src/vars | sort > filesBefore ${update-vars-script} ./src ${testName} \ --repo-root ${self.packages.${hostPkgs.system}.clan-core-flake} \ --clean + mkdir -p ./src/sops ./src/vars find ./src/sops ./src/vars | sort > filesAfter if ! diff -q filesBefore filesAfter; then echo "The update-vars script changed the files in ${testSrc}."