summary refs log tree commit diff
path: root/nixos/modules/services/mail
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules/services/mail')
-rw-r--r--nixos/modules/services/mail/dovecot.nix168
-rw-r--r--nixos/modules/services/mail/freepops.nix87
-rw-r--r--nixos/modules/services/mail/mail.nix33
-rw-r--r--nixos/modules/services/mail/opensmtpd.nix83
-rw-r--r--nixos/modules/services/mail/postfix.nix405
-rw-r--r--nixos/modules/services/mail/spamassassin.nix64
6 files changed, 840 insertions, 0 deletions
diff --git a/nixos/modules/services/mail/dovecot.nix b/nixos/modules/services/mail/dovecot.nix
new file mode 100644
index 00000000000..5f8e8e1ade3
--- /dev/null
+++ b/nixos/modules/services/mail/dovecot.nix
@@ -0,0 +1,168 @@
+{ config, pkgs, ... }:
+
+with pkgs.lib;
+
+let
+
+  cfg = config.services.dovecot2;
+
+  dovecotConf =
+    ''
+      base_dir = /var/run/dovecot2/
+
+      protocols = ${optionalString cfg.enableImap "imap"} ${optionalString cfg.enablePop3 "pop3"}
+    ''
+    + (if cfg.sslServerCert!="" then
+    ''
+      ssl_cert = <${cfg.sslServerCert}
+      ssl_key = <${cfg.sslServerKey}
+      ssl_ca = <${cfg.sslCACert}
+      disable_plaintext_auth = yes
+    '' else ''
+      ssl = no
+      disable_plaintext_auth = no
+    '')
+
+    + ''
+      default_internal_user = ${cfg.user}
+
+      mail_location = ${cfg.mailLocation}
+
+      maildir_copy_with_hardlinks = yes
+
+      auth_mechanisms = plain login
+      service auth {
+        user = root
+      }
+      userdb {
+        driver = passwd
+      }
+      passdb {
+        driver = pam
+        args = ${optionalString cfg.showPAMFailure "failure_show_msg=yes"} dovecot2
+      }
+
+      pop3_uidl_format = %08Xv%08Xu
+    '' + cfg.extraConfig;
+
+  confFile = pkgs.writeText "dovecot.conf" dovecotConf;
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.dovecot2 = {
+
+      enable = mkOption {
+        default = false;
+        description = "Whether to enable the Dovecot 2.x POP3/IMAP server.";
+      };
+
+      enablePop3 = mkOption {
+        default = true;
+        description = "Start the POP3 listener (when Dovecot is enabled).";
+      };
+
+      enableImap = mkOption {
+        default = true;
+        description = "Start the IMAP listener (when Dovecot is enabled).";
+      };
+
+      user = mkOption {
+        default = "dovecot2";
+        description = "Dovecot user name.";
+      };
+
+      group = mkOption {
+        default = "dovecot2";
+        description = "Dovecot group name.";
+      };
+
+      extraConfig = mkOption {
+        default = "";
+        example = "mail_debug = yes";
+        description = "Additional entries to put verbatim into Dovecot's config file.";
+      };
+
+      mailLocation = mkOption {
+        default = "maildir:/var/spool/mail/%u"; /* Same as inbox, as postfix */
+        example = "maildir:~/mail:INBOX=/var/spool/mail/%u";
+        description = ''
+          Location that dovecot will use for mail folders. Dovecot mail_location option.
+        '';
+      };
+
+      sslServerCert = mkOption {
+        default = "";
+        description = "Server certificate";
+      };
+
+      sslCACert = mkOption {
+        default = "";
+        description = "CA certificate used by the server certificate.";
+      };
+
+      sslServerKey = mkOption {
+        default = "";
+        description = "Server key.";
+      };
+
+      showPAMFailure = mkOption {
+        default = false;
+        description = "Show the PAM failure message on authentication error (useful for OTPW).";
+      };
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf config.services.dovecot2.enable {
+
+    security.pam.services = [ { name = "dovecot2"; } ];
+
+    users.extraUsers = [
+      { name = cfg.user;
+        uid = config.ids.uids.dovecot2;
+        description = "Dovecot user";
+        group = cfg.group;
+      }
+      { name = "dovenull";
+        uid = config.ids.uids.dovenull2;
+        description = "Dovecot user for untrusted logins";
+        group = cfg.group;
+      }
+    ];
+
+    users.extraGroups = singleton
+      { name = cfg.group;
+        gid = config.ids.gids.dovecot2;
+      };
+
+    jobs.dovecot2 =
+      { description = "Dovecot IMAP/POP3 server";
+
+        startOn = "started networking";
+
+        preStart =
+          ''
+            ${pkgs.coreutils}/bin/mkdir -p /var/run/dovecot2 /var/run/dovecot2/login
+            ${pkgs.coreutils}/bin/chown -R ${cfg.user}:${cfg.group} /var/run/dovecot2
+          '';
+
+        exec = "${pkgs.dovecot}/sbin/dovecot -F -c ${confFile}";
+      };
+
+    environment.systemPackages = [ pkgs.dovecot ];
+
+    assertions = [{ assertion = cfg.enablePop3 || cfg.enableImap;
+                    message = "dovecot needs at least one of the IMAP or POP3 listeners enabled";}];
+
+  };
+
+}
diff --git a/nixos/modules/services/mail/freepops.nix b/nixos/modules/services/mail/freepops.nix
new file mode 100644
index 00000000000..8f6e9382607
--- /dev/null
+++ b/nixos/modules/services/mail/freepops.nix
@@ -0,0 +1,87 @@
+{config, pkgs, ...}:
+
+with pkgs.lib;
+
+let
+  cfg = config.services.mail.freepopsd;
+in
+
+{
+  options = {
+    services.mail.freepopsd = {
+      enable = mkOption {
+        default = false;
+        type = with types; bool;
+        description = ''
+          Enables Freepops, a POP3 webmail wrapper.
+        '';
+      };
+
+      port = mkOption {
+        default = 2000;
+        type = with types; uniq int;
+        description = ''
+          Port on which the pop server will listen.
+        '';
+      };
+
+      threads = mkOption {
+        default = 5;
+        type = with types; uniq int;
+        description = ''
+          Max simultaneous connections.
+        '';
+      };
+
+      bind = mkOption {
+        default = "0.0.0.0";
+        type = with types; uniq string;
+        description = ''
+          Bind over an IPv4 address instead of any.
+        '';
+      };
+
+      logFile = mkOption {
+        default = "/var/log/freepopsd";
+        example = "syslog";
+        type = with types; uniq string;
+        description = ''
+          Filename of the log file or syslog to rely on the logging daemon.
+        '';
+      };
+
+      suid = {
+        user = mkOption {
+          default = "nobody";
+          type = with types; uniq string;
+          description = ''
+            User name under which freepopsd will be after binding the port.
+          '';
+        };
+
+        group = mkOption {
+          default = "nogroup";
+          type = with types; uniq string;
+          description = ''
+            Group under which freepopsd will be after binding the port.
+          '';
+        };
+      };
+
+    };
+  };
+
+  config = mkIf cfg.enable {
+    jobs.freepopsd = {
+      description = "Freepopsd (webmail over POP3)";
+      startOn = "ip-up";
+      exec = ''${pkgs.freepops}/bin/freepopsd \
+        -p ${toString cfg.port} \
+        -t ${toString cfg.threads} \
+        -b ${cfg.bind} \
+        -vv -l ${cfg.logFile} \
+        -s ${cfg.suid.user}.${cfg.suid.group}
+      '';
+    };
+  };
+}
diff --git a/nixos/modules/services/mail/mail.nix b/nixos/modules/services/mail/mail.nix
new file mode 100644
index 00000000000..bad0b22625d
--- /dev/null
+++ b/nixos/modules/services/mail/mail.nix
@@ -0,0 +1,33 @@
+{ config, pkgs, ... }:
+
+with pkgs.lib;
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.mail = {
+
+      sendmailSetuidWrapper = mkOption {
+        default = null;
+        description = ''
+          Configuration for the sendmail setuid wrwapper (like an element of
+          security.setuidOwners)";
+        '';
+      };
+
+    };
+
+  };
+
+  ###### implementation
+
+  config = mkIf (config.services.mail.sendmailSetuidWrapper != null) {
+
+    security.setuidOwners = [ config.services.mail.sendmailSetuidWrapper ];
+
+  };
+
+}
diff --git a/nixos/modules/services/mail/opensmtpd.nix b/nixos/modules/services/mail/opensmtpd.nix
new file mode 100644
index 00000000000..2732fd60200
--- /dev/null
+++ b/nixos/modules/services/mail/opensmtpd.nix
@@ -0,0 +1,83 @@
+{ pkgs, config, ... }:
+
+with pkgs;
+with pkgs.lib;
+
+let
+
+  cfg = config.services.opensmtpd;
+  conf = writeText "smtpd.conf" cfg.serverConfiguration;
+  args = concatStringsSep " " cfg.extraServerArgs;
+
+in {
+
+  ###### interface
+
+  options = {
+
+    services.opensmtpd = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Whether to enable the OpenSMTPD server.";
+      };
+
+      extraServerArgs = mkOption {
+        type = types.listOf types.string;
+        default = [];
+        example = [ "-v" "-P mta" ];
+        description = ''
+          Extra command line arguments provided when the smtpd process
+          is started.
+        '';
+      };
+
+      serverConfiguration = mkOption {
+        type = types.string;
+        default = "";
+        example = ''
+          listen on lo
+          accept for any deliver to lmtp localhost:24
+        ''; 
+        description = ''
+          The contents of the smtpd.conf configuration file. See the
+          OpenSMTPD documentation for syntax information. If this option
+          is left empty, the OpenSMTPD server will not start.
+        '';
+      };
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf config.services.opensmtpd.enable {
+    users.extraGroups = {
+      smtpd.gid = config.ids.gids.smtpd;
+      smtpq.gid = config.ids.gids.smtpq;
+    };
+
+    users.extraUsers = {
+      smtpd = {
+        description = "OpenSMTPD process user";
+        uid = config.ids.uids.smtpd;
+        group = "smtpd";
+      };
+      smtpq = {
+        description = "OpenSMTPD queue user";
+        uid = config.ids.uids.smtpq;
+        group = "smtpq";
+      };
+    };
+
+    systemd.services.opensmtpd = {
+      wantedBy = [ "multi-user.target" ];
+      wants = [ "network.target" ];
+      after = [ "network.target" ];
+      preStart = "mkdir -p /var/spool";
+      serviceConfig.ExecStart = "${opensmtpd}/sbin/smtpd -d -f ${conf} ${args}";
+    };
+  };
+}
diff --git a/nixos/modules/services/mail/postfix.nix b/nixos/modules/services/mail/postfix.nix
new file mode 100644
index 00000000000..2633289b46d
--- /dev/null
+++ b/nixos/modules/services/mail/postfix.nix
@@ -0,0 +1,405 @@
+{ config, pkgs, ... }:
+
+with pkgs.lib;
+
+let
+
+  cfg = config.services.postfix;
+  user = cfg.user;
+  group = cfg.group;
+  setgidGroup = cfg.setgidGroup;
+
+  mainCf =
+    ''
+      queue_directory = /var/postfix/queue
+      command_directory = ${pkgs.postfix}/sbin
+      daemon_directory = ${pkgs.postfix}/libexec/postfix
+
+      mail_owner = ${user}
+      default_privs = nobody
+
+    ''
+    + optionalString config.networking.enableIPv6 ''
+      inet_protocols = all
+    ''
+    + (if cfg.networks != null then
+        ''
+          mynetworks = ${concatStringsSep ", " cfg.networks}
+        ''
+      else if cfg.networksStyle != "" then
+        ''
+          mynetworks_style = ${cfg.networksStyle}
+        ''
+      else
+        # Postfix default is subnet, but let's play safe
+        ''
+          mynetworks_style = host
+        '')
+    + optionalString (cfg.hostname != "") ''
+      myhostname = ${cfg.hostname}
+    ''
+    + optionalString (cfg.domain != "") ''
+      mydomain = ${cfg.domain}
+    ''
+    + optionalString (cfg.origin != "") ''
+      myorigin = ${cfg.origin}
+    ''
+    + optionalString (cfg.destination != null) ''
+      mydestination = ${concatStringsSep ", " cfg.destination}
+    ''
+    + optionalString (cfg.relayDomains != null) ''
+      relay_domains = ${concatStringsSep ", " cfg.relayDomains}
+    ''
+    + ''
+      local_recipient_maps =
+
+      relayhost = ${if cfg.lookupMX || cfg.relayHost == "" then
+          cfg.relayHost
+        else
+          "[" + cfg.relayHost + "]"}
+
+      alias_maps = hash:/var/postfix/conf/aliases
+
+      mail_spool_directory = /var/spool/mail/
+
+      setgid_group = ${setgidGroup}
+    ''
+    + optionalString (cfg.sslCert != "") ''
+
+      smtp_tls_CAfile = ${cfg.sslCACert}
+      smtp_tls_cert_file = ${cfg.sslCert}
+      smtp_tls_key_file = ${cfg.sslKey}
+
+      smtp_use_tls = yes
+
+      smtpd_tls_CAfile = ${cfg.sslCACert}
+      smtpd_tls_cert_file = ${cfg.sslCert}
+      smtpd_tls_key_file = ${cfg.sslKey}
+
+      smtpd_use_tls = yes
+
+      recipientDelimiter = ${cfg.recipientDelimiter}
+    ''
+    + optionalString (cfg.virtual != "") ''
+      virtual_alias_maps = hash:/etc/postfix/virtual
+    ''
+    + cfg.extraConfig;
+
+  masterCf = ''
+    # ==========================================================================
+    # service type  private unpriv  chroot  wakeup  maxproc command + args
+    #               (yes)   (yes)   (yes)   (never) (100)
+    # ==========================================================================
+    smtp      inet  n       -       n       -       -       smtpd
+    #submission inet n       -       n       -       -       smtpd
+    #  -o smtpd_tls_security_level=encrypt
+    #  -o smtpd_sasl_auth_enable=yes
+    #  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
+    #  -o milter_macro_daemon_name=ORIGINATING
+    pickup    fifo  n       -       n       60      1       pickup
+    cleanup   unix  n       -       n       -       0       cleanup
+    qmgr      fifo  n       -       n       300     1       qmgr
+    tlsmgr    unix  -       -       n       1000?   1       tlsmgr
+    rewrite   unix  -       -       n       -       -       trivial-rewrite
+    bounce    unix  -       -       n       -       0       bounce
+    defer     unix  -       -       n       -       0       bounce
+    trace     unix  -       -       n       -       0       bounce
+    verify    unix  -       -       n       -       1       verify
+    flush     unix  n       -       n       1000?   0       flush
+    proxymap  unix  -       -       n       -       -       proxymap
+    proxywrite unix -       -       n       -       1       proxymap
+    smtp      unix  -       -       n       -       -       smtp
+    relay     unix  -       -       n       -       -       smtp
+    	      -o smtp_fallback_relay=
+    #       -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
+    showq     unix  n       -       n       -       -       showq
+    error     unix  -       -       n       -       -       error
+    retry     unix  -       -       n       -       -       error
+    discard   unix  -       -       n       -       -       discard
+    local     unix  -       n       n       -       -       local
+    virtual   unix  -       n       n       -       -       virtual
+    lmtp      unix  -       -       n       -       -       lmtp
+    anvil     unix  -       -       n       -       1       anvil
+    scache    unix  -       -       n       -       1       scache
+    ${cfg.extraMasterConf}
+  '';
+
+  aliases =
+    optionalString (cfg.postmasterAlias != "") ''
+      postmaster: ${cfg.postmasterAlias}
+    ''
+    + optionalString (cfg.rootAlias != "") ''
+      root: ${cfg.rootAlias}
+    ''
+    + cfg.extraAliases
+  ;
+
+  aliasesFile = pkgs.writeText "postfix-aliases" aliases;
+  virtualFile = pkgs.writeText "postfix-virtual" cfg.virtual;
+  mainCfFile = pkgs.writeText "postfix-main.cf" mainCf;
+  masterCfFile = pkgs.writeText "postfix-master.cf" masterCf;
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.postfix = {
+
+      enable = mkOption {
+        default = false;
+        description = "Whether to run the Postfix mail server.";
+      };
+
+      setSendmail = mkOption {
+        default = true;
+        description = "Whether to set the system sendmail to postfix's.";
+      };
+
+      user = mkOption {
+        default = "postfix";
+        description = "What to call the Postfix user (must be used only for postfix).";
+      };
+
+      group = mkOption {
+        default = "postfix";
+        description = "What to call the Postfix group (must be used only for postfix).";
+      };
+
+      setgidGroup = mkOption {
+        default = "postdrop";
+        description = "
+          How to call postfix setgid group (for postdrop). Should
+          be uniquely used group.
+        ";
+      };
+
+      networks = mkOption {
+        default = null;
+        example = ["192.168.0.1/24"];
+        description = "
+          Net masks for trusted - allowed to relay mail to third parties -
+          hosts. Leave empty to use mynetworks_style configuration or use
+          default (localhost-only).
+        ";
+      };
+
+      networksStyle = mkOption {
+        default = "";
+        description = "
+          Name of standard way of trusted network specification to use,
+          leave blank if you specify it explicitly or if you want to use
+          default (localhost-only).
+        ";
+      };
+
+      hostname = mkOption {
+        default = "";
+        description ="
+          Hostname to use. Leave blank to use just the hostname of machine.
+          It should be FQDN.
+        ";
+      };
+
+      domain = mkOption {
+        default = "";
+        description ="
+          Domain to use. Leave blank to use hostname minus first component.
+        ";
+      };
+
+      origin = mkOption {
+        default = "";
+        description ="
+          Origin to use in outgoing e-mail. Leave blank to use hostname.
+        ";
+      };
+
+      destination = mkOption {
+        default = null;
+        example = ["localhost"];
+        description = "
+          Full (!) list of domains we deliver locally. Leave blank for
+          acceptable Postfix default.
+        ";
+      };
+
+      relayDomains = mkOption {
+        default = null;
+        example = ["localdomain"];
+        description = "
+          List of domains we agree to relay to. Default is the same as
+          destination.
+        ";
+      };
+
+      relayHost = mkOption {
+        default = "";
+        description = "
+          Mail relay for outbound mail.
+        ";
+      };
+
+      lookupMX = mkOption {
+        default = false;
+        description = "
+          Whether relay specified is just domain whose MX must be used.
+        ";
+      };
+
+      postmasterAlias = mkOption {
+        default = "root";
+        description = "Who should receive postmaster e-mail.";
+      };
+
+      rootAlias = mkOption {
+        default = "";
+        description = "
+          Who should receive root e-mail. Blank for no redirection.
+        ";
+      };
+
+      extraAliases = mkOption {
+        default = "";
+        description = "
+          Additional entries to put verbatim into aliases file.
+        ";
+      };
+
+      extraConfig = mkOption {
+        default = "";
+        description = "
+          Extra lines to be added verbatim to the main.cf configuration file.
+        ";
+      };
+
+      sslCert = mkOption {
+        default = "";
+        description = "SSL certificate to use.";
+      };
+
+      sslCACert = mkOption {
+        default = "";
+        description = "SSL certificate of CA.";
+      };
+
+      sslKey = mkOption {
+        default = "";
+        description = "SSL key to use.";
+      };
+
+      recipientDelimiter = mkOption {
+        default = "";
+        example = "+";
+        description = "
+          Delimiter for address extension: so mail to user+test can be handled by ~user/.forward+test
+        ";
+      };
+
+      virtual = mkOption {
+        default = "";
+        description = "
+          Entries for the virtual alias map.
+        ";
+      };
+
+      extraMasterConf = mkOption {
+        default = "";
+        example = "submission inet n - n - - smtpd";
+        description = "Extra lines to append to the generated master.cf file.";
+      };
+
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf config.services.postfix.enable {
+
+    environment = {
+      etc = singleton
+        { source = "/var/postfix/conf";
+          target = "postfix";
+        };
+
+      # This makes comfortable for root to run 'postqueue' for example.
+      systemPackages = [ pkgs.postfix ];
+    };
+
+    services.mail.sendmailSetuidWrapper = mkIf config.services.postfix.setSendmail {
+      program = "sendmail";
+      source = "${pkgs.postfix}/bin/sendmail";
+      owner = "nobody";
+      group = "postdrop";
+      setuid = false;
+      setgid = true;
+    };
+
+    users.extraUsers = singleton
+      { name = user;
+        description = "Postfix mail server user";
+        uid = config.ids.uids.postfix;
+        group = group;
+      };
+
+    users.extraGroups =
+      [ { name = group;
+          gid = config.ids.gids.postfix;
+        }
+        { name = setgidGroup;
+          gid = config.ids.gids.postdrop;
+        }
+      ];
+
+    jobs.postfix =
+      # I copy _lots_ of shipped configuration filed
+      # that can be left as is. I am afraid the exact
+      # will list slightly change in next Postfix
+      # release, so listing them all one-by-one in an
+      # accurate way is unlikely to be better.
+      { description = "Postfix mail server";
+
+        wantedBy = [ "multi-user.target" ];
+        after = [ "network.target" ];
+
+        daemonType = "fork";
+
+        preStart =
+          ''
+            if ! [ -d /var/spool/postfix ]; then
+              ${pkgs.coreutils}/bin/mkdir -p /var/spool/mail /var/postfix/conf /var/postfix/queue
+            fi
+
+            ${pkgs.coreutils}/bin/chown -R ${user}:${group} /var/postfix
+            ${pkgs.coreutils}/bin/chown -R ${user}:${setgidGroup} /var/postfix/queue
+            ${pkgs.coreutils}/bin/chmod -R ug+rwX /var/postfix/queue
+            ${pkgs.coreutils}/bin/chown root:root /var/spool/mail
+            ${pkgs.coreutils}/bin/chmod a+rwxt /var/spool/mail
+
+            ln -sf "${pkgs.postfix}/share/postfix/conf/"* /var/postfix/conf
+
+            ln -sf ${aliasesFile} /var/postfix/conf/aliases
+            ln -sf ${virtualFile} /var/postfix/conf/virtual
+            ln -sf ${mainCfFile} /var/postfix/conf/main.cf
+            ln -sf ${masterCfFile} /var/postfix/conf/master.cf
+
+            ${pkgs.postfix}/sbin/postalias -c /var/postfix/conf /var/postfix/conf/aliases
+            ${pkgs.postfix}/sbin/postmap -c /var/postfix/conf /var/postfix/conf/virtual
+
+            ${pkgs.postfix}/sbin/postfix -c /var/postfix/conf start
+          '';
+
+        preStop = ''
+            ${pkgs.postfix}/sbin/postfix -c /var/postfix/conf stop
+        '';
+
+      };
+
+  };
+
+}
diff --git a/nixos/modules/services/mail/spamassassin.nix b/nixos/modules/services/mail/spamassassin.nix
new file mode 100644
index 00000000000..aaf1dfcc210
--- /dev/null
+++ b/nixos/modules/services/mail/spamassassin.nix
@@ -0,0 +1,64 @@
+{ config, pkgs, ... }:
+
+with pkgs.lib;
+
+let
+
+  cfg = config.services.spamassassin;
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.spamassassin = {
+
+      enable = mkOption {
+        default = false;
+        description = "Whether to run the SpamAssassin daemon.";
+      };
+
+      debug = mkOption {
+        default = false;
+        description = "Whether to run the SpamAssassin daemon in debug mode.";
+      };
+
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    # Allow users to run 'spamc'.
+    environment.systemPackages = [ pkgs.spamassassin ];
+
+    users.extraUsers = singleton {
+    name = "spamd";
+      description = "Spam Assassin Daemon";
+      uid = config.ids.uids.spamd;
+      group = "spamd";
+    };
+
+    users.extraGroups = singleton {
+      name = "spamd";
+      gid = config.ids.gids.spamd;
+    };
+
+    jobs.spamd = {
+      description = "Spam Assassin Server";
+
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+
+      exec = "${pkgs.spamassassin}/bin/spamd ${optionalString cfg.debug "-D"} --username=spamd --groupname=spamd --nouser-config --virtual-config-dir=/var/lib/spamassassin/user-%u --allow-tell --pidfile=/var/run/spamd.pid";
+    };
+
+  };
+
+}