]> git.immae.eu Git - perso/Immae/Config/Nix.git/blobdiff - virtual/modules/websites/default.nix
Move some more configuration for websites
[perso/Immae/Config/Nix.git] / virtual / modules / websites / default.nix
diff --git a/virtual/modules/websites/default.nix b/virtual/modules/websites/default.nix
new file mode 100644 (file)
index 0000000..14b9998
--- /dev/null
@@ -0,0 +1,192 @@
+{ lib, pkgs, config, mylibs, myconfig, ... }:
+let
+  cfg = config.services.myWebsites;
+  makeService = name: cfg: let
+    toVhost = vhostConf: {
+      enableSSL = true;
+      sslServerCert = "/var/lib/acme/${vhostConf.certName}/cert.pem";
+      sslServerKey = "/var/lib/acme/${vhostConf.certName}/key.pem";
+      sslServerChain = "/var/lib/acme/${vhostConf.certName}/fullchain.pem";
+      logFormat = "combinedVhost";
+      listen = [
+        { ip = cfg.ip;  port = 443; }
+      ];
+      hostName = builtins.head vhostConf.hosts;
+      serverAliases = builtins.tail vhostConf.hosts or [];
+      documentRoot = vhostConf.root;
+      extraConfig = builtins.concatStringsSep "\n" vhostConf.extraConfig;
+    };
+  in rec {
+    enable = true;
+    listen = [
+      { ip = cfg.ip;  port = 443; }
+    ];
+    stateDir = "/run/httpd_${name}";
+    logPerVirtualHost = true;
+    multiProcessingModule = "worker";
+    adminAddr = "httpd@immae.eu";
+    logFormat = "combinedVhost";
+    extraModules = pkgs.lib.lists.unique (pkgs.lib.lists.flatten cfg.modules);
+    extraConfig = builtins.concatStringsSep "\n" cfg.extraConfig;
+    virtualHosts = pkgs.lib.attrsets.mapAttrsToList (n: v: toVhost v) cfg.vhostConfs;
+  };
+  makeServiceOptions = name: ip: {
+    enable = lib.mkEnableOption "enable websites in ${name}";
+    ip = lib.mkOption {
+      type = lib.types.string;
+      default = ip;
+      description = "${name} ip to listen to";
+    };
+    modules = lib.mkOption {
+      type = lib.types.listOf (lib.types.str);
+      default = [];
+    };
+    extraConfig = lib.mkOption {
+      type = lib.types.listOf (lib.types.lines);
+      default = [];
+    };
+    vhostConfs = lib.mkOption {
+      type = lib.types.attrsOf (lib.types.submodule {
+        options = {
+          certName = lib.mkOption { type = lib.types.string; };
+          hosts    = lib.mkOption { type = lib.types.listOf lib.types.string; };
+          root     = lib.mkOption { type = lib.types.nullOr lib.types.path; };
+          extraConfig = lib.mkOption { type = lib.types.listOf lib.types.lines; default = []; };
+        };
+      });
+    };
+  };
+in
+{
+  imports = [
+    ./chloe
+    ./ludivine
+    ./aten
+    ./piedsjaloux
+    ./connexionswing
+    # built using:
+    # sed -e "s/services\.httpd/services\.httpdProd/g" .nix-defexpr/channels/nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix
+    # And removed users / groups
+    ./apache/httpd_prod.nix
+    ./apache/httpd_inte.nix
+  ];
+
+  options.services.myWebsites = {
+    production = makeServiceOptions "production" myconfig.ips.production;
+    integration = makeServiceOptions "integration" myconfig.ips.integration;
+
+    apacheConfig = lib.mkOption {
+      type = lib.types.attrsOf (lib.types.submodule {
+        options = {
+          modules = lib.mkOption {
+            type = lib.types.listOf (lib.types.str);
+            default = [];
+          };
+          extraConfig = lib.mkOption {
+            type = lib.types.nullOr lib.types.lines;
+            default = null;
+          };
+        };
+      });
+      default = {};
+      description = "Extra global config";
+    };
+
+  };
+
+  config = {
+    networking = {
+      firewall = {
+        enable = true;
+        allowedTCPPorts = [ 80 443 ];
+      };
+      interfaces."eth0".ipv4.addresses = [
+        # 176.9.151.89 declared in nixops -> infra / tools
+        { address = myconfig.ips.production; prefixLength = 32; }
+        { address = myconfig.ips.integration; prefixLength = 32; }
+      ];
+    };
+
+    services.myWebsites.Chloe.production.enable = cfg.production.enable;
+    services.myWebsites.Ludivine.production.enable = cfg.production.enable;
+    services.myWebsites.Aten.production.enable = cfg.production.enable;
+    services.myWebsites.PiedsJaloux.production.enable = cfg.production.enable;
+    services.myWebsites.Connexionswing.production.enable = cfg.production.enable;
+
+    services.myWebsites.Chloe.integration.enable = cfg.integration.enable;
+    services.myWebsites.Ludivine.integration.enable = cfg.integration.enable;
+    services.myWebsites.Aten.integration.enable = cfg.integration.enable;
+    services.myWebsites.PiedsJaloux.integration.enable = cfg.integration.enable;
+    services.myWebsites.Connexionswing.integration.enable = cfg.integration.enable;
+
+    services.myWebsites.apacheConfig = {
+      gzip = {
+        modules = [ "deflate" "filter" ];
+        extraConfig = ''
+          AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript
+        '';
+      };
+      macros = {
+        modules = [ "macro" ];
+      };
+      ldap = {
+        modules = [ "ldap" "authnz_ldap" ];
+        # FIXME: starttls
+        extraConfig = assert mylibs.checkEnv "NIXOPS_HTTP_LDAP_PASSWORD"; ''
+          <IfModule ldap_module>
+            LDAPSharedCacheSize 500000
+            LDAPCacheEntries 1024
+            LDAPCacheTTL 600
+            LDAPOpCacheEntries 1024
+            LDAPOpCacheTTL 600
+          </IfModule>
+
+          <Macro LDAPConnect>
+            <IfModule authnz_ldap_module>
+              AuthLDAPURL          ldap://ldap.immae.eu:389/dc=immae,dc=eu STARTTLS
+              AuthLDAPBindDN       cn=httpd,ou=services,dc=immae,dc=eu
+              AuthLDAPBindPassword "${builtins.getEnv "NIXOPS_HTTP_LDAP_PASSWORD"}"
+              AuthType             Basic
+              AuthName             "Authentification requise (Acces LDAP)"
+              AuthBasicProvider    ldap
+            </IfModule>
+          </Macro>
+
+          <Macro Stats %{domain}>
+            Alias /awstats /var/lib/goaccess/%{domain}
+            <Directory /var/lib/goaccess/%{domain}>
+              DirectoryIndex index.html
+              AllowOverride None
+              Require all granted
+            </Directory>
+            <Location /awstats>
+              Use LDAPConnect
+              Require ldap-group cn=%{domain},ou=stats,cn=httpd,ou=services,dc=immae,dc=eu
+            </Location>
+          </Macro>
+        '';
+      };
+      http2 = {
+        modules = [ "http2" ];
+        extraConfig = ''
+          Protocols h2 http/1.1
+        '';
+      };
+      customLog = {
+        extraConfig = ''
+          LogFormat "%v:%p %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combinedVhost
+        '';
+      };
+    };
+
+    # FIXME: logrotate
+    # FIXME: ipv6
+    services.httpdProd = makeService "production" config.services.myWebsites.production;
+    services.myWebsites.production.modules = pkgs.lib.lists.flatten (pkgs.lib.attrsets.mapAttrsToList (n: v: v.modules or []) cfg.apacheConfig);
+    services.myWebsites.production.extraConfig = (builtins.filter (x: x != null) (pkgs.lib.attrsets.mapAttrsToList (n: v: v.extraConfig or null) cfg.apacheConfig));
+
+    services.httpdInte = makeService "integration" config.services.myWebsites.integration;
+    services.myWebsites.integration.modules = pkgs.lib.lists.flatten (pkgs.lib.attrsets.mapAttrsToList (n: v: v.modules or []) cfg.apacheConfig);
+    services.myWebsites.integration.extraConfig = (builtins.filter (x: x != null) (pkgs.lib.attrsets.mapAttrsToList (n: v: v.extraConfig or null) cfg.apacheConfig));
+  };
+}