at 25.11-pre 6.8 kB view raw
1{ 2 config, 3 pkgs, 4 lib, 5 ... 6}: 7let 8 cfg = config.services.schleuder; 9 settingsFormat = pkgs.formats.yaml { }; 10 postfixMap = 11 entries: lib.concatStringsSep "\n" (lib.mapAttrsToList (name: value: "${name} ${value}") entries); 12 writePostfixMap = name: entries: pkgs.writeText name (postfixMap entries); 13 configScript = pkgs.writeScript "schleuder-cfg" '' 14 #!${pkgs.runtimeShell} 15 set -exuo pipefail 16 umask 0077 17 ${pkgs.yq}/bin/yq \ 18 --slurpfile overrides <(${pkgs.yq}/bin/yq . <${lib.escapeShellArg cfg.extraSettingsFile}) \ 19 < ${settingsFormat.generate "schleuder.yml" cfg.settings} \ 20 '. * $overrides[0]' \ 21 > /etc/schleuder/schleuder.yml 22 chown schleuder: /etc/schleuder/schleuder.yml 23 ''; 24in 25{ 26 options.services.schleuder = { 27 enable = lib.mkEnableOption "Schleuder secure remailer"; 28 enablePostfix = lib.mkEnableOption "automatic postfix integration" // { 29 default = true; 30 }; 31 lists = lib.mkOption { 32 description = '' 33 List of list addresses that should be handled by Schleuder. 34 35 Note that this is only handled by the postfix integration, and 36 the setup of the lists, their members and their keys has to be 37 performed separately via schleuder's API, using a tool such as 38 schleuder-cli. 39 ''; 40 type = lib.types.listOf lib.types.str; 41 default = [ ]; 42 example = [ 43 "widget-team@example.com" 44 "security@example.com" 45 ]; 46 }; 47 /* 48 maybe one day.... 49 domains = lib.mkOption { 50 description = "Domains for which all mail should be handled by Schleuder."; 51 type = lib.types.listOf lib.types.str; 52 default = []; 53 example = ["securelists.example.com"]; 54 }; 55 */ 56 settings = lib.mkOption { 57 description = '' 58 Settings for schleuder.yml. 59 60 Check the [example configuration](https://0xacab.org/schleuder/schleuder/blob/master/etc/schleuder.yml) for possible values. 61 ''; 62 type = lib.types.submodule { 63 freeformType = settingsFormat.type; 64 options.keyserver = lib.mkOption { 65 type = lib.types.str; 66 description = '' 67 Key server from which to fetch and update keys. 68 69 Note that NixOS uses a different default from upstream, since the upstream default sks-keyservers.net is deprecated. 70 ''; 71 default = "keys.openpgp.org"; 72 }; 73 }; 74 default = { }; 75 }; 76 extraSettingsFile = lib.mkOption { 77 description = "YAML file to merge into the schleuder config at runtime. This can be used for secrets such as API keys."; 78 type = lib.types.nullOr lib.types.path; 79 default = null; 80 }; 81 listDefaults = lib.mkOption { 82 description = '' 83 Default settings for lists (list-defaults.yml). 84 85 Check the [example configuration](https://0xacab.org/schleuder/schleuder/-/blob/master/etc/list-defaults.yml) for possible values. 86 ''; 87 type = settingsFormat.type; 88 default = { }; 89 }; 90 }; 91 config = lib.mkIf cfg.enable { 92 assertions = [ 93 { 94 assertion = !(cfg.settings.api ? valid_api_keys); 95 message = '' 96 services.schleuder.settings.api.valid_api_keys is set. Defining API keys via NixOS config results in them being copied to the world-readable Nix store. Please use the extraSettingsFile option to store API keys in a non-public location. 97 ''; 98 } 99 { 100 assertion = !(lib.any (db: db ? password) (lib.attrValues cfg.settings.database or { })); 101 message = '' 102 A password is defined for at least one database in services.schleuder.settings.database. Defining passwords via NixOS config results in them being copied to the world-readable Nix store. Please use the extraSettingsFile option to store database passwords in a non-public location. 103 ''; 104 } 105 ]; 106 users.users.schleuder.isSystemUser = true; 107 users.users.schleuder.group = "schleuder"; 108 users.groups.schleuder = { }; 109 environment.systemPackages = [ 110 pkgs.schleuder-cli 111 ]; 112 services.postfix = lib.mkIf cfg.enablePostfix { 113 extraMasterConf = '' 114 schleuder unix - n n - - pipe 115 flags=DRhu user=schleuder argv=/${pkgs.schleuder}/bin/schleuder work ''${recipient} 116 ''; 117 transport = lib.mkIf (cfg.lists != [ ]) (postfixMap (lib.genAttrs cfg.lists (_: "schleuder:"))); 118 extraConfig = '' 119 schleuder_destination_recipient_limit = 1 120 ''; 121 # review: does this make sense? 122 localRecipients = lib.mkIf (cfg.lists != [ ]) cfg.lists; 123 }; 124 systemd.services = 125 let 126 commonServiceConfig = { 127 # We would have liked to use DynamicUser, but since the default 128 # database is SQLite and lives in StateDirectory, and that same 129 # database needs to be readable from the postfix service, this 130 # isn't trivial to do. 131 User = "schleuder"; 132 StateDirectory = "schleuder"; 133 StateDirectoryMode = "0700"; 134 }; 135 in 136 { 137 schleuder-init = { 138 serviceConfig = commonServiceConfig // { 139 ExecStartPre = lib.mkIf (cfg.extraSettingsFile != null) [ 140 "+${configScript}" 141 ]; 142 ExecStart = [ "${pkgs.schleuder}/bin/schleuder install" ]; 143 Type = "oneshot"; 144 }; 145 }; 146 schleuder-api-daemon = { 147 after = [ 148 "local-fs.target" 149 "network.target" 150 "schleuder-init.service" 151 ]; 152 wantedBy = [ "multi-user.target" ]; 153 requires = [ "schleuder-init.service" ]; 154 serviceConfig = commonServiceConfig // { 155 ExecStart = [ "${pkgs.schleuder}/bin/schleuder-api-daemon" ]; 156 }; 157 }; 158 schleuder-weekly-key-maintenance = { 159 after = [ 160 "local-fs.target" 161 "network.target" 162 ]; 163 startAt = "weekly"; 164 serviceConfig = commonServiceConfig // { 165 ExecStart = [ 166 "${pkgs.schleuder}/bin/schleuder refresh_keys" 167 "${pkgs.schleuder}/bin/schleuder check_keys" 168 ]; 169 }; 170 }; 171 }; 172 173 environment.etc."schleuder/schleuder.yml" = lib.mkIf (cfg.extraSettingsFile == null) { 174 source = settingsFormat.generate "schleuder.yml" cfg.settings; 175 }; 176 environment.etc."schleuder/list-defaults.yml".source = 177 settingsFormat.generate "list-defaults.yml" cfg.listDefaults; 178 179 services.schleuder = { 180 #lists_dir = "/var/lib/schleuder.lists"; 181 settings.filters_dir = lib.mkDefault "/var/lib/schleuder/filters"; 182 settings.keyword_handlers_dir = lib.mkDefault "/var/lib/schleuder/keyword_handlers"; 183 }; 184 }; 185}