1{ config, pkgs, lib, ... }:
2
3with lib;
4let
5 cfg = config.services.zeyple;
6 ini = pkgs.formats.ini { };
7
8 gpgHome = pkgs.runCommand "zeyple-gpg-home" { } ''
9 mkdir -p $out
10 for file in ${lib.concatStringsSep " " cfg.keys}; do
11 ${config.programs.gnupg.package}/bin/gpg --homedir="$out" --import "$file"
12 done
13
14 # Remove socket files
15 rm -f $out/S.*
16 '';
17in {
18 options.services.zeyple = {
19 enable = mkEnableOption (lib.mdDoc "Zeyple, an utility program to automatically encrypt outgoing emails with GPG");
20
21 user = mkOption {
22 type = types.str;
23 default = "zeyple";
24 description = lib.mdDoc ''
25 User to run Zeyple as.
26
27 ::: {.note}
28 If left as the default value this user will automatically be created
29 on system activation, otherwise the sysadmin is responsible for
30 ensuring the user exists.
31 :::
32 '';
33 };
34
35 group = mkOption {
36 type = types.str;
37 default = "zeyple";
38 description = lib.mdDoc ''
39 Group to use to run Zeyple.
40
41 ::: {.note}
42 If left as the default value this group will automatically be created
43 on system activation, otherwise the sysadmin is responsible for
44 ensuring the user exists.
45 :::
46 '';
47 };
48
49 settings = mkOption {
50 type = ini.type;
51 default = { };
52 description = lib.mdDoc ''
53 Zeyple configuration. refer to
54 <https://github.com/infertux/zeyple/blob/master/zeyple/zeyple.conf.example>
55 for details on supported values.
56 '';
57 };
58
59 keys = mkOption {
60 type = with types; listOf path;
61 description = lib.mdDoc "List of public key files that will be imported by gpg.";
62 };
63
64 rotateLogs = mkOption {
65 type = types.bool;
66 default = true;
67 description = lib.mdDoc "Whether to enable rotation of log files.";
68 };
69 };
70
71 config = mkIf cfg.enable {
72 users.groups = optionalAttrs (cfg.group == "zeyple") { "${cfg.group}" = { }; };
73 users.users = optionalAttrs (cfg.user == "zeyple") {
74 "${cfg.user}" = {
75 isSystemUser = true;
76 group = cfg.group;
77 };
78 };
79
80 services.zeyple.settings = {
81 zeyple = mapAttrs (name: mkDefault) {
82 log_file = "/var/log/zeyple/zeyple.log";
83 force_encrypt = true;
84 };
85
86 gpg = mapAttrs (name: mkDefault) { home = "${gpgHome}"; };
87
88 relay = mapAttrs (name: mkDefault) {
89 host = "localhost";
90 port = 10026;
91 };
92 };
93
94 environment.etc."zeyple.conf".source = ini.generate "zeyple.conf" cfg.settings;
95
96 systemd.tmpfiles.rules = [ "f '${cfg.settings.zeyple.log_file}' 0600 ${cfg.user} ${cfg.group} - -" ];
97 services.logrotate = mkIf cfg.rotateLogs {
98 enable = true;
99 settings.zeyple = {
100 files = cfg.settings.zeyple.log_file;
101 frequency = "weekly";
102 rotate = 5;
103 compress = true;
104 copytruncate = true;
105 };
106 };
107
108 services.postfix.extraMasterConf = ''
109 zeyple unix - n n - - pipe
110 user=${cfg.user} argv=${pkgs.zeyple}/bin/zeyple ''${recipient}
111
112 localhost:${toString cfg.settings.relay.port} inet n - n - 10 smtpd
113 -o content_filter=
114 -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks,no_milters
115 -o smtpd_helo_restrictions=
116 -o smtpd_client_restrictions=
117 -o smtpd_sender_restrictions=
118 -o smtpd_recipient_restrictions=permit_mynetworks,reject
119 -o mynetworks=127.0.0.0/8,[::1]/128
120 -o smtpd_authorized_xforward_hosts=127.0.0.0/8,[::1]/128
121 '';
122
123 services.postfix.extraConfig = "content_filter = zeyple";
124 };
125}