]> git.immae.eu Git - perso/Immae/Config/Nix.git/blobdiff - modules/websites/default.nix
Upgrade nixos
[perso/Immae/Config/Nix.git] / modules / websites / default.nix
index 2e1d23a48764a50b16fe3210a461b08e1b4601fb..3f46e65dfb4890dabf2cc071b7c123ae764c03cd 100644 (file)
 { lib, config, ... }: with lib;
 let
-  cfg = {
-    certs = config.services.websitesCerts;
-    webappDirs = config.services.websitesWebappDirs;
-    env = config.services.websites;
-  };
+  cfg = config.services.websites;
 in
 {
-  options.services.websitesCerts = mkOption {
-    description = "Default websites configuration for certificates as accepted by acme";
-  };
-  options.services.websitesWebappDirs = mkOption {
-    description = ''
-      Defines a symlink between /run/current-system/webapps and a store
-      app directory to be used in http configuration. Permits to avoid
-      restarting httpd when only the folder name changes.
-      '';
-    type = types.attrsOf types.path;
-    default = {};
-  };
-  # TODO: ajouter /run/current-system/webapps (RO) et webapps (RW)
-  options.services.websites = with types; mkOption {
-    default = {};
-    description = "Each type of website to enable will target a distinct httpd server";
-    type = attrsOf (submodule {
-      options = {
-        enable = mkEnableOption "Enable websites of this type";
-        adminAddr = mkOption {
-          type = str;
-          description = "Admin e-mail address of the instance";
-        };
-        httpdName = mkOption {
-          type = str;
-          description = "Name of the httpd instance to assign this type to";
-        };
-        ips = mkOption {
-          type = listOf string;
-          default = [];
-          description = "ips to listen to";
-        };
-        modules = mkOption {
-          type = listOf str;
-          default = [];
-          description = "Additional modules to load in Apache";
-        };
-        extraConfig = mkOption {
-          type = listOf lines;
-          default = [];
-          description = "Additional configuration to append to Apache";
-        };
-        nosslVhost = mkOption {
-          description = "A default nossl vhost for captive portals";
-          default = {};
-          type = submodule {
-            options = {
-              enable = mkEnableOption "Add default no-ssl vhost for this instance";
-              host = mkOption {
-                type = string;
-                description = "The hostname to use for this vhost";
-              };
-              root = mkOption {
-                type = path;
-                default = ./nosslVhost;
-                description = "The root folder to serve";
-              };
-              indexFile = mkOption {
-                type = string;
-                default = "index.html";
-                description = "The index file to show.";
+  options.services.websites = with types; {
+    certs = mkOption {
+      description = "Default websites configuration for certificates as accepted by acme";
+    };
+    webappDirs = mkOption {
+      description = ''
+        Defines a symlink between /run/current-system/webapps and a store
+        app directory to be used in http configuration. Permits to avoid
+        restarting httpd when only the folder name changes.
+        '';
+      type = types.attrsOf types.path;
+      default = {};
+    };
+    webappDirsName = mkOption {
+      type = str;
+      default = "webapps";
+      description = ''
+        Name of the webapp dir to create in /run/current-system
+        '';
+    };
+    env = mkOption {
+      default = {};
+      description = "Each type of website to enable will target a distinct httpd server";
+      type = attrsOf (submodule {
+        options = {
+          enable = mkEnableOption "Enable websites of this type";
+          adminAddr = mkOption {
+            type = str;
+            description = "Admin e-mail address of the instance";
+          };
+          httpdName = mkOption {
+            type = str;
+            description = "Name of the httpd instance to assign this type to";
+          };
+          ips = mkOption {
+            type = listOf str;
+            default = [];
+            description = "ips to listen to";
+          };
+          modules = mkOption {
+            type = listOf str;
+            default = [];
+            description = "Additional modules to load in Apache";
+          };
+          extraConfig = mkOption {
+            type = listOf lines;
+            default = [];
+            description = "Additional configuration to append to Apache";
+          };
+          nosslVhost = mkOption {
+            description = "A default nossl vhost for captive portals";
+            default = {};
+            type = submodule {
+              options = {
+                enable = mkEnableOption "Add default no-ssl vhost for this instance";
+                host = mkOption {
+                  type = str;
+                  description = "The hostname to use for this vhost";
+                };
+                root = mkOption {
+                  type = path;
+                  default = ./nosslVhost;
+                  description = "The root folder to serve";
+                };
+                indexFile = mkOption {
+                  type = str;
+                  default = "index.html";
+                  description = "The index file to show.";
+                };
               };
             };
           };
-        };
-        fallbackVhost = mkOption {
-          description = "The fallback vhost that will be defined as first vhost in Apache";
-          type = submodule {
-            options = {
-              certName = mkOption { type = string; };
-              hosts    = mkOption { type = listOf string; };
-              root     = mkOption { type = nullOr path; };
-              extraConfig = mkOption { type = listOf lines; default = []; };
+          fallbackVhost = mkOption {
+            description = "The fallback vhost that will be defined as first vhost in Apache";
+            type = submodule {
+              options = {
+                certName = mkOption { type = str; };
+                hosts    = mkOption { type = listOf str; };
+                root     = mkOption { type = nullOr path; };
+                extraConfig = mkOption { type = listOf lines; default = []; };
+              };
             };
           };
-        };
-        vhostConfs = mkOption {
-          default = {};
-          description = "List of vhosts to define for Apache";
-          type = attrsOf (submodule {
-            options = {
-              certName = mkOption { type = string; };
-              addToCerts = mkOption {
-                type = bool;
-                default = false;
-                description = "Use these to certificates. Is ignored (considered true) if certMainHost is not null";
+          vhostNoSSLConfs = mkOption {
+            default = {};
+            description = "List of no ssl vhosts to define for Apache";
+            type = attrsOf (submodule {
+              options = {
+                hosts    = mkOption { type = listOf str; };
+                root     = mkOption { type = nullOr path; };
+                extraConfig = mkOption { type = listOf lines; default = []; };
               };
-              certMainHost = mkOption {
-                type = nullOr string;
-                description = "Use that host as 'main host' for acme certs";
-                default = null;
+            });
+          };
+          vhostConfs = mkOption {
+            default = {};
+            description = "List of vhosts to define for Apache";
+            type = attrsOf (submodule {
+              options = {
+                certName = mkOption { type = str; };
+                addToCerts = mkOption {
+                  type = bool;
+                  default = false;
+                  description = "Use these to certificates. Is ignored (considered true) if certMainHost is not null";
+                };
+                certMainHost = mkOption {
+                  type = nullOr str;
+                  description = "Use that host as 'main host' for acme certs";
+                  default = null;
+                };
+                hosts    = mkOption { type = listOf str; };
+                root     = mkOption { type = nullOr path; };
+                extraConfig = mkOption { type = listOf lines; default = []; };
               };
-              hosts    = mkOption { type = listOf string; };
-              root     = mkOption { type = nullOr path; };
-              extraConfig = mkOption { type = listOf lines; default = []; };
-            };
-          });
-        };
-        watchPaths = mkOption {
-          type = listOf string;
-          default = [];
-          description = ''
-            Paths to watch that should trigger a reload of httpd
-            '';
+            });
+          };
+          watchPaths = mkOption {
+            type = listOf str;
+            default = [];
+            description = ''
+              Paths to watch that should trigger a reload of httpd
+              '';
+          };
         };
-      };
-    });
+      });
+    };
+    # Readonly variables
+    webappDirsPaths = mkOption {
+      type = attrsOf path;
+      readOnly = true;
+      description = ''
+        Full paths of the webapp dir
+        '';
+      default = attrsets.mapAttrs' (name: icfg: attrsets.nameValuePair
+        name "/run/current-system/${cfg.webappDirsName}/${name}"
+      ) cfg.webappDirs;
+    };
   };
 
   config.services.httpd = let
@@ -123,7 +149,7 @@ in
       serverAliases = [ "*" ];
       enableSSL = false;
       logFormat = "combinedVhost";
-      documentRoot = "${config.security.acme.directory}/acme-challenge";
+      documentRoot = "/var/lib/acme/acme-challenge";
       extraConfig = ''
         RewriteEngine on
         RewriteCond "%{REQUEST_URI}"   "!^/\.well-known"
@@ -152,9 +178,9 @@ in
     };
     toVhost = ips: vhostConf: {
       enableSSL = true;
-      sslServerCert = "${config.security.acme.directory}/${vhostConf.certName}/cert.pem";
-      sslServerKey = "${config.security.acme.directory}/${vhostConf.certName}/key.pem";
-      sslServerChain = "${config.security.acme.directory}/${vhostConf.certName}/chain.pem";
+      sslServerCert = "${config.security.acme.certs."${vhostConf.certName}".directory}/cert.pem";
+      sslServerKey = "${config.security.acme.certs."${vhostConf.certName}".directory}/key.pem";
+      sslServerChain = "${config.security.acme.certs."${vhostConf.certName}".directory}/chain.pem";
       logFormat = "combinedVhost";
       listen = map (ip: { inherit ip; port = 443; }) ips;
       hostName = builtins.head vhostConf.hosts;
@@ -162,6 +188,15 @@ in
       documentRoot = vhostConf.root;
       extraConfig = builtins.concatStringsSep "\n" vhostConf.extraConfig;
     };
+    toVhostNoSSL = ips: vhostConf: {
+      enableSSL = false;
+      logFormat = "combinedVhost";
+      listen = map (ip: { inherit ip; port = 80; }) ips;
+      hostName = builtins.head vhostConf.hosts;
+      serverAliases = builtins.tail vhostConf.hosts or [];
+      documentRoot = vhostConf.root;
+      extraConfig = builtins.concatStringsSep "\n" vhostConf.extraConfig;
+    };
   in attrsets.mapAttrs' (name: icfg: attrsets.nameValuePair
     icfg.httpdName (mkIf icfg.enable {
       enable = true;
@@ -169,12 +204,21 @@ in
       stateDir = "/run/httpd_${name}";
       logPerVirtualHost = true;
       multiProcessingModule = "worker";
+      # https://ssl-config.mozilla.org/#server=apache&version=2.4.41&config=intermediate&openssl=1.0.2t&guideline=5.4
+      sslProtocols = "all -SSLv3 -TLSv1 -TLSv1.1";
+      sslCiphers = builtins.concatStringsSep ":" [
+        "ECDHE-ECDSA-AES128-GCM-SHA256" "ECDHE-RSA-AES128-GCM-SHA256"
+        "ECDHE-ECDSA-AES256-GCM-SHA384" "ECDHE-RSA-AES256-GCM-SHA384"
+        "ECDHE-ECDSA-CHACHA20-POLY1305" "ECDHE-RSA-CHACHA20-POLY1305"
+        "DHE-RSA-AES128-GCM-SHA256" "DHE-RSA-AES256-GCM-SHA384"
+      ];
       inherit (icfg) adminAddr;
       logFormat = "combinedVhost";
       extraModules = lists.unique icfg.modules;
       extraConfig = builtins.concatStringsSep "\n" icfg.extraConfig;
       virtualHosts = [ (toVhost icfg.ips icfg.fallbackVhost) ]
         ++ optionals (icfg.nosslVhost.enable) [ (nosslVhost icfg.ips icfg.nosslVhost) ]
+        ++ (attrsets.mapAttrsToList (n: v: toVhostNoSSL icfg.ips v) icfg.vhostNoSSLConfs)
         ++ (attrsets.mapAttrsToList (n: v: toVhost icfg.ips v) icfg.vhostConfs)
         ++ [ (redirectVhost icfg.ips) ];
     })
@@ -226,7 +270,10 @@ in
   ) groupedCerts;
 
   config.system.extraSystemBuilderCmds = lib.mkIf (builtins.length (builtins.attrValues cfg.webappDirs) > 0) ''
-    mkdir -p $out/webapps
-    ${builtins.concatStringsSep "\n" (attrsets.mapAttrsToList (name: path: "ln -s ${path} $out/webapps/${name}") cfg.webappDirs)}
+    mkdir -p $out/${cfg.webappDirsName}
+    ${builtins.concatStringsSep "\n"
+      (attrsets.mapAttrsToList
+        (name: path: "ln -s ${path} $out/${cfg.webappDirsName}/${name}") cfg.webappDirs)
+    }
   '';
 }