update openldap, dovecot, postfix.
authorJulien Moutinho <julm@autogeree.net>
Tue, 18 Sep 2018 21:43:28 +0000 (23:43 +0200)
committerJulien Moutinho <julm@autogeree.net>
Tue, 18 Sep 2018 21:43:28 +0000 (23:43 +0200)
12 files changed:
.envrc
install/logical/friot.nix
install/logical/friot/dovecot.nix
install/logical/friot/dovecot/autoconfig.nix [new file with mode: 0644]
install/logical/friot/openldap.nix
install/logical/friot/openldap/postfix-book.ldif [new file with mode: 0644]
install/logical/friot/openldap/postfix2.ldif [new file with mode: 0644]
install/logical/friot/postfix.nix
install/logical/friot/rmilter.nix
install/overlays.nix [new file with mode: 0644]
install/physical/nixos.nix
install/physical/virtualbox.nix

diff --git a/.envrc b/.envrc
index ce74ae4d7695cab3703125fff487f3f0b9e30730..3e6b43cb5bd1faa122aae62075a8e18ef8332672 100644 (file)
--- a/.envrc
+++ b/.envrc
@@ -9,6 +9,7 @@ NIX_PATH="nixpkgs=/home/julm/src/nixpkgs"
 NIX_PATH+=":nixsys=$PWD/lib/nixsys"
 NIX_PATH+=":sys=$PWD"
 #NIX_PATH+=":nixpkgs-overlays=$PWD/lib/nixsys/build/overlays.nix"
+#NIX_PATH+=":nixpkgs-overlays=$PWD/install/overlays.nix"
 export NIX_PATH
 
 # Use NixOps as Disnix's provisioning backend
index 2eb04b7028ef13da789dbca68e008f2b9004c127..289457328cc5677379770e9f22f890ece30d6a38 100644 (file)
@@ -47,6 +47,7 @@ options = {
   };
 };
 config = {
+  nixpkgs.overlays = import ../overlays.nix;
   networking = {
     baseName = "commonsoft";
     domain   = "${config.networking.baseName}.coop";
@@ -161,7 +162,7 @@ config = {
       #sssd
       docker
       #nss_ldap
-      nss_pam_ldapd
+      #nss_pam_ldapd
       socat
     ];
   };
index 498a7461a728cf483984a93ebeb598e584169882..63c5ca9bc14a588e6aca2d862b853cdff9317366 100644 (file)
@@ -1,7 +1,7 @@
 {pkgs, lib, config, system, ...}:
-let inherit (builtins) toString toFile attrNames;
+let inherit (builtins) toString toFile;
     inherit (lib) types;
-    inherit (config.services) dovecot2 postfix x509;
+    inherit (config.services) dovecot2 postfix x509 openldap;
     unlines     = lib.concatStringsSep "\n";
     when        = x: y: if x == null then "" else y;
     extSep      = postfix.recipientDelimiter;
@@ -16,75 +16,77 @@ let inherit (builtins) toString toFile attrNames;
                                         || "0"<=c && c<="9"
                                         || c=="-"
                                         then c else "_");
+    etc_dovecot = [
+      { target = "dovecot/${config.networking.domain}/dovecot-ldap.conf";
+        source = pkgs.writeText "dovecot-ldap.conf" ''
+          ${lib.optionalString dovecot2.debug ''
+            debug_level = 1
+          ''}
+
+          # LDAP database
+          uris = ldapi://
+          base = ou=posix,${openldap.domainSuffix}
+          scope = subtree
+          deref = never
+          blocking = no
+            # NOTE: sufficient for small systems and uses less resources.
+
+          # LDAP auth
+          sasl_bind = yes
+          sasl_mech = EXTERNAL
+          dn = cn=admin,${openldap.domainSuffix}
+          #dnpass = useless with sasl_mech=EXTERNAL
+          auth_bind = no
+          #auth_bind_userdn = cn=%n,ou=accounts,ou=posix,dc=${openldap.domainSuffix}
+
+          # dovecot passdb query
+          pass_filter = (&(objectClass=posixAccount)(uid=%n))
+          pass_attrs = userPassword=password,\
+                       uidNumber=userdb_uid,\
+                       gidNumber=userdb_gid,\
+                       mailGroupMember=mail_access_groups,\
+                       =user=%n@%d
+                       #homeDirectory=userdb_home
+                       #quotaBytes=userdb_quota_rule=*:bytes=%{ldap:quotaBytes}
+            # TODO: userdb_quota_rule=*:storage=
+            # TODO: userdb_mail_access_groups
+            # DOC: http://wiki2.dovecot.org/PasswordDatabase/ExtraFields
+          default_pass_scheme = CRYPT
+
+          # dovecot userdb query
+          user_filter = (&(objectClass=posixAccount)(uid=%n))
+          #user_filter = (&(objectClass=inetOrgPerson)(uid=%n)(mailEnabled=TRUE))
+          #  # DOC: http://wiki2.dovecot.org/Variables
+          #user_attrs = homeDirectory=home,uidNumber=uid,gidNumber=gid
+          #user_attrs = mailHomeDirectory=home,\
+          #              mailStorageDirectory=mail,\
+          #              mailUidNumber=uid,\
+          #              mailGidNumber=gid,\
+          #              mailQuota=quota_rule=*:bytes=%$
+          #  # DOC: http://wiki2.dovecot.org/UserDatabase/ExtraFields
+
+          # doveadm user query
+          iterate_attrs = =user=%{ldap:uid}@${config.networking.domain}
+          iterate_filter = (objectClass=posixAccount)
+        '';
+      }
+    ];
 in
 {
+imports = [
+  dovecot/autoconfig.nix
+];
 config = {
-  services.nginx = {
-    virtualHosts."autoconfig" =
-    let servers = lib.concatMapStringsSep " "
-                   (dom: "autoconfig.${dom}")
-                   (attrNames dovecot2.domains);
-        autoconfigSite = pkgs.writeTextFile {
-          name = "autoconfig";
-          destination = "/mail/config-v1.1.xml";
-          text = ''
-            <?xml version="1.0"?>
-            <clientConfig version="1.1">
-              <emailProvider id="%EMAILDOMAIN%">
-                <!-- <displayName></displayName> -->
-                <!-- <displayShortName></displayShortName> -->
-                <domain>%EMAILDOMAIN%</domain>
-                <incomingServer type="imap">
-                  <hostname>mail.%EMAILDOMAIN%</hostname>
-                  <port>993</port>
-                  <socketType>SSL</socketType>
-                  <username>%EMAILADDRESS%</username>
-                  <authentication>password-cleartext</authentication>
-                </incomingServer>
-                <incomingServer type="pop3">
-                  <hostname>mail.%EMAILDOMAIN%</hostname>
-                  <port>995</port>
-                  <socketType>SSL</socketType>
-                  <username>%EMAILADDRESS%</username>
-                  <authentication>password-cleartext</authentication>
-                  <pop3>
-                    <leaveMessagesOnServer>false</leaveMessagesOnServer>
-                    <downloadOnBiff>true</downloadOnBiff>
-                  </pop3>
-                </incomingServer>
-                <outgoingServer type="smtp">
-                  <hostname>mail.%EMAILDOMAIN%</hostname>
-                  <port>465</port>
-                  <socketType>SSL</socketType> <!-- see above -->
-                  <username>%EMAILADDRESS%</username> <!-- if smtp-auth -->
-                  <authentication>password-cleartext</authentication>
-                  <!-- <restriction>client-IP-address</restriction> -->
-                  <addThisServer>true</addThisServer>
-                  <useGlobalPreferredServer>false</useGlobalPreferredServer>
-                </outgoingServer>
-              </emailProvider>
-              <!-- <clientConfigUpdate url="https://www.example.com/config/mozilla.xml" /> -->
-            </clientConfig>
-          '';
-        };
-    in
-    {
-      serverName = "autoconfig.${config.networking.domain}";
-      root = autoconfigSite;
-      #addSSL = true;
-      extraConfig = ''
-        access_log off;
-        log_not_found off;
-      '';
-    };
-  };
+  systemd.services.dovecot2.after = [ "postfix.service" ];
+  systemd.services.dovecot2.restartTriggers =
+    map (f: f.source) etc_dovecot;
+  environment.etc = etc_dovecot;
   #services.postfix.mapFiles."transport-dovecot" =
   #  toFile "transport-dovecot"
   #   (unlines
   #     (lib.mapAttrsToList
   #       (dom: {...}: "${transportSubDomain}.${dom} lmtp:unix:private/dovecot-lmtp")
   #       dovecot2.domains));
-  systemd.services.dovecot2.after = [ "postfix.service" ];
   #users.extraUsers = [
   #  { name        = "dovecot";
   #    uid         = config.ids.uids.dovecot2;
@@ -92,11 +94,12 @@ config = {
   #    group       = dovecot2.group;
   #  }
   #];
-  users.extraGroups = lib.mapAttrs
-                       (domain: {...}:
-                        { name = escapeGroup "${dovecot2.mailGroup}-${domain}";
-                        })
-                       dovecot2.domains;
+  users.extraGroups =
+    lib.mapAttrs
+     (domain: {...}:
+      { name = escapeGroup "${dovecot2.mailGroup}-${domain}";
+      })
+     dovecot2.domains;
   systemd.services.dovecot2.preStart =
     let sieveList =
           pkgs.writeText "list.sieve" ''
@@ -204,7 +207,7 @@ config = {
        -g ${authGroup} \
        ${libDir}/auth \
        ${libDir}/auth/${domain}
-      dir_passwd=${libDir}/auth/${domain}
+      dir_passwd=${authDir}/${domain}
       old_passwd=$dir_passwd/passwd
       new_passwd=$(TMPDIR= mktemp --tmpdir=$dir_passwd -t passwd.XXXXXXXX.tmp)
       
@@ -264,48 +267,55 @@ config = {
     ) dovecot2.domains);
   services.dovecot2 = {
     enable    = true;
+    debug     = true;
     mailUser  = "dovemail";
     mailGroup = "dovemail";
     modules   = [
       #pkgs.dovecot_antispam
       pkgs.dovecot_pigeonhole
     ];
-    # ${lib.concatMapStringsSep "\n"
-    #     (dom: ''
-    #       local_name imap.${dom} {
-    #         #ssl_ca   = <''${caPath}
-    #         ssl_cert = <${x509.cert dom}
-    #         ssl_key  = <${x509.key dom}
-    #         }
-    #       local_name pop.${dom} {
-    #         #ssl_ca   = <''${caPath}
-    #         ssl_cert = <${x509.cert dom}
-    #         ssl_key  = <${x509.key dom}
-    #         }
-    #     '')
-    #     dovecot2.domains
-    # }
-
     configFile = toString (pkgs.writeText "dovecot.conf" ''
       passdb {
-        driver = passwd-file
-        args   = scheme=crypt username_format=%n ${authDir}/%d/passwd
-        }
+        driver = ldap
+        args = /etc/dovecot/${config.networking.domain}/dovecot-ldap.conf
+        default_fields =
+        override_fields =
+      }
       userdb {
         driver = prefetch
-        }
+      }
       userdb {
         # NOTE: this userdb is only used by lda.
-        driver = passwd-file
-        args = username_format=%n ${authDir}/%d/passwd
-        #default_fields = home=${mailDir}/%d/%n
-        }
+        driver = ldap
+        args = /etc/dovecot/${config.networking.domain}/dovecot-ldap.conf
+        default_fields =
+        override_fields =
+        skip = found
+      }
+      #passdb {
+      #  driver = passwd-file
+      #  args   = scheme=crypt username_format=%n ${authDir}/%d/passwd
+      #}
+      #userdb {
+      #  # NOTE: this userdb is only used by lda.
+      #  driver = passwd-file
+      #  args = username_format=%n ${authDir}/%d/passwd
+      #  #default_fields = home=${mailDir}/%d/%n
+      #  skip = found
+      #}
       mail_home = ${mailDir}/%d/%n
+        # NOTE: if needed, may be overrided by userdb_mail
+      mail_location = maildir:${mailDir}/%d/%n/Maildir:LAYOUT=fs:INDEX=${libDir}/index/%d/%n:CONTROL=${libDir}/control/%d/%n
+        # NOTE: if needed, may be overrided by userdb_mail
+        # NOTE: INDEX and CONTROL are on a partition without quota, as explain in the doc.
+        # SEE: http://wiki2.dovecot.org/Quota/FS
       auth_mechanisms = plain login
-      # postfix does not supply a client cert.
       auth_ssl_require_client_cert = no
+        # NOTE: postfix does not supply a client cert.
       auth_ssl_username_from_cert = yes
       auth_verbose = yes
+      auth_username_format = %Lu
+        # NOTE: lowercase the username, help with LDAP?
       ${lib.optionalString dovecot2.debug ''
         auth_debug  = yes
         mail_debug  = yes
@@ -319,9 +329,7 @@ config = {
       lda_mailbox_autosubscribe = yes
       listen = *
       log_timestamp = "%Y-%m-%d %H:%M:%S "
-      # NOTE: INDEX and CONTROL are on a partition without quota, as explain in the doc.
-      # SEE: http://wiki2.dovecot.org/Quota/FS
-      mail_location = maildir:${mailDir}/%d/%n/Maildir:LAYOUT=fs:INDEX=${libDir}/index/%d/%n:CONTROL=${libDir}/control/%d/%n
+      #maildir_copy_with_hardlinks = yes
       namespace inbox {
         # NOTE: here because protocol sieve {namespace inbox{}} does not seem to work.
         inbox     = yes
@@ -329,25 +337,30 @@ config = {
         list      = yes
         prefix    =
         separator = ${dirSep}
-        }
+      }
       namespace {
         #list          = children
         list          = yes
-        location      = maildir:${mailDir}/%%d/%%n/Maildir:LAYOUT=fs:INDEX=${libDir}/index/%d/%n/Shared/%%n:CONTROL=${libDir}/control/%d/%n/Shared/%%n
+        location      = maildir:${mailDir}/%d/%n/Maildir:LAYOUT=fs:INDEX=${libDir}/index/%d/%n/Shared/%n:CONTROL=${libDir}/control/%d/%n/Shared/%n
+          # FIXME: %d not working
         prefix        = Partages+%%n+
         separator     = ${dirSep}
         subscriptions = yes
         type          = shared
-        }
+      }
       mail_plugins = $mail_plugins acl quota virtual
       #mail_uid = ${dovecot2.mailUser}
       #mail_gid = ${dovecot2.mailGroup}
+        # NOTE: each user has a dedicated (uid,gid) pair
       #mail_privileged_group = mail
       #mail_access_groups =
       plugin {
         acl = vfile:/etc/dovecot/acl/global.d
         acl_anyone = allow
         acl_shared_dict = file:${mailDir}/%d/acl.db
+          # NOTE: to let users LIST mailboxes shared by other users,
+          #       Dovecot needs a shared mailbox dictionary.
+          # FIXME: %d not working with userdb ldap
         ##antispam_allow_append_to_spam = yes
         # # NOTE: pour offlineimap
         #antispam_backend = pipe
@@ -374,6 +387,12 @@ config = {
         quota = maildir:User quota
         quota_rule = *:storage=256M
         quota_rule2 = Trash:storage=+64M
+        quota_max_mail_size = 20M
+        #quota_exceeded_message = </path/to/quota_exceeded_message.txt
+        quota_warning  = storage=95%% quota-warning 95 %u
+        quota_warning2 = storage=80%% quota-warning 80 %u
+        quota_warning3 = -storage=100%% quota-warning below %u
+         # NOTE: user is no longer over quota
         recipient_delimiter = ${extSep}
         sieve = file:${mailDir}/%d/%n/sieve;active=${mailDir}/%d/%n/sieve/main.sieve
         #sieve_default = file:${mailDir}/%u/default.sieve
@@ -390,7 +409,27 @@ config = {
         sieve_spamtest_status_header = X-Spam-Score
         sieve_spamtest_status_type = strlen
         sieve_user_log = /var/log/dovecot/%d/sieve.%n.log
+      }
+      service quota-warning {
+        executable = script ${
+          pkgs.writeScript "quota-warning" ''
+            #!/bin/sh -eu
+            PERCENT=$1
+            USER=$2
+            cat << EOF | ${pkgs.dovecot}/libexec/dovecot/dovecot-lda -d $USER -o
+            "plugin/quota=maildir:User quota:noenforcing"
+            From: postmaster@${config.networking.domain}
+            Subject: [WARNING] your mailbox is now $PERCENT% full.
+
+            Please remove some mails to make room for new ones.
+            EOF
+          ''
+        }
+        # use some unprivileged user for executing the quota warnings
+        user = ${dovecot2.user}
+        unix_listener quota-warning {
         }
+      }
       protocol imap {
         #mail_max_userip_connections = 10
         mail_plugins = $mail_plugins imap_acl imap_quota # antispam
@@ -400,23 +439,23 @@ config = {
           list = yes
           mailbox Drafts {
             special_use = \Drafts
-            }
+          }
           mailbox Junk {
             special_use = \Junk
-            }
+          }
           mailbox Sent {
             special_use = \Sent
-            }
+          }
           mailbox "Sent Messages" {
             special_use = \Sent
-            }
+          }
           mailbox Trash {
             special_use = \Trash
-            }
+          }
           prefix =
           separator = ${dirSep}
-          }
         }
+      }
       protocol lda {
         auth_socket_path = /var/run/dovecot/auth-userdb
         hostname         = ${config.networking.domain}
@@ -429,10 +468,10 @@ config = {
           list      = yes
           prefix    =
           separator = ${dirSep}
-          }
+        }
         postmaster_address = postmaster${extSep}dovecot${extSep}lda@${config.networking.domain}
         syslog_facility = mail
-        }
+      }
       protocol lmtp {
         #info_log_path = /tmp/dovecot-lmtp.log
         mail_plugins = $mail_plugins sieve
@@ -442,19 +481,19 @@ config = {
           list      = yes
           prefix    =
           separator = ${dirSep}
-          }
-        postmaster_address = postmaster${extSep}dovecot${extSep}lmtp@${config.networking.domain}
         }
+        postmaster_address = postmaster${extSep}dovecot${extSep}lmtp@${config.networking.domain}
+      }
       protocol pop3 {
         #mail_max_userip_connections = 10
-        # Used by ${libDir}/pop3/INBOX/dovecot-virtual
         namespace all {
+          # NOTE: used by ${libDir}/pop3/INBOX/dovecot-virtual
           hidden    = yes
           list      = no
           location  =
           prefix    = all+
           separator = ${dirSep}
-          }
+        }
         # Virtual namespace for the virtual INBOX.
         # Use a global directory for dovecot-virtual files.
         namespace inbox {
@@ -464,14 +503,14 @@ config = {
           location  = virtual:${libDir}/pop3:INDEX=${libDir}/index/%d/%n/POP3:LAYOUT=fs
           prefix    = pop3+
           separator = ${dirSep}
-          }
+        }
         pop3_client_workarounds =
         pop3_fast_size_lookups = yes
         pop3_lock_session = yes
         pop3_no_flag_updates = yes
         # Use GUIDs to avoid accidental POP3 UIDL changes instead of IMAP UIDs.
         pop3_uidl_format = %g
-        }
+      }
       protocol sieve {
         #mail_max_userip_connections = 10
         #managesieve_implementation_string = Dovecot Pigeonhole
@@ -479,7 +518,7 @@ config = {
         #managesieve_max_line_length = 65536
         #managesieve_notify_capability = mailto
         #managesieve_sieve_capability = fileinto reject envelope encoded-character vacation subaddress comparator-i;ascii-numeric relational regex imap4flags copy include variables body enotify environment mailbox date ihave
-        }
+      }
       protocols = imap lmtp pop3 sieve
       service lmtp {
         #executable = lmtp -L
@@ -488,57 +527,67 @@ config = {
           user  = ${postfix.user}
           group = ${postfix.group}
           mode  = 0600
-          }
-        #user = mail
         }
+        #user = mail
+      }
       service auth {
         user = root
+          # FIXME: may be user=dovecot-auth with LDAP?
         unix_listener auth-userdb {
           user  = ${dovecot2.user}
           group = ${dovecot2.group}
           mode  = 0660
-          }
+        }
         unix_listener /var/lib/postfix/queue/private/auth {
           user  = ${postfix.user}
           group = ${postfix.group}
           mode  = 0660
-          }
         }
+      }
       service imap {
         # Most of the memory goes to mmap()ing files.
         # You may need to increase this limit if you have huge mailboxes.
         #vsz_limit =
         process_limit = 1024
-        }
+      }
       service imap-login {
         #inet_listener imap {
         #  address = 127.0.0.1
         #  port    = 143
         #  ssl     = no
-        #  }
+        #}
         inet_listener imaps {
           port = 993
           ssl  = yes
-          }
         }
+      }
       service pop3 {
         process_limit = 1024
-        }
+      }
       service pop3-login {
         inet_listener pop3s {
           port = 995
           ssl  = yes
-          }
         }
+      }
       ssl = required
-      #ssl_ca   = <''${caPath}
+      ssl_dh = <${x509.dir}/dh.pem
+      ssl_cipher_list = HIGH:!LOW:!SSLv2:!EXP:!aNULL
       ssl_cert = <${x509.cert}
-      ssl_dh   = <${x509.dir}/dh.pem
-        # gOTE: only with dovecot >= 2.3
-      ssl_cipher_list = ALL:!LOW:!SSLv2:!EXP:!aNULL
       ssl_key = <${x509.key}
+      #ssl_ca   = <''${caPath}
       #ssl_verify_client_cert = yes
     '');
+      #${lib.concatMapStringsSep "\n"
+      #    (dom: ''
+      #      local_name mail.${dom} {
+      #        #ssl_ca   = <''${caPath}
+      #        ssl_cert = <${x509.cert dom}
+      #        ssl_key  = <${x509.key dom}
+      #        }
+      #    '')
+      #    dovecot2.domains
+      #}
   };
 };
 }
diff --git a/install/logical/friot/dovecot/autoconfig.nix b/install/logical/friot/dovecot/autoconfig.nix
new file mode 100644 (file)
index 0000000..20436f6
--- /dev/null
@@ -0,0 +1,66 @@
+{pkgs, lib, config, ...}:
+let inherit (builtins) attrNames;
+    inherit (config.services) dovecot2;
+in
+{
+config = {
+  services.nginx = {
+    virtualHosts."autoconfig" =
+    let servers = lib.concatMapStringsSep " "
+                   (dom: "autoconfig.${dom}")
+                   (attrNames dovecot2.domains);
+    in
+    {
+      serverName = "autoconfig.${config.networking.domain}";
+      #addSSL = true;
+      extraConfig = ''
+        access_log off;
+        log_not_found off;
+      '';
+      root = pkgs.writeTextFile {
+        name = "autoconfig";
+        destination = "/mail/config-v1.1.xml";
+        text = ''
+          <?xml version="1.0"?>
+          <clientConfig version="1.1">
+            <emailProvider id="%EMAILDOMAIN%">
+              <!-- <displayName></displayName> -->
+              <!-- <displayShortName></displayShortName> -->
+              <domain>%EMAILDOMAIN%</domain>
+              <incomingServer type="imap">
+                <hostname>mail.%EMAILDOMAIN%</hostname>
+                <port>993</port>
+                <socketType>SSL</socketType>
+                <username>%EMAILADDRESS%</username>
+                <authentication>password-cleartext</authentication>
+              </incomingServer>
+              <incomingServer type="pop3">
+                <hostname>mail.%EMAILDOMAIN%</hostname>
+                <port>995</port>
+                <socketType>SSL</socketType>
+                <username>%EMAILADDRESS%</username>
+                <authentication>password-cleartext</authentication>
+                <pop3>
+                  <leaveMessagesOnServer>false</leaveMessagesOnServer>
+                  <downloadOnBiff>true</downloadOnBiff>
+                </pop3>
+              </incomingServer>
+              <outgoingServer type="smtp">
+                <hostname>mail.%EMAILDOMAIN%</hostname>
+                <port>465</port>
+                <socketType>SSL</socketType> <!-- see above -->
+                <username>%EMAILADDRESS%</username> <!-- if smtp-auth -->
+                <authentication>password-cleartext</authentication>
+                <!-- <restriction>client-IP-address</restriction> -->
+                <addThisServer>true</addThisServer>
+                <useGlobalPreferredServer>false</useGlobalPreferredServer>
+              </outgoingServer>
+            </emailProvider>
+            <!-- <clientConfigUpdate url="https://www.example.com/config/mozilla.xml" /> -->
+          </clientConfig>
+        '';
+      };
+    };
+  };
+};
+}
index d4664ced0058937b2599cea5ccac05d48e652597..bfc60339a0ff293d61497022609e4c2244efbd10 100644 (file)
@@ -1,21 +1,21 @@
 {pkgs, lib, config, ...}:
-let inherit (config.services) openldap;
+let inherit (builtins) baseNameOf readFile;
+    inherit (config.services) openldap;
     inherit (config.users) ldap;
-    cnConfigLDIF = pkgs.writeText "cn=config.ldif" ''
+    copyFile = file: pkgs.writeText (baseNameOf file) (readFile file);
+    configLDIF = pkgs.writeText "cn=config.ldif" ''
       dn: cn=config
-      cn: config
       objectClass: olcGlobal
       #olcPidFile: /run/slapd/slapd.pid
       # List of arguments that were passed to the server
       #olcArgsFile: /run/slapd/slapd.args
       # Read slapd-config(5) for possible values
       olcLogLevel: none
-      # The tool-threads parameter sets the actual amount of cpu's that is used
-      # for indexing.
+      # The tool-threads parameter sets the actual amount of cpu's
+      # that is used for indexing.
       olcToolThreads: 1
-      
+
       dn: olcDatabase={-1}frontend,cn=config
-      olcDatabase: {-1}frontend
       objectClass: olcDatabaseConfig
       objectClass: olcFrontendConfig
       # The maximum number of entries that is returned for a search operation
@@ -29,9 +29,8 @@ let inherit (config.services) openldap;
         by * read
       olcAccess: to dn.base="cn=Subschema"
         by * read
-      
+
       dn: olcDatabase=config,cn=config
-      olcDatabase: config
       objectClass: olcDatabaseConfig
       olcRootDN: cn=admin,cn=config
       # Access to cn=config, system root can be manager
@@ -39,120 +38,137 @@ let inherit (config.services) openldap;
       olcAccess: to *
         by dn.exact="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" manage
         by * break
-      
+
       dn: cn=schema,cn=config
-      cn: schema
       objectClass: olcSchemaConfig
-      
+
       include: file://${pkgs.openldap}/etc/schema/core.ldif
       include: file://${pkgs.openldap}/etc/schema/cosine.ldif
       include: file://${pkgs.openldap}/etc/schema/nis.ldif
       include: file://${pkgs.openldap}/etc/schema/inetorgperson.ldif
-      
+      include: file://${copyFile openldap/postfix-book.ldif}
+      include: file://${copyFile openldap/postfix2.ldif}
+
       dn: cn=module{0},cn=config
-      cn: module{0}
       objectClass: olcModuleList
       # Where the dynamically loaded modules are stored
       #olcModulePath: /usr/lib/ldap
       olcModuleLoad: back_mdb
-      
+
       dn: olcBackend={1}mdb,cn=config
-      olcBackend: {1}mdb
       objectClass: olcBackendConfig
 
-      include: file://${mdb1Config}
+      include: file://${domainConfigLDIF openldap.domainSuffix}
     '';
-    mdb1Suffix = "dc=${config.networking.baseName}";
-    mdb1Config = pkgs.writeText "${mdb1Suffix}.config.ldif" ''
-      # sudo ldapsearch -LLL -D cn=admin,cn=config -Y EXTERNAL -b 'olcDatabase={1}mdb,cn=config' -s sub
+    domainConfigLDIF = dbSuffix: pkgs.writeText "config.ldif" ''
+      # sudo ldapsearch -LLL -H ldapi:// -D cn=admin,cn=config -Y EXTERNAL -b 'olcDatabase={1}mdb,cn=config' -s sub
       dn: olcDatabase={1}mdb,cn=config
-      olcDatabase: {1}mdb
       objectClass: olcDatabaseConfig
       objectClass: olcMdbConfig
-      # Checkpoint the database periodically in case of system
-      # failure and to speed slapd shutdown.
+      # NOTE: checkpoint the database periodically in case of system failure
+      # and to speed slapd shutdown.
       olcDbCheckpoint: 512 30
       # Database max size is 1G
       olcDbMaxSize: 1073741824
       olcLastMod: TRUE
-      olcSuffix: ${mdb1Suffix}
+      olcSuffix: ${dbSuffix}
       olcDbDirectory: ${openldap.dataDir}
-      # Database superuser. Needed for syncrepl.
-      olcRootDN: cn=admin,${mdb1Suffix}
-      # superuser password, generated with slappasswd -s SECRET
-      # olcRootPW: {SSHA}VUlLVeNl3IKltfX50f/PokMRnlhRsSDI
+      # NOTE: database superuser. Needed for syncrepl.
+      olcRootDN: cn=admin,${dbSuffix}
+      # NOTE: superuser password, generated with slappasswd -s SECRET
+      # FIXME: remove when dovecot2 compiled with SASL
+      olcRootPW: {SSHA}NONVwwKnKsCBmFxkMqTCFekdu3SJQHc9
       olcDbIndex: objectClass eq
       olcDbIndex: cn,uid eq
       olcDbIndex: uidNumber,gidNumber eq
       olcDbIndex: member,memberUid eq
+      olcDbIndex: mail eq
+      olcDbIndex: mailEnabled eq
       olcAccess: to attrs=userPassword
         by self write
         by anonymous auth
+        by dn="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" read
         by * none
       olcAccess: to attrs=shadowLastChange
         by self write
         by * none
-      olcAccess: to dn.sub="ou=posix,${mdb1Suffix}"
-        by dn="gidNumber=${toString config.users.groups.nslcd.gid}+uidNumber=${toString config.users.users.nslcd.uid},cn=peercred,cn=external,cn=auth" manage
+      olcAccess: to dn.sub="ou=posix,${dbSuffix}"
+        by dn="gidNumber=${toString config.users.groups.nslcd.gid}+uidNumber=${toString config.users.users.nslcd.uid},cn=peercred,cn=external,cn=auth" read
+        by dn="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" read
       olcAccess: to *
         by self read
         by * none
     '';
-    mdb1LDIF = pkgs.writeText "${mdb1Suffix}.ldif" ''
-      dn: ${mdb1Suffix}
-      dc: ${config.networking.baseName}
+    domainDataLDIF = dbSuffix: pkgs.writeText "data.ldif" ''
+      dn: ${dbSuffix}
       objectClass: top
       objectClass: dcObject
       objectClass: organization
-      o: Commonsoft
-      
-      dn: cn=admin,${mdb1Suffix}
-      cn: admin
+      o: ${config.networking.baseName}
+
+      dn: cn=admin,${dbSuffix}
       objectClass: simpleSecurityObject
       objectClass: organizationalRole
       description: ${config.networking.baseName} LDAP administrator
-      roleOccupant: ${mdb1Suffix}
-      userPassword:
-      
-      dn: ou=posix,${mdb1Suffix}
-      ou: posix
+      roleOccupant: ${dbSuffix}
+      userPassword: 
+      #userPassword: {SSHA}NONVwwKnKsCBmFxkMqTCFekdu3SJQHc9
+
+      dn: ou=posix,${dbSuffix}
       objectClass: top
       objectClass: organizationalUnit
-      
-      dn: ou=accounts,ou=posix,${mdb1Suffix}
-      ou: accounts
+
+      dn: ou=accounts,ou=posix,${dbSuffix}
       objectClass: top
       objectClass: organizationalUnit
-      
-      dn: ou=groups,ou=posix,${mdb1Suffix}
-      ou: groups
+
+      dn: ou=groups,ou=posix,${dbSuffix}
       objectClass: top
       objectClass: organizationalUnit
-      
-      dn: cn=users,ou=groups,ou=posix,${mdb1Suffix}
-      cn: users
+
+      dn: cn=users,ou=groups,ou=posix,${dbSuffix}
       objectclass: top
       objectclass: posixGroup
       gidnumber: 10000
-      memberuid: julm
+      memberuid: ju
       memberuid: sevy
-      
-      dn: uid=julm,ou=accounts,ou=posix,${mdb1Suffix}
-      uid: julm
-      objectClass: account
+
+      #dn: cn=dovemail,ou=groups,ou=posix,${dbSuffix}
+      #objectclass: top
+      #objectclass: posixGroup
+      #gidnumber: 497
+      # # FIXME: do not hardcode this gid
+      #memberuid: ju
+      #memberuid: sevy
+
+      dn: uid=ju,ou=accounts,ou=posix,${dbSuffix}
+      #objectClass: account
+      objectclass: person
       objectClass: posixAccount
+      objectclass: postfixUser
+      objectclass: PostfixBookMailAccount
+      objectclass: PostfixBookMailForward
       cn: Julien M.
+      sn: julm
+      mail: ju@commonsoft.coop
+      mailAlias: julien.moutinho@commonsoft.coop
       uidNumber: 10000
-      gidNumber: 10000
-      homeDirectory: /home/julm
+      gidNumber: 497
+      homeDirectory: /home/ju
       loginShell: /run/current-system/sw/bin/bash
       userPassword: {SSHA}144Rfau9KJ14U0U4KdLNB7OrtpiEc3E3
-      
-      dn: uid=sevy,ou=accounts,ou=posix,${mdb1Suffix}
-      uid: sevy
-      objectClass: account
+
+      dn: uid=sevy,ou=accounts,ou=posix,${dbSuffix}
+      #objectClass: account
+      objectclass: person
       objectClass: posixAccount
+      objectclass: postfixUser
+      objectclass: PostfixBookMailAccount
+      objectclass: PostfixBookMailForward
       cn: Séverine P.
+      sn: sévy
+      mail: sevy@commonsoft.coop
+      mailAlias: severine.popek@commonsoft.coop
       uidNumber: 10001
       gidNumber: 10000
       homeDirectory: /home/sevy
@@ -161,6 +177,13 @@ let inherit (config.services) openldap;
     '';
 in
 {
+  options.services.openldap.domainSuffix = lib.mkOption {
+    type    = lib.types.str;
+    default = "dc=${lib.concatStringsSep ",dc=" (lib.splitString "." config.networking.domain)}";
+    description = ''
+      LDAP suffix for the first database.
+    '';
+  };
   config = {
     users.ldap = {
       enable = true;
@@ -173,9 +196,9 @@ in
         '';
       };
       server = "ldapi:///";
-      base = "ou=posix,${mdb1Suffix}";
+      base = "ou=posix,${openldap.domainSuffix}";
       bind = {
-        #distinguishedName = "cn=admin,${mdb1Suffix}";
+        #distinguishedName = "cn=admin,${openldap.domainSuffix}";
       };
     };
     services.openldap = {
@@ -186,26 +209,24 @@ in
     };
     systemd.services.openldap = {
       preStart = ''
-        # NOTE: the config is always re-initialized.
+        # NOTE: slapd's config is always re-initialized.
         rm -rf "${openldap.configDir}"/cn=config \
                "${openldap.configDir}"/cn=config.ldif
         umask 0077
-        install -D -d -m 0700 \
-         -o "${openldap.user}" \
-         -g "${openldap.group}" \
-         "${openldap.dataDir}" \
-         "${openldap.configDir}"
-        
-        # NOTE: slapd is stopped in preStart, slap* commands can therefore be used.
-        ${pkgs.openldap}/bin/slapadd -n 0 -F "${openldap.configDir}" -l ${cnConfigLDIF}
+         install -D -d -m 0700 -o "${openldap.user}" -g "${openldap.group}" "${openldap.configDir}"
+
+        # NOTE: slapd is supposed to be stopped while in preStart,
+        #       hence slap* commands can safely be used.
+        ${pkgs.openldap}/bin/slapadd -n 0 -F "${openldap.configDir}" -l ${configLDIF}
         # NOTE: slapadd(8): To populate the config database slapd-config(5),
         #                   use -n 0 as it is always the first database.
         #                   It must physically exist on the filesystem prior to this, however.
-        
+
         # NOTE: the data are only initialized, never re-initialized.
         if test ! -e "${openldap.dataDir}"/data.mdb
          then
-          ${pkgs.openldap}/bin/slapadd -F "${openldap.configDir}" -l ${mdb1LDIF}
+          install -D -d -m 0700 -o "${openldap.user}" -g "${openldap.group}" "${openldap.dataDir}"
+          ${pkgs.openldap}/bin/slapadd -F "${openldap.configDir}" -l ${domainDataLDIF openldap.domainSuffix}
          fi
         chown -R "${openldap.user}:${openldap.group}" \
          "${openldap.dataDir}" \
diff --git a/install/logical/friot/openldap/postfix-book.ldif b/install/logical/friot/openldap/postfix-book.ldif
new file mode 100644 (file)
index 0000000..d61c582
--- /dev/null
@@ -0,0 +1,73 @@
+# SOURCE: https://github.com/variablenix/ldap-mail-schema/
+dn: cn=postfix-book,cn=schema,cn=config
+objectClass: olcSchemaConfig
+olcAttributeTypes: ( 1.3.6.1.4.1.29426.1.10.1
+  NAME 'mailHomeDirectory'
+  DESC 'The absolute path to the mail user home directory'
+  EQUALITY caseExactIA5Match
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+  SINGLE-VALUE )
+olcAttributeTypes: ( 1.3.6.1.4.1.29426.1.10.2
+  NAME 'mailAlias'
+  DESC 'RFC822 Mailbox - mail alias'
+  EQUALITY caseIgnoreIA5Match
+  SUBSTR caseIgnoreIA5SubstringsMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
+olcAttributeTypes: ( 1.3.6.1.4.1.29426.1.10.3
+  NAME 'mailUidNumber'
+  DESC 'UID required to access the mailbox'
+  EQUALITY integerMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+  SINGLE-VALUE )
+olcAttributeTypes: ( 1.3.6.1.4.1.29426.1.10.4
+  NAME 'mailGidNumber'
+  DESC 'GID required to access the mailbox'
+  EQUALITY integerMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+  SINGLE-VALUE )
+olcAttributeTypes: ( 1.3.6.1.4.1.29426.1.10.5
+  NAME 'mailEnabled'
+  DESC 'TRUE to enable, FALSE to disable account'
+  EQUALITY booleanMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
+  SINGLE-VALUE )
+olcAttributeTypes: ( 1.3.6.1.4.1.29426.1.10.6
+  NAME 'mailGroupMember'
+  DESC 'Name of a mail distribution list'
+  EQUALITY caseExactIA5Match
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+olcAttributeTypes: ( 1.3.6.1.4.1.29426.1.10.7
+  NAME 'mailQuota'
+  DESC 'Mail quota limit in kilobytes'
+  EQUALITY caseExactIA5Match
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+olcAttributeTypes: ( 1.3.6.1.4.1.29426.1.10.8
+  NAME 'mailStorageDirectory'
+  DESC 'The absolute path to the mail users mailbox'
+  EQUALITY caseExactIA5Match
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+  SINGLE-VALUE )
+olcAttributeTypes: ( 1.3.6.1.4.1.29426.1.10.9
+  NAME 'mailSieveRuleSource'
+  DESC 'Sun ONE Messaging Server defined attribute'
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+  X-ORIGIN 'Sun ONE Messaging Server' )
+olcAttributeTypes: ( 1.3.6.1.4.1.29426.1.10.10
+  NAME 'mailForwardingAddress'
+  DESC 'Address(es) to forward all incoming messages to.'
+  EQUALITY caseIgnoreIA5Match
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{320} )
+olcObjectClasses: ( 1.3.6.1.4.1.29426.1.2.2.1
+  NAME 'PostfixBookMailAccount'
+  DESC 'Mail account used in Postfix Book'
+  SUP top AUXILIARY
+  MUST mail
+  MAY ( mailHomeDirectory $ mailAlias $ mailGroupMember $
+  mailUidNumber $ mailGidNumber $ mailEnabled $
+  mailQuota $ mailStorageDirectory $ mailSieveRuleSource ) )
+olcObjectClasses: ( 1.3.6.1.4.1.29426.1.2.2.2
+  NAME 'PostfixBookMailForward'
+  DESC 'Mail forward used in Postfix Book'
+  SUP top AUXILIARY
+  MUST ( mail $ mailAlias )
+  MAY mailForwardingAddress )
diff --git a/install/logical/friot/openldap/postfix2.ldif b/install/logical/friot/openldap/postfix2.ldif
new file mode 100644 (file)
index 0000000..2cd3f43
--- /dev/null
@@ -0,0 +1,21 @@
+# SOURCE: https://github.com/variablenix/ldap-mail-schema/
+# DOC: http://www.postfix.org/LDAP_README.html
+dn: cn=postfix2,cn=schema,cn=config
+objectClass: olcSchemaConfig
+olcAttributeTypes: ( 1.3.6.1.4.1.4203.666.1.200
+  NAME 'mailacceptinggeneralid'
+  DESC 'Postfix mail local address alias attribute'
+  EQUALITY caseIgnoreMatch
+  SUBSTR caseIgnoreSubstringsMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{1024} )
+olcAttributeTypes: ( 1.3.6.1.4.1.4203.666.1.201
+  NAME 'maildrop'
+  DESC 'Postfix mail final destination attribute'
+  EQUALITY caseIgnoreMatch
+  SUBSTR caseIgnoreSubstringsMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{1024} )
+olcObjectClasses: ( 1.3.6.1.4.1.4203.666.1.100
+  NAME 'postfixUser'
+  DESC 'Postfix mail user class'
+  SUP top AUXILIARY
+  MAY ( mailacceptinggeneralid $ maildrop ) )
index c51b9e2614658f3dc6edce7ef8d6a09402420ab6..db0fb78d2404871d7f5b8dd0a6cf1ab764b33929 100644 (file)
@@ -36,7 +36,8 @@ config = {
     else [];
   services.postfix = {
     enable = true;
-    hostname = "${config.networking.domain}";
+    #hostname = config.networking.domain;
+    #domain = "localdomain";
     networksStyle = "host";
     #mapFiles."valias" = toFile "valias" (unlines (all_valiases_postfix ++ catchAllPostfix));
     # See https://blog.grimneko.de/2011/12/24/a-bunch-of-tips-for-improving-your-postfix-setup/
@@ -64,7 +65,12 @@ config = {
     sslKey = x509.key;
     #enableSubmission = true;
     #enableSmtp = true;
-    destination = [ "localhost" ];
+    destination = [
+      "localhost"
+      "localhost.localdomain"
+      config.networking.hostName
+      "${config.networking.hostName}.localdomain"
+    ];
     networks = [ "127.0.0.0/8" "[::1]/128" ];
     recipientDelimiter = "+";
     config = {
@@ -92,13 +98,18 @@ config = {
       #header_checks = "regexp:/var/lib/postfix/conf/header_checks";
       #inet_interfaces = "all";
       line_length_limit = "2048";
+
       # Let $fallback_transport check existence of recipients
       local_recipient_maps = "";
+      #mail_spool_directory = "/var/spool/mail";
+        # NOTE: nixpkgs's default
       #local_header_rewrite_clients = "";
-      mailbox_command = ''
-        ${pkgs.procmail}/bin/procmail -t -a "$SENDER" -a "$RECIPIENT" -a "$USER" -a "$EXTENSION" -a "$DOMAIN" -a "$ORIGINAL_RECIPIENT" "$HOME/.procmailrc"
-      '';
-      mailbox_size_limit = "0";
+      #home_mailbox = "Maildir/";
+      #mailbox_command = ''
+      #  ${pkgs.procmail}/bin/procmail -t -a "$SENDER" -a "$RECIPIENT" -a "$USER" -a "$EXTENSION" -a "$DOMAIN" -a "$ORIGINAL_RECIPIENT" "$HOME/.procmailrc"
+      #'';
+      mailbox_size_limit = "204800000";
+
       masquerade_classes = [ "envelope_sender" "header_sender" "header_recipient" ];
       masquerade_domains = "";
       masquerade_exceptions = "root";
@@ -161,7 +172,7 @@ config = {
       #smtp_tls_verify_cert_match = "hostname";
       # Useful to test restrictions
       smtpd_authorized_xclient_hosts = "127.0.0.1";
-      smtpd_banner = "$myhostname ESMTP $mail_name (NixOS)";
+      smtpd_banner = "${config.networking.fqdn} ESMTP $mail_name (NixOS)";
       smtpd_client_connection_count_limit = "50";
       smtpd_client_connection_rate_limit = "0";
       smtpd_client_event_limit_exceptions = "$mynetworks";
@@ -232,6 +243,7 @@ config = {
         "reject_unauth_destination"
       ];
       #smtpd_restriction_classes = "";
+      broken_sasl_auth_clients = false;
       #smtpd_sasl_auth_enable = true;
       #smtpd_sasl_path = "private/auth";
       #smtpd_sasl_security_options = "noanonymous";
@@ -290,6 +302,7 @@ config = {
       # Use a non blocking source of randomness
       tls_random_source = "dev:/dev/urandom";
       transport_maps = [
+        #"ldap:transport"
         #"hash:/etc/postfix/transport-dovecot"
         #"hash:/etc/postfix/$mydomain/transport"
         #"hash:/etc/dovecot/transport"
@@ -307,6 +320,7 @@ config = {
       virtual_alias_domains = [];
       virtual_alias_maps = [
         "hash:/etc/postfix/virtual_alias_maps"
+        #"ldap:aliases"
         #"hash:/etc/postfix/virtual_alias-dovecot"
         #"hash:/var/lib/postfix/conf/valias"
         #"regexp:/etc/sympa/virtual_alias"
@@ -332,12 +346,17 @@ config = {
     #  cleanup_service_name         = "submission-header-cleanup";
     #};
     extraMasterConf = ''
-      spfcheck    unix  -        n       n       -        0        spawn
-        user=policyd-spf argv=/usr/sbin/postfix-policyd-spf-perl
+      #spfcheck    unix  -        n       n       -        0        spawn
+      #  user=policyd-spf argv=/usr/sbin/postfix-policyd-spf-perl
       465         inet  n        -       -       -        -        smtpd
         -o milter_macro_daemon_name=ORIGINATING
         -o smtpd_client_restrictions=permit_sasl_authenticated,reject
+        -o smtpd_recipient_restrictions=reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_sasl_authenticated,reject
         -o smtpd_sasl_auth_enable=yes
+        -o smtpd_sasl_local_domain=$myhostname
+        -o smtpd_sasl_path=private/auth
+        -o smtpd_sasl_security_options=noanonymous
+        -o smtpd_sasl_type=dovecot
         -o smtpd_tls_ask_ccert=no
         -o smtpd_tls_auth_only=yes
         -o smtpd_tls_ccert_verifydepth=0
@@ -345,11 +364,6 @@ config = {
         -o smtpd_tls_req_ccert=no
         -o smtpd_tls_security_level=encrypt
         -o smtpd_tls_wrappermode=yes
-        -o smtpd_recipient_restrictions=reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_sasl_authenticated,reject
-        -o smtpd_sasl_local_domain=$myhostname
-        -o smtpd_sasl_security_options=noanonymous
-        -o smtpd_sasl_type=dovecot
-        -o smtpd_sasl_path=private/auth
       # -o smtpd_sender_restrictions=reject_sender_login_mismatch
       # -o smtpd_sender_login_maps=hash:/etc/postfix/vaccounts
       # -o cleanup_service_name=submission-header-cleanup
index 7fc52a35c5f5c23578a686f1307c79b57308c2a1..2046829d685008afafbb3081b0a99889c5164f25 100644 (file)
@@ -19,70 +19,70 @@ let inherit (builtins) attrNames;
     '';
 in
 {
-options.services.dkim = lib.mkOption {
-  default = {};
-  type = types.submodule {
-    options = {
-      keyDir = lib.mkOption {
-        type        = types.path;
-        default     = "/var/lib/dkim";
-        description = ''
-        '';
-      };
-      selector = lib.mkOption {
-        type        = types.str;
-        default     = "mail";
-        description = ''
-        '';
+  options.services.dkim = lib.mkOption {
+    default = {};
+    type = types.submodule {
+      options = {
+        keyDir = lib.mkOption {
+          type        = types.path;
+          default     = "/var/lib/dkim";
+          description = ''
+          '';
+        };
+        selector = lib.mkOption {
+          type        = types.str;
+          default     = "mail";
+          description = ''
+          '';
+        };
       };
     };
   };
-};
-config = {
-  services.rspamd = {
-    enable = true;
-  };
-  services.rmilter = {
-    enable = true;
-    #debug = true;
-    postfix = {
+  config = {
+    services.rspamd = {
       enable = true;
     };
-    rspamd = {
-      enable      = true;
-      extraConfig = "extended_spam_headers = yes;";
-    };
-    extraConfig = ''
-      use_redis = true;
-      max_size  = 20M;
-      #clamav {
-      #  servers = /var/run/clamav/clamd.ctl;
-      #};
-      # NOTE: domain = "*"; causes rmilter to try to search key in the key path
-      # as keypath/domain.selector.key for any domain.
-      dkim {
-        domain {
-          domain   = "*";
-          key      = "${dkim.keyDir}";
-          selector = "${dkim.selector}";
-        };
-        sign_alg  = sha256;
-        auth_only = yes;
+    services.rmilter = {
+      enable = true;
+      #debug = true;
+      postfix = {
+        enable = true;
       };
-    '';
-    bindSocket.type = "unix";
-    bindSocket.path = "/run/rmilter.sock";
-      # NOTE: fix default which is in wiped out directory /run/rmilter/rmilter.sock
-  };
-  #systemd.sockets.rmilter.socketConfig.Accept = false;
-  systemd.services.rmilter = {
-    requires = [ "rmilter.socket" ];
-    after    = [ "rmilter.socket" ];
-    preStart = ''
-      install -D -d -o rmilter -g rmilter ${dkim.keyDir}
-      ${lib.concatStringsSep "\n" (map createDomainDkimCert (attrNames dovecot2.domains))}
-      chown -R rmilter:rmilter "${dkim.keyDir}"
-    '';
+      rspamd = {
+        enable      = true;
+        extraConfig = "extended_spam_headers = yes;";
+      };
+      extraConfig = ''
+        use_redis = true;
+        max_size  = 20M;
+        #clamav {
+        #  servers = /var/run/clamav/clamd.ctl;
+        #};
+        # NOTE: domain = "*"; causes rmilter to try to search key in the key path
+        # as keypath/domain.selector.key for any domain.
+        dkim {
+          domain {
+            domain   = "*";
+            key      = "${dkim.keyDir}";
+            selector = "${dkim.selector}";
+          };
+          sign_alg  = sha256;
+          auth_only = yes;
+        };
+      '';
+      bindSocket.type = "unix";
+      bindSocket.path = "/run/rmilter.sock";
+        # NOTE: fix default which is in wiped out directory /run/rmilter/rmilter.sock
+    };
+    #systemd.sockets.rmilter.socketConfig.Accept = false;
+    systemd.services.rmilter = {
+      requires = [ "rmilter.socket" ];
+      after    = [ "rmilter.socket" ];
+      preStart = ''
+        install -D -d -o rmilter -g rmilter ${dkim.keyDir}
+        ${lib.concatStringsSep "\n" (map createDomainDkimCert (attrNames dovecot2.domains))}
+        chown -R rmilter:rmilter "${dkim.keyDir}"
+      '';
+    };
   };
-};
 }
diff --git a/install/overlays.nix b/install/overlays.nix
new file mode 100644 (file)
index 0000000..9e61eec
--- /dev/null
@@ -0,0 +1,3 @@
+map import
+[ #overlays/servers/mail/dovecot.nix
+]
index a5db44cea18a88231ae3fc7411ecdd2ed431dfee..d0cd49729a462fc7836e37c2138d5069cb39beaa 100644 (file)
@@ -1,15 +1,24 @@
 {
-friot = {pkgs, config, ...}: {
-  deployment.targetHost = "1.2.3.4";
-  networking.zones = {
-    net = {
-      iface = null;
-      ipv4  = null;
+  friot = {pkgs, config, ...}: {
+    deployment.targetHost = "1.2.3.4";
+    deployment.autoLuks = {
+      # NOTE: not working on virtualbox deployment
+      secretdisk = {
+        device     = "/dev/sda";
+        passphrase = "foobar";
+        autoFormat = true;
+        cipher     = "aes-cbc-essiv:sha256";
+      };
     };
-    lan = {
-      iface = null;
-      ipv4  = null;
+    networking.zones = {
+      net = {
+        iface = null;
+        ipv4  = null;
+      };
+      lan = {
+        iface = null;
+        ipv4  = null;
+      };
     };
   };
-};
 }
index a3a117a8b245a2503c853484997841c6305abd39..c100cff0661de1d8645b2dd1c1980bca9aa96157 100644 (file)
@@ -1,50 +1,40 @@
 {
-network.rollBack = false;
-friot = {pkgs, lib, config, options, ...}:
-let ipv4 = if options.networking.privateIPv4.isDefined
-           then config.networking.privateIPv4
-           else "X.X.X.X";
-in
-{
-  config = {
-    deployment.targetEnv             = "virtualbox";
-    deployment.virtualbox.headless   = true;
-    deployment.virtualbox.memorySize = 1024;
-    deployment.virtualbox.vcpu       = 2;
-    deployment.virtualbox.disks.disk1.baseImage = <sys/var/virtualbox/nixops.vmdk>;
-    #deployment.virtualbox.disks.disk1.size = 6024;
-     # NOTE: resize not yet supported.
+  network.rollBack = false;
+  friot = {pkgs, lib, config, options, ...}:
+    let ipv4 = if options.networking.privateIPv4.isDefined
+               then config.networking.privateIPv4
+               else "X.X.X.X";
+    in {
+    config = {
+      deployment.targetEnv             = "virtualbox";
+      deployment.virtualbox.headless   = true;
+      deployment.virtualbox.memorySize = 1024;
+      deployment.virtualbox.vcpu       = 2;
+      deployment.virtualbox.disks.disk1.baseImage = <sys/var/virtualbox/nixops.vmdk>;
+      #deployment.virtualbox.disks.disk1.size = 6024;
+       # NOTE: resize not yet supported.
 
-    deployment.storeKeysOnMachine = true;
-    deployment.autoLuks = {
-      # NOTE: not working on virtualbox deployment
-      secretdisk = {
-        device     = "/dev/sda";
-        passphrase = "foobar";
-        autoFormat = true;
-        cipher     = "aes-cbc-essiv:sha256";
-      };
-     };
-    networking = {
-      interfaces."enp0s8" = {
-        #macAddress = "00:11:22:33:44:55";
-        #ipv4.addresses = [ { address = ipv4; prefixLength = 32; } ];
-        ipv6.addresses = [ { address = "fe80::1"; prefixLength = 10; } ];
-      };
-      zones = {
-        net = {
-          iface = "enp0s3";
-          ipv4  = ipv4;
+      deployment.storeKeysOnMachine = true;
+      networking = {
+        interfaces."enp0s8" = {
+          #macAddress = "00:11:22:33:44:55";
+          #ipv4.addresses = [ { address = ipv4; prefixLength = 32; } ];
+          ipv6.addresses = [ { address = "fe80::1"; prefixLength = 10; } ];
         };
-        lan = {
-          iface = "enp0s8";
-          ipv4  = ipv4;
-          #ipv6  = "fe80::1";
+        zones = {
+          net = {
+            iface = "enp0s3";
+            ipv4  = ipv4;
+          };
+          lan = {
+            iface = "enp0s8";
+            ipv4  = ipv4;
+            #ipv6  = "fe80::1";
+          };
         };
       };
     };
   };
-};
 }
 
 #{