]> git.immae.eu Git - perso/Immae/Config/Nix.git/blobdiff - flakes/private/environment/flake.nix
Squash changes containing private information
[perso/Immae/Config/Nix.git] / flakes / private / environment / flake.nix
diff --git a/flakes/private/environment/flake.nix b/flakes/private/environment/flake.nix
new file mode 100644 (file)
index 0000000..15c079a
--- /dev/null
@@ -0,0 +1,1135 @@
+{
+  outputs = { self }: {
+    nixosModule = self.nixosModules.environment;
+    nixosModules.environment = { config, lib, name, ... }:
+      with lib;
+      with types;
+      with lists;
+      let
+        ldapOptions = {
+          base = mkOption { description = "Base of the LDAP tree"; type = str; };
+          host = mkOption { description = "Host to access LDAP"; type = str; };
+          root_dn = mkOption { description = "DN of the root user"; type = str; };
+          root_pw = mkOption { description = "Hashed password of the root user"; type = str; };
+          replication_dn = mkOption { description = "DN of the user allowed to replicate the LDAP directory"; type = str; };
+          replication_pw = mkOption { description = "Password of the user allowed to replicate the LDAP directory"; type = str; };
+        };
+        mkLdapOptions = name: more: mkOption {
+          description = "${name} LDAP configuration";
+          type = submodule {
+            options = ldapOptions // {
+              dn = mkOption { description = "DN of the ${name} user"; type = str; };
+              password = mkOption { description = "password of the ${name} user"; type = str; };
+              filter = mkOption { description = "Filter for ${name} users"; type = str; default = ""; };
+            } // more;
+          };
+        };
+        mysqlOptions = {
+          host = mkOption { description = "Host to access Mysql"; type = str; };
+          remoteHost = mkOption { description = "Host to access Mysql from outside"; type = str; };
+          port = mkOption { description = "Port to access Mysql"; type = int; };
+          socket = mkOption { description = "Socket to access Mysql"; type = path; };
+          systemUsers = mkOption {
+            description = "Attrs of user-passwords allowed to access mysql";
+            type = attrsOf str;
+          };
+          pam = mkOption {
+            description = "PAM configuration for mysql";
+            type = submodule {
+              options = {
+                dn = mkOption { description = "DN to connect as to check users"; type = str; };
+                password = mkOption { description = "DN password to connect as to check users"; type = str; };
+                filter = mkOption { description = "filter to match users"; type = str; };
+              };
+            };
+          };
+        };
+        mkMysqlOptions = name: more: mkOption {
+          description = "${name} mysql configuration";
+          type = submodule {
+            options = mysqlOptions // {
+              database = mkOption { description = "${name} database"; type = str; };
+              user = mkOption { description = "${name} user"; type = str; };
+              password = mkOption { description = "mysql password of the ${name} user"; type = str; };
+            } // more;
+          };
+        };
+        psqlOptions = {
+          host = mkOption { description = "Host to access Postgresql"; type = str; };
+          port = mkOption { description = "Port to access Postgresql"; type = str; };
+          socket = mkOption { description = "Socket to access Postgresql"; type = path; };
+          pam = mkOption {
+            description = "PAM configuration for psql";
+            type = submodule {
+              options = {
+                dn = mkOption { description = "DN to connect as to check users"; type = str; };
+                password = mkOption { description = "DN password to connect as to check users"; type = str; };
+                filter = mkOption { description = "filter to match users"; type = str; };
+              };
+            };
+          };
+        };
+        mkPsqlOptions = name: mkOption {
+          description = "${name} psql configuration";
+          type = submodule {
+            options = psqlOptions // {
+              database = mkOption { description = "${name} database"; type = str; };
+              schema = mkOption { description = "${name} schema"; type = nullOr str; default = null; };
+              user = mkOption { description = "${name} user"; type = str; };
+              password = mkOption { description = "psql password of the ${name} user"; type = str; };
+            };
+          };
+        };
+        redisOptions = {
+          host = mkOption { description = "Host to access Redis"; type = str; };
+          port = mkOption { description = "Port to access Redis"; type = str; };
+          socket = mkOption { description = "Socket to access Redis"; type = path; };
+          dbs = mkOption {
+            description = "Attrs of db number. Each number should be unique to avoid collision!";
+            type = attrsOf str;
+          };
+          spiped_key = mkOption {
+            type = str;
+            description = ''
+              Key to use with spiped to make a secure channel to replication
+              '';
+          };
+          predixy = mkOption {
+            description = "Predixy configuration. Unused yet";
+            type = submodule {
+              options = {
+                read = mkOption { type = str; description = "Read password"; };
+              };
+            };
+          };
+        };
+        mkRedisOptions = name: mkOption {
+          description = "${name} redis configuration";
+          type = submodule {
+            options = redisOptions // {
+              db = mkOption { description = "${name} database"; type = str; };
+            };
+          };
+        };
+        smtpOptions = {
+          host = mkOption { description = "Host to access SMTP"; type = str; };
+          port = mkOption { description = "Port to access SMTP"; type = str; };
+        };
+        mkSmtpOptions = name: mkOption {
+          description = "${name} smtp configuration";
+          type = submodule {
+            options = smtpOptions // {
+              email = mkOption { description = "${name} email"; type = str; };
+              password = mkOption { description = "SMTP password of the ${name} user"; type = str; };
+            };
+          };
+        };
+        hostEnv = submodule {
+          options = {
+            fqdn = mkOption {
+              description = "Host FQDN";
+              type = str;
+            };
+            hostKey = mkOption {
+              type = nullOr str;
+              default = null;
+              description = ''
+                ssh host key
+              '';
+            };
+            isVm = mkEnableOption "The host is a vm";
+            users = mkOption {
+              type = unspecified;
+              default = pkgs: [];
+              description = ''
+                Sublist of users from realUsers. Function that takes pkgs as
+                argument and gives an array as a result
+              '';
+            };
+            emails = mkOption {
+              default = [];
+              description = "List of e-mails that the server can be a sender of";
+              type = listOf str;
+            };
+            ldap = mkOption {
+              description = ''
+                LDAP credentials for the host
+              '';
+              type = submodule {
+                options = {
+                  password = mkOption { type = str; description = "Password for the LDAP connection"; };
+                  dn = mkOption { type = str; description = "DN for the LDAP connection"; };
+                };
+              };
+            };
+            mx = mkOption {
+              description = "subdomain and priority for MX server";
+              default = { enable = false; };
+              type = submodule {
+                options = {
+                  enable = mkEnableOption "Enable MX";
+                  subdomain = mkOption { type = nullOr str; description = "Subdomain name (mx-*)"; };
+                  priority = mkOption { type = nullOr int; description = "Priority"; };
+                };
+              };
+            };
+            ips = mkOption {
+              description = ''
+                attrs of ip4/ip6 grouped by section
+              '';
+              type = attrsOf (submodule {
+                options = {
+                  alias = mkOption {
+                    type = nullOr str;
+                    default = null;
+                    description = ''
+                      alias to use in DNS for that group
+                    '';
+                  };
+                  ip4 = mkOption {
+                    type = listOf str;
+                    default = [];
+                    description = ''
+                      ip4 addresses of the host
+                    '';
+                  };
+                  ip6 = mkOption {
+                    type = listOf str;
+                    default = [];
+                    description = ''
+                      ip6 addresses of the host
+                    '';
+                  };
+                };
+              });
+            };
+          };
+        };
+      in
+      {
+        # Necessary for situations where flake gets included multiple times
+        key = builtins.hashString "sha256" (builtins.path { path = self.sourceInfo.outPath; name = "source"; });
+
+        options.myEnv = {
+          servers = mkOption {
+            description = ''
+              Attrs of servers information in the cluster (not necessarily handled by nixops)
+            '';
+            default = {};
+            type = attrsOf hostEnv;
+          };
+          hetznerCloud = mkOption {
+            description = ''
+              Hetzner Cloud credential information
+            '';
+            type = submodule {
+              options = {
+                authToken = mkOption {
+                  type = str;
+                  description = ''
+                    The API auth token.
+                  '';
+                };
+              };
+            };
+          };
+          hetzner = mkOption {
+            description = ''
+              Hetzner credential information
+            '';
+            type = submodule {
+              options = {
+                user = mkOption { type = str; description = "User"; };
+                pass = mkOption { type = str; description = "Password"; };
+              };
+            };
+          };
+          sshd = mkOption {
+            description = ''
+              sshd service credential information
+            '';
+            type = submodule {
+              options = {
+                rootKeys = mkOption { type = attrsOf str; description = "Keys of root users"; };
+                ldap = mkOption {
+                  description = ''
+                    LDAP credentials for cn=ssh,ou=services,dc=immae,dc=eu dn
+                  '';
+                  type = submodule {
+                    options = {
+                      password = mkOption { description = "Password"; type = str; };
+                    };
+                  };
+                };
+                psql = mkOption {
+                  description = ''
+                    PSQL credentials for immae_auth_read
+                  '';
+                  type = submodule {
+                    options = {
+                      password = mkOption { description = "Password"; type = str; };
+                    };
+                  };
+                };
+              };
+            };
+          };
+          ports = mkOption {
+            description = ''
+              non-standard reserved ports. Must be unique!
+            '';
+            type = attrsOf port;
+            default = {};
+            apply = let
+              noDupl = x: builtins.length (builtins.attrValues x) == builtins.length (unique (builtins.attrValues x));
+            in
+              x: if isAttrs x && noDupl x then x else throw "Non unique values for ports";
+          };
+          httpd = mkOption {
+            description = ''
+              httpd service credential information
+            '';
+            type = submodule {
+              options = {
+                ldap = mkOption {
+                  description = ''
+                    LDAP credentials for cn=httpd,ou=services,dc=immae,dc=eu dn
+                  '';
+                  type = submodule {
+                    options = {
+                      password = mkOption { description = "Password"; type = str; };
+                    };
+                  };
+                };
+              };
+            };
+          };
+          smtp = mkOption {
+            type = submodule { options = smtpOptions; };
+            description = "SMTP configuration";
+          };
+          ldap = mkOption {
+            description = ''
+              LDAP server configuration
+              '';
+            type = submodule {
+              options = ldapOptions;
+            };
+          };
+          databases = mkOption {
+            description = "Databases configuration";
+            type = submodule {
+              options = {
+                mysql = mkOption {
+                  type = submodule { options = mysqlOptions; };
+                  description = "Mysql configuration";
+                };
+                redis = mkOption {
+                  type = submodule { options = redisOptions; };
+                  description = "Redis configuration";
+                };
+                postgresql = mkOption {
+                  type = submodule { options = psqlOptions; };
+                  description = "Postgresql configuration";
+                };
+              };
+            };
+          };
+          jabber = mkOption {
+            description = "Jabber configuration";
+            type = submodule {
+              options = {
+                postfix_user_filter = mkOption { type = str; description = "Postfix filter to get xmpp users"; };
+                ldap = mkLdapOptions "Jabber" {};
+                postgresql = mkPsqlOptions "Jabber";
+              };
+            };
+          };
+          realUsers = mkOption {
+            description = ''
+              Attrset of function taking pkgs as argument.
+              Real users settings, should provide a subattr of users.users.<name>
+              with at least: name, (hashed)Password, shell
+            '';
+            type = attrsOf unspecified;
+          };
+          users = mkOption {
+            description = "System and regular users uid/gid";
+            type = attrsOf (submodule {
+              options = {
+                uid = mkOption {
+                  description = "user uid";
+                  type = int;
+                };
+                gid = mkOption {
+                  description = "user gid";
+                  type = int;
+                };
+              };
+            });
+          };
+          dns = mkOption {
+            description = "DNS configuration";
+            type = submodule {
+              options = {
+                ns = mkOption {
+                  description = "Attrs of NS servers group";
+                  example = {
+                    foo = {
+                      "ns1.foo.com" = [ "198.51.100.10" "2001:db8:abcd::1" ];
+                      "ns2.foo.com" = [ "198.51.100.15" "2001:db8:1234::1" ];
+                    };
+                  };
+                  type = attrsOf (attrsOf (listOf str));
+                };
+              };
+            };
+          };
+          backup = mkOption {
+            description = ''
+              Remote backup with duplicity
+              '';
+            type = submodule {
+              options = {
+                password = mkOption { type = str; description = "Password for encrypting files"; };
+                remotes = mkOption {
+                  type = attrsOf (submodule {
+                    options = {
+                      remote = mkOption {
+                        type = functionTo str;
+                        example = literalExample ''
+                          bucket: "s3://some_host/${bucket}";
+                          '';
+                        description = ''
+                          Function.
+                          Takes a bucket name as argument and returns a url
+                          '';
+                      };
+                      accessKeyId = mkOption { type = str; description = "Remote access-key"; };
+                      secretAccessKey = mkOption { type = str; description = "Remote access secret"; };
+                    };
+                  });
+                };
+              };
+            };
+          };
+          zrepl_backup = mkOption {
+            type = submodule {
+              options = {
+                ssh_key = mkOption {
+                  description = "SSH key information";
+                  type = submodule {
+                    options = {
+                      public = mkOption { type = str; description = "Public part of the key"; };
+                      private = mkOption { type = lines; description = "Private part of the key"; };
+                    };
+                  };
+                };
+                mysql = mkMysqlOptions "Zrepl" {};
+                certs = mkOption {
+                  description = "Certificates";
+                  type = attrsOf (submodule {
+                    options = {
+                      key = mkOption { type = str; description = "Key"; };
+                      certificate = mkOption { type = str; description = "Certificate"; };
+                    };
+                  });
+                };
+              };
+            };
+          };
+          rsync_backup = mkOption {
+            description  =''
+              Rsync backup configuration from controlled host
+              '';
+            type = submodule {
+              options = {
+                ssh_key = mkOption {
+                  description = "SSH key information";
+                  type = submodule {
+                    options = {
+                      public = mkOption { type = str; description = "Public part of the key"; };
+                      private = mkOption { type = lines; description = "Private part of the key"; };
+                    };
+                  };
+                };
+                profiles = mkOption {
+                  description = "Attrs of profiles to backup";
+                  default = {};
+                  type = attrsOf (submodule {
+                    options = {
+                      keep = mkOption { type = int; description = "Number of backups to keep"; };
+                      check_command = mkOption { type = str; description = "command to check if backup needs to be done"; default = "backup"; };
+                      login = mkOption { type = str; description = "Login to connect to host"; };
+                      port = mkOption { type = str; default = "22"; description = "Port to connect to host"; };
+                      host = mkOption { type = str; description = "Host to connect to"; };
+                      host_key = mkOption { type = str; description = "Host key"; };
+                      host_key_type = mkOption { type = str; description = "Host key type"; };
+                      parts = mkOption {
+                        description = "Parts to backup for this host";
+                        type = attrsOf (submodule {
+                          options = {
+                            remote_folder = mkOption { type = path; description = "Remote folder to backup";};
+                            exclude_from = mkOption {
+                              type = listOf path;
+                              default = [];
+                              description = "List of folders/files to exclude from the backup";
+                            };
+                            files_from = mkOption {
+                              type = listOf path;
+                              default = [];
+                              description = "List of folders/files to backup in the base folder";
+                            };
+                            args = mkOption {
+                              type = nullOr str;
+                              default = null;
+                              description = "Extra arguments to pass to rsync";
+                            };
+                          };
+                        });
+                      };
+                    };
+                  });
+                };
+              };
+            };
+          };
+          monitoring = mkOption {
+            description = "Monitoring configuration";
+            type = submodule {
+              options = {
+                status_url = mkOption { type = str; description = "URL to push status to"; };
+                status_token = mkOption { type = str; description = "Token for the status url"; };
+                http_user_password = mkOption { type = str; description = "HTTP credentials to check services behind wall"; };
+                email = mkOption { type = str; description = "Admin E-mail"; };
+                ssh_public_key = mkOption { type = str; description = "SSH public key"; };
+                ssh_secret_key = mkOption { type = str; description = "SSH secret key"; };
+                imap_login = mkOption { type = str; description = "IMAP login"; };
+                imap_password = mkOption { type = str; description = "IMAP password"; };
+                eriomem_keys = mkOption { type = listOf (listOf str); description = "Eriomem keys"; default = []; };
+                ovh_sms = mkOption {
+                  description = "OVH credentials for sms script";
+                  type = submodule {
+                    options = {
+                      endpoint = mkOption { type = str; default = "ovh-eu"; description = "OVH endpoint"; };
+                      application_key = mkOption { type = str; description = "Application key"; };
+                      application_secret = mkOption { type = str; description = "Application secret"; };
+                      consumer_key = mkOption { type = str; description = "Consumer key"; };
+                      account = mkOption { type = str; description = "Account"; };
+                    };
+                  };
+                };
+                nrdp_tokens = mkOption { type = listOf str; description = "Tokens allowed to push status update"; };
+                apprise_urls = mkOption { type = str; description = "Apprise space-separated urls to push status update"; };
+                netdata_aggregator = mkOption { type = str; description = "Url where netdata information should be sent"; };
+                netdata_keys = mkOption { type = attrsOf str; description = "netdata host keys"; };
+                immae_contact = mkOption { type = str; description = "Immae Contact e-mail"; };
+                email_check = mkOption {
+                  description = "Emails services to check";
+                  type = attrsOf (submodule {
+                    options = {
+                      local = mkOption { type = bool; default = false; description = "Use local configuration"; };
+                      port = mkOption { type = nullOr str; default = null; description = "Port to connect to ssh"; };
+                      login = mkOption { type = nullOr str; default = null; description = "Login to connect to ssh"; };
+                      targets = mkOption { type = listOf str; description = "Hosts to send E-mails to"; };
+                      mail_address = mkOption { type = nullOr str; default = null; description = "E-mail recipient part to send e-mail to"; };
+                      mail_domain = mkOption { type = nullOr str; default = null; description = "E-mail domain part to send e-mail to"; };
+                    };
+                  });
+                };
+              };
+            };
+          };
+          mpd = mkOption {
+            description = "MPD configuration";
+            type = submodule {
+              options = {
+                folder = mkOption { type = str; description = "Folder to serve from the MPD instance"; };
+                password = mkOption { type = str; description = "Password to connect to the MPD instance"; };
+                host = mkOption { type = str; description = "Host to connect to the MPD instance"; };
+                port = mkOption { type = str; description = "Port to connect to the MPD instance"; };
+              };
+            };
+          };
+          ftp = mkOption {
+            description = "FTP configuration";
+            type = submodule {
+              options = {
+                ldap = mkLdapOptions "FTP" {
+                  proftpd_filter = mkOption { type = str; description = "Filter for proftpd listing in LDAP"; };
+                  pure-ftpd_filter = mkOption { type = str; description = "Filter for pure-ftpd listing in LDAP"; };
+                };
+              };
+            };
+          };
+          vpn = mkOption {
+            description = "VPN configuration";
+            type = attrsOf (submodule {
+              options = {
+                prefix = mkOption { type = str; description = "ipv6 prefix for the vpn subnet"; };
+                privateKey = mkOption { type = str; description = "Private key for the host"; };
+                publicKey = mkOption { type = str; description = "Public key for the host"; };
+              };
+            });
+          };
+          mail = mkOption {
+            description = "Mail configuration";
+            type = submodule {
+              options = {
+                dmarc = mkOption {
+                  description = "DMARC configuration";
+                  type = submodule {
+                    options = {
+                      ignore_hosts = mkOption {
+                        type = lines;
+                        description = ''
+                          Hosts to ignore when checking for dmarc
+                          '';
+                      };
+                    };
+                  };
+                };
+                dkim = mkOption {
+                  description = "DKIM configuration";
+                  type = attrsOf (submodule {
+                    options = {
+                      public = mkOption {
+                        type = attrsOf str;
+                        example = literalExample ''
+                          {
+                            v = "DKIM1";
+                            k = "rsa";
+                            p = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC3w1a2aMxWw9+hdcmbqX4UevcVqr204y0K73Wdc7MPZiOOlUJQYsMNSYR1Y/SC7jmPKeitpcJCpQgn/cveJZbuikjjPLsDReHyFEYmC278ZLRTELHx6f1IXM8WE08JIRT69CfZiMi1rVcOh9qRT4F93PyjCauU8Y5hJjtg9ThsWwIDAQAB";
+                          }
+                          '';
+                        description = "Public entry to put in DNS TXT field";
+                      };
+                      private = mkOption { type = nullOr str; default = null; description = "Private key"; };
+                    };
+                  });
+                };
+                postfix = mkOption {
+                  description = "Postfix configuration";
+                  type = submodule {
+                    options = {
+                      mysql = mkMysqlOptions "Postfix" {
+                        password_encrypt = mkOption { type = str; description = "Key to encrypt relay password in database"; };
+                      };
+                      admins = mkOption {
+                        description = ''
+                          List of admins meant to receive common aliases
+                        '';
+                        type = listOf str;
+                      };
+                      common_aliases = mkOption {
+                        description = ''
+                          List of aliases common to all hosts, to forward to admins
+                        '';
+                        type = listOf str;
+                      };
+                      other_aliases = mkOption {
+                        description = ''
+                          Other list of aliases, to forward to admins
+                        '';
+                        type = listOf str;
+                      };
+                    };
+                  };
+                };
+                dovecot = mkOption {
+                  description = "Dovecot configuration";
+                  type = submodule {
+                    options = {
+                      ldap = mkLdapOptions "Dovecot" {
+                        pass_attrs = mkOption { type = str; description = "Password attribute in LDAP"; };
+                        user_attrs = mkOption { type = str; description = "User attribute mapping in LDAP"; };
+                        iterate_attrs = mkOption { type = str; description = "User attribute mapping for listing in LDAP"; };
+                        iterate_filter = mkOption { type = str; description = "User attribute filter for listing in LDAP"; };
+                        postfix_mailbox_filter = mkOption { type = str; description = "Postfix filter to get mailboxes"; };
+                      };
+                    };
+                  };
+                };
+                rspamd = mkOption {
+                  description = "rspamd configuration";
+                  type = submodule {
+                    options = {
+                      redis = mkRedisOptions "Redis";
+                      read_password_hashed = mkOption { type = str; description = "Hashed read password for rspamd"; };
+                      write_password_hashed = mkOption { type = str; description = "Hashed write password for rspamd"; };
+                      read_password = mkOption {
+                        type = str;
+                        description = "Read password for rspamd. Unused";
+                        apply = x: "";
+                      };
+                      write_password = mkOption {
+                        type = str;
+                        description = "Write password for rspamd. Unused";
+                        apply = x: "";
+                      };
+                    };
+                  };
+                };
+                sympa = mkOption {
+                  description = "Sympa configuration";
+                  type = submodule {
+                    options = {
+                      listmasters = mkOption {
+                        type = listOf str;
+                        description = "Listmasters";
+                      };
+                      postgresql = mkPsqlOptions "Sympa";
+                      data_sources = mkOption {
+                        type = attrsOf str;
+                        default = {};
+                        description = "Data sources to make available to sympa";
+                      };
+                      scenari = mkOption {
+                        type = attrsOf str;
+                        default = {};
+                        description = "Scenari to make available to sympa";
+                      };
+                    };
+                  };
+                };
+              };
+            };
+          };
+          coturn = mkOption {
+            description = "Coturn configuration";
+            type = submodule {
+              options = {
+                auth_access_key = mkOption { type = str; description = "key to access coturn"; };
+              };
+            };
+          };
+          buildbot = mkOption {
+            description = "Buildbot configuration";
+            type = submodule {
+              options = {
+                ssh_key = mkOption {
+                  description = "SSH key information";
+                  type = submodule {
+                    options = {
+                      public = mkOption { type = str; description = "Public part of the key"; };
+                      private = mkOption { type = lines; description = "Private part of the key"; };
+                    };
+                  };
+                };
+                workerPassword = mkOption { description = "Buildbot worker password"; type = str; };
+                user = mkOption {
+                  description = "Buildbot user";
+                  type = submodule {
+                    options = {
+                      uid = mkOption {
+                        description = "user uid";
+                        type = int;
+                      };
+                      gid = mkOption {
+                        description = "user gid";
+                        type = int;
+                      };
+                    };
+                  };
+                };
+                ldap = mkOption {
+                  description = "Ldap configuration for buildbot";
+                  type = submodule {
+                    options = {
+                      password = mkOption { type = str; description = "Buildbot password"; };
+                    };
+                  };
+                };
+                projects = mkOption {
+                  description = "Projects to make a buildbot for";
+                  type = attrsOf (submodule {
+                    options = {
+                      name = mkOption { type = str; description = "Project name"; };
+                      src = mkOption { type = path; description = "source of the project configuration"; };
+                      packages = mkOption {
+                        type = listOf package;
+                        example = literalExample ''
+                          [ pkgs.bash pkgs.git pkgs.gzip pkgs.openssh ];
+                          '';
+                        description = ''
+                          Builds packages list to make available to buildbot project.
+                        '';
+                      };
+                      pythonPathHome = mkOption { type = bool; description = "Whether to add project’s python home to python path"; };
+                      workerPort = mkOption { type = port; description = "Port for the worker"; };
+                      secrets = mkOption {
+                        type = attrsOf lines;
+                        description = "Secrets for the project to dump as files";
+                      };
+                      secretsDeps = mkOption {
+                        type = listOf package;
+                        default = [];
+                        description = "Dependencies of file that will land in secrets";
+                      };
+                      environment = mkOption {
+                        type = attrsOf str;
+                        description = ''
+                          Environment variables for the project.
+                          BUILDBOT_ is prefixed to the variable names
+                        '';
+                      };
+                      activationScript = mkOption {
+                        type = lines;
+                        description = ''
+                          Activation script to run during deployment
+                        '';
+                      };
+                      webhookTokens = mkOption {
+                        type = nullOr (listOf str);
+                        default = null;
+                        description = ''
+                          List of tokens allowed to push to project’s change_hook/base endpoint
+                        '';
+                      };
+                    };
+                  });
+                };
+              };
+            };
+          };
+          tools = mkOption {
+            description = "Tools configurations";
+            type = submodule {
+              options = {
+                contact = mkOption { type = str; description = "Contact e-mail address"; };
+                assets = mkOption {
+                  default = {};
+                  type = attrsOf (submodule {
+                    options = {
+                      assetType = mkOption { type = enum ["tgz" "url" "googleFont"]; default = "url"; description = "Type of asset"; };
+                      tgzRemoveComponents = mkOption { type = int; default = 0; description = "Remove components when extracting"; };
+                      url = mkOption { type = str; description = "URL to fetch"; };
+                      sha256 = mkOption { type = str; description = "Hash of the url"; };
+                    };
+                  });
+                  description = "Assets to provide on assets.immae.eu";
+                };
+                davical = mkOption {
+                  description = "Davical configuration";
+                  type = submodule {
+                    options = {
+                      postgresql = mkPsqlOptions "Davical";
+                      ldap = mkLdapOptions "Davical" {};
+                    };
+                  };
+                };
+                diaspora = mkOption {
+                  description = "Diaspora configuration";
+                  type = submodule {
+                    options = {
+                      postgresql = mkPsqlOptions "Diaspora";
+                      redis = mkRedisOptions "Diaspora";
+                      ldap = mkLdapOptions "Diaspora" {};
+                      secret_token = mkOption { type = str; description = "Secret token"; };
+                    };
+                  };
+                };
+                dmarc_reports = mkOption {
+                  description = "DMARC reports configuration";
+                  type = submodule {
+                    options = {
+                      mysql = mkMysqlOptions "DMARC" {};
+                      anonymous_key = mkOption { type = str; description = "Anonymous hashing key"; };
+                    };
+                  };
+                };
+                etherpad-lite = mkOption {
+                  description = "Etherpad configuration";
+                  type = submodule {
+                    options = {
+                      postgresql = mkPsqlOptions "Etherpad";
+                      ldap = mkLdapOptions "Etherpad" {
+                        group_filter = mkOption { type = str; description = "Filter for groups"; };
+                      };
+                      adminPassword = mkOption { type = str; description = "Admin password for mypads / admin"; };
+                      session_key = mkOption { type = str; description = "Session key"; };
+                      api_key = mkOption { type = str; description = "API key"; };
+                    };
+                  };
+                };
+                gitolite = mkOption {
+                  description = "Gitolite configuration";
+                  type = submodule {
+                    options = {
+                      ldap = mkLdapOptions "Gitolite" {};
+                      ssh_key = mkOption {
+                        description = "SSH key information";
+                        type = submodule {
+                          options = {
+                            public = mkOption { type = str; description = "Public part of the key"; };
+                            private = mkOption { type = lines; description = "Private part of the key"; };
+                          };
+                        };
+                      };
+                    };
+                  };
+                };
+                landing = mkOption {
+                  description = "Landing configuration";
+                  type = submodule {
+                    options = {
+                      postgresql = mkPsqlOptions "Landing";
+                    };
+                  };
+                };
+                kanboard = mkOption {
+                  description = "Kanboard configuration";
+                  type = submodule {
+                    options = {
+                      postgresql = mkPsqlOptions "Kanboard";
+                      ldap = mkLdapOptions "Kanboard" {
+                        admin_dn = mkOption { type = str; description = "Admin DN"; };
+                      };
+                    };
+                  };
+                };
+                mantisbt = mkOption {
+                  description = "Mantisbt configuration";
+                  type = submodule {
+                    options = {
+                      postgresql = mkPsqlOptions "Mantisbt";
+                      ldap = mkLdapOptions "Mantisbt" {};
+                      master_salt = mkOption { type = str; description = "Master salt for password hash"; };
+                    };
+                  };
+                };
+                mastodon = mkOption {
+                  description = "Mastodon configuration";
+                  type = submodule {
+                    options = {
+                      postgresql = mkPsqlOptions "Mastodon";
+                      redis = mkRedisOptions "Mastodon";
+                      ldap = mkLdapOptions "Mastodon" {};
+                      paperclip_secret = mkOption { type = str; description = "Paperclip secret"; };
+                      otp_secret = mkOption { type = str; description = "OTP secret"; };
+                      secret_key_base = mkOption { type = str; description = "Secret key base"; };
+                      vapid = mkOption {
+                        description = "vapid key";
+                        type = submodule {
+                          options = {
+                            private = mkOption { type = str; description = "Private key"; };
+                            public = mkOption { type = str; description = "Public key"; };
+                          };
+                        };
+                      };
+                    };
+                  };
+                };
+                mediagoblin = mkOption {
+                  description = "Mediagoblin configuration";
+                  type = submodule {
+                    options = {
+                      postgresql = mkPsqlOptions "Mediagoblin";
+                      redis = mkRedisOptions "Mediagoblin";
+                      ldap = mkLdapOptions "Mediagoblin" {};
+                    };
+                  };
+                };
+                nextcloud = mkOption {
+                  description = "Nextcloud configuration";
+                  type = submodule {
+                    options = {
+                      postgresql = mkPsqlOptions "Nextcloud";
+                      redis = mkRedisOptions "Nextcloud";
+                      password_salt = mkOption { type = str; description = "Password salt"; };
+                      instance_id = mkOption { type = str; description = "Instance ID"; };
+                      secret = mkOption { type = str; description = "App secret"; };
+                    };
+                  };
+                };
+                peertube = mkOption {
+                  description = "Peertube configuration";
+                  type = submodule {
+                    options = {
+                      listenPort = mkOption { type = port; description = "Port to listen to"; };
+                      postgresql = mkPsqlOptions "Peertube";
+                      redis = mkRedisOptions "Peertube";
+                      ldap = mkLdapOptions "Peertube" {};
+                    };
+                  };
+                };
+                phpldapadmin = mkOption {
+                  description = "phpLdapAdmin configuration";
+                  type = submodule {
+                    options = {
+                      ldap = mkLdapOptions "phpldapadmin" {};
+                    };
+                  };
+                };
+                rompr = mkOption {
+                  description = "Rompr configuration";
+                  type = submodule {
+                    options = {
+                      mpd = mkOption {
+                        description = "MPD configuration";
+                        type = submodule {
+                          options = {
+                            host = mkOption { type = str; description = "Host for MPD"; };
+                            port = mkOption { type = port; description = "Port to access MPD host"; };
+                          };
+                        };
+                      };
+                    };
+                  };
+                };
+                roundcubemail = mkOption {
+                  description = "Roundcubemail configuration";
+                  type = submodule {
+                    options = {
+                      postgresql = mkPsqlOptions "TT-RSS";
+                      secret = mkOption { type = str; description = "Secret"; };
+                    };
+                  };
+                };
+                shaarli = mkOption {
+                  description = "Shaarli configuration";
+                  type = submodule {
+                    options = {
+                      ldap = mkLdapOptions "Shaarli" {};
+                    };
+                  };
+                };
+                status_engine = mkOption {
+                  description = "Status Engine configuration";
+                  type = submodule {
+                    options = {
+                      mysql = mkMysqlOptions "StatusEngine" {};
+                      ldap = mkLdapOptions "StatusEngine" {};
+                    };
+                  };
+                };
+                task = mkOption {
+                  description = "Taskwarrior configuration";
+                  type = submodule {
+                    options = {
+                      ldap = mkLdapOptions "Taskwarrior" {};
+                      taskwarrior-web = mkOption {
+                        description = "taskwarrior-web profiles";
+                        default = {};
+                        type = attrsOf (submodule {
+                          options = {
+                            uid = mkOption {
+                              type = listOf str;
+                              description = "List of ldap uids having access to this profile";
+                            };
+                            org = mkOption { type = str; description = "Taskd organisation"; };
+                            key = mkOption { type = str; description = "Taskd key"; };
+                            date = mkOption { type = str; description = "Preferred date format"; };
+                          };
+                        });
+                      };
+                    };
+                  };
+                };
+                ttrss = mkOption {
+                  description = "TT-RSS configuration";
+                  type = submodule {
+                    options = {
+                      postgresql = mkPsqlOptions "TT-RSS";
+                      ldap = mkLdapOptions "TT-RSS" {};
+                    };
+                  };
+                };
+                wallabag = mkOption {
+                  description = "Wallabag configuration";
+                  type = submodule {
+                    options = {
+                      postgresql = mkPsqlOptions "Wallabag";
+                      ldap = mkLdapOptions "Wallabag" {
+                        admin_filter = mkOption { type = str; description = "Admin users filter"; };
+                      };
+                      redis = mkRedisOptions "Wallabag";
+                      secret = mkOption { type = str; description = "App secret"; };
+                    };
+                  };
+                };
+                webhooks = mkOption {
+                  type = attrsOf str;
+                  description = "Mapping 'name'.php => script for webhooks";
+                };
+                csp_reports = mkOption {
+                  description = "CSP report configuration";
+                  type = submodule {
+                    options = {
+                      report_uri = mkOption { type = str; description = "URI to report CSP violations to"; };
+                      policies = mkOption { type = attrsOf str; description = "CSP policies to apply"; };
+                    };
+                  };
+                };
+                commento = mkOption {
+                  description = "Commento configuration";
+                  type = submodule {
+                    options = {
+                      listenPort = mkOption { type = port; description = "Port to listen to"; };
+                      postgresql = mkPsqlOptions "Commento";
+                      smtp = mkSmtpOptions "Commento";
+                    };
+                  };
+                };
+                cryptpad = mkOption {
+                  description = "Cryptpad configuration";
+                  type = submodule {
+                    options = {
+                      email = mkOption { type = str; description = "Admin e-mail"; };
+                      admins = mkOption { type = listOf str; description = "Instance admin public keys"; };
+                      port = mkOption { type = port; description = "Port to listen to"; };
+                    };
+                  };
+                };
+                ympd = mkOption {
+                  description = "Ympd configuration";
+                  type = submodule {
+                    options = {
+                      listenPort = mkOption { type = port; description = "Port to listen to"; };
+                      mpd = mkOption {
+                        description = "MPD configuration";
+                        type = submodule {
+                          options = {
+                            password = mkOption { type = str; description = "Password to access MPD host"; };
+                            host = mkOption { type = str; description = "Host for MPD"; };
+                            port = mkOption { type = port; description = "Port to access MPD host"; };
+                          };
+                        };
+                      };
+                    };
+                  };
+                };
+                umami = mkOption {
+                  description = "Umami configuration";
+                  type = submodule {
+                    options = {
+                      listenPort = mkOption { type = port; description = "Port to listen to"; };
+                      postgresql = mkPsqlOptions "Umami";
+                      hashSalt = mkOption { type = str; description = "Hash salt"; };
+                    };
+                  };
+                };
+                yourls = mkOption {
+                  description = "Yourls configuration";
+                  type = submodule {
+                    options = {
+                      mysql = mkMysqlOptions "Yourls" {};
+                      ldap = mkLdapOptions "Yourls" {};
+                      cookieKey = mkOption { type = str; description = "Cookie key"; };
+                    };
+                  };
+                };
+              };
+            };
+          };
+          serverSpecific = mkOption { type = attrsOf unspecified; description = "Server specific configuration"; };
+        };
+        options.hostEnv = mkOption {
+          readOnly = true;
+          type = hostEnv;
+          default = config.myEnv.servers."${name}";
+          description = "Host environment";
+        };
+      };
+  };
+}