1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6
7 cfg = config.services.postsrsd;
8
9in {
10
11 ###### interface
12
13 options = {
14
15 services.postsrsd = {
16
17 enable = mkOption {
18 type = types.bool;
19 default = false;
20 description = lib.mdDoc "Whether to enable the postsrsd SRS server for Postfix.";
21 };
22
23 secretsFile = mkOption {
24 type = types.path;
25 default = "/var/lib/postsrsd/postsrsd.secret";
26 description = lib.mdDoc "Secret keys used for signing and verification";
27 };
28
29 domain = mkOption {
30 type = types.str;
31 description = lib.mdDoc "Domain name for rewrite";
32 };
33
34 separator = mkOption {
35 type = types.enum ["-" "=" "+"];
36 default = "=";
37 description = lib.mdDoc "First separator character in generated addresses";
38 };
39
40 # bindAddress = mkOption { # uncomment once 1.5 is released
41 # type = types.str;
42 # default = "127.0.0.1";
43 # description = "Socket listen address";
44 # };
45
46 forwardPort = mkOption {
47 type = types.int;
48 default = 10001;
49 description = lib.mdDoc "Port for the forward SRS lookup";
50 };
51
52 reversePort = mkOption {
53 type = types.int;
54 default = 10002;
55 description = lib.mdDoc "Port for the reverse SRS lookup";
56 };
57
58 timeout = mkOption {
59 type = types.int;
60 default = 1800;
61 description = lib.mdDoc "Timeout for idle client connections in seconds";
62 };
63
64 excludeDomains = mkOption {
65 type = types.listOf types.str;
66 default = [];
67 description = lib.mdDoc "Origin domains to exclude from rewriting in addition to primary domain";
68 };
69
70 user = mkOption {
71 type = types.str;
72 default = "postsrsd";
73 description = lib.mdDoc "User for the daemon";
74 };
75
76 group = mkOption {
77 type = types.str;
78 default = "postsrsd";
79 description = lib.mdDoc "Group for the daemon";
80 };
81
82 };
83
84 };
85
86
87 ###### implementation
88
89 config = mkIf cfg.enable {
90
91 services.postsrsd.domain = mkDefault config.networking.hostName;
92
93 users.users = optionalAttrs (cfg.user == "postsrsd") {
94 postsrsd = {
95 group = cfg.group;
96 uid = config.ids.uids.postsrsd;
97 };
98 };
99
100 users.groups = optionalAttrs (cfg.group == "postsrsd") {
101 postsrsd.gid = config.ids.gids.postsrsd;
102 };
103
104 systemd.services.postsrsd = {
105 description = "PostSRSd SRS rewriting server";
106 after = [ "network.target" ];
107 before = [ "postfix.service" ];
108 wantedBy = [ "multi-user.target" ];
109
110 path = [ pkgs.coreutils ];
111
112 serviceConfig = {
113 ExecStart = ''${pkgs.postsrsd}/sbin/postsrsd "-s${cfg.secretsFile}" "-d${cfg.domain}" -a${cfg.separator} -f${toString cfg.forwardPort} -r${toString cfg.reversePort} -t${toString cfg.timeout} "-X${concatStringsSep "," cfg.excludeDomains}"'';
114 User = cfg.user;
115 Group = cfg.group;
116 PermissionsStartOnly = true;
117 };
118
119 preStart = ''
120 if [ ! -e "${cfg.secretsFile}" ]; then
121 echo "WARNING: secrets file not found, autogenerating!"
122 DIR="$(dirname "${cfg.secretsFile}")"
123 if [ ! -d "$DIR" ]; then
124 mkdir -p -m750 "$DIR"
125 chown "${cfg.user}:${cfg.group}" "$DIR"
126 fi
127 dd if=/dev/random bs=18 count=1 | base64 > "${cfg.secretsFile}"
128 chmod 600 "${cfg.secretsFile}"
129 fi
130 chown "${cfg.user}:${cfg.group}" "${cfg.secretsFile}"
131 '';
132 };
133
134 };
135}