lol

Merge pull request #28749 from florianjacob/piwik-improve-config

nixos/piwik: Adjust to recent NixOS changes, use nginx's virtualHost instead of replicating [WIP]

authored by

Franz Pletz and committed by
GitHub
5393b0fc de31f879

+44 -54
-10
nixos/modules/services/web-apps/piwik-doc.xml
··· 79 You can safely ignore this, unless you need a plugin that needs JavaScript tracker access. 80 </para> 81 </listitem> 82 - 83 - <listitem> 84 - <para> 85 - Sending mail from piwik, e.g. for the password reset function, might not work out of the box: 86 - There's a problem with using <command>sendmail</command> from <literal>php-fpm</literal> that is 87 - being investigated at <link xlink:href="https://github.com/NixOS/nixpkgs/issues/26611" />. 88 - If you have (or don't have) this problem as well, please report it. You can enable SMTP as method 89 - to send mail in piwik's <quote>General Settings</quote> > <quote>Mail Server Settings</quote> instead. 90 - </para> 91 - </listitem> 92 </itemizedlist> 93 </section> 94
··· 79 You can safely ignore this, unless you need a plugin that needs JavaScript tracker access. 80 </para> 81 </listitem> 82 </itemizedlist> 83 </section> 84
+44 -44
nixos/modules/services/web-apps/piwik.nix
··· 24 default = false; 25 description = '' 26 Enable piwik web analytics with php-fpm backend. 27 ''; 28 }; 29 30 webServerUser = mkOption { 31 - type = types.str; 32 - example = "nginx"; 33 description = '' 34 - Name of the owner of the ${phpSocket} fastcgi socket for piwik. 35 If you want to use another webserver than nginx, you need to set this to that server's user 36 and pass fastcgi requests to `index.php` and `piwik.php` to this socket. 37 ''; ··· 57 }; 58 59 nginx = mkOption { 60 - # TODO: for maximum flexibility, it would be nice to use nginx's vhost_options module 61 - # but this only makes sense if we can somehow specify defaults suitable for piwik. 62 - # But users can always copy the piwik nginx config to their configuration.nix and customize it. 63 - type = types.nullOr (types.submodule { 64 - options = { 65 - virtualHost = mkOption { 66 - type = types.str; 67 - default = "piwik.${config.networking.hostName}"; 68 - example = "piwik.$\{config.networking.hostName\}"; 69 - description = '' 70 - Name of the nginx virtualhost to use and set up. 71 - ''; 72 - }; 73 - enableSSL = mkOption { 74 - type = types.bool; 75 - default = true; 76 - description = "Whether to enable https."; 77 - }; 78 - forceSSL = mkOption { 79 - type = types.bool; 80 - default = true; 81 - description = "Whether to always redirect to https."; 82 - }; 83 - enableACME = mkOption { 84 - type = types.bool; 85 - default = true; 86 - description = "Whether to ask Let's Encrypt to sign a certificate for this vhost."; 87 - }; 88 - }; 89 - }); 90 default = null; 91 - example = { virtualHost = "stats.$\{config.networking.hostName\}"; }; 92 description = '' 93 - The options to use to configure an nginx virtualHost. 94 - If null (the default), no nginx virtualHost will be configured. 95 ''; 96 }; 97 }; 98 }; 99 100 config = mkIf cfg.enable { 101 102 users.extraUsers.${user} = { 103 isSystemUser = true; ··· 153 serviceConfig.UMask = "0007"; 154 }; 155 156 - services.phpfpm.poolConfigs = { 157 ${pool} = '' 158 listen = "${phpSocket}" 159 - listen.owner = ${cfg.webServerUser} 160 listen.group = root 161 listen.mode = 0600 162 user = ${user} ··· 170 # References: 171 # https://fralef.me/piwik-hardening-with-nginx-and-php-fpm.html 172 # https://github.com/perusio/piwik-nginx 173 - ${cfg.nginx.virtualHost} = { 174 - root = "${pkgs.piwik}/share"; 175 - enableSSL = cfg.nginx.enableSSL; 176 - enableACME = cfg.nginx.enableACME; 177 - forceSSL = cfg.nginx.forceSSL; 178 179 locations."/" = { 180 index = "index.php"; ··· 208 locations."= /piwik.js".extraConfig = '' 209 expires 1M; 210 ''; 211 - }; 212 }; 213 }; 214
··· 24 default = false; 25 description = '' 26 Enable piwik web analytics with php-fpm backend. 27 + Either the nginx option or the webServerUser option is mandatory. 28 ''; 29 }; 30 31 webServerUser = mkOption { 32 + type = types.nullOr types.str; 33 + default = null; 34 + example = "lighttpd"; 35 description = '' 36 + Name of the web server user that forwards requests to the ${phpSocket} fastcgi socket for piwik if the nginx 37 + option is not used. Either this option or the nginx option is mandatory. 38 If you want to use another webserver than nginx, you need to set this to that server's user 39 and pass fastcgi requests to `index.php` and `piwik.php` to this socket. 40 ''; ··· 60 }; 61 62 nginx = mkOption { 63 + type = types.nullOr (types.submodule (import ../web-servers/nginx/vhost-options.nix { 64 + inherit config lib; 65 + })); 66 default = null; 67 + example = { 68 + serverName = "stats.$\{config.networking.hostName\}"; 69 + enableACME = false; 70 + }; 71 description = '' 72 + With this option, you can customize an nginx virtualHost which already has sensible defaults for piwik. 73 + Either this option or the webServerUser option is mandatory. 74 + Set this to {} to just enable the virtualHost if you don't need any customization. 75 + If enabled, then by default, the serverName is piwik.$\{config.networking.hostName\}, SSL is active, 76 + and certificates are acquired via ACME. 77 + If this is set to null (the default), no nginx virtualHost will be configured. 78 ''; 79 }; 80 }; 81 }; 82 83 config = mkIf cfg.enable { 84 + warnings = mkIf (cfg.nginx != null && cfg.webServerUser != null) [ 85 + "If services.piwik.nginx is set, services.piwik.nginx.webServerUser is ignored and should be removed." 86 + ]; 87 + 88 + assertions = [ { 89 + assertion = cfg.nginx != null || cfg.webServerUser != null; 90 + message = "Either services.piwik.nginx or services.piwik.nginx.webServerUser is mandatory"; 91 + }]; 92 93 users.extraUsers.${user} = { 94 isSystemUser = true; ··· 144 serviceConfig.UMask = "0007"; 145 }; 146 147 + services.phpfpm.poolConfigs = let 148 + # workaround for when both are null and need to generate a string, 149 + # which is illegal, but as assertions apparently are being triggered *after* config generation, 150 + # we have to avoid already throwing errors at this previous stage. 151 + socketOwner = if (cfg.nginx != null) then config.services.nginx.user 152 + else if (cfg.webServerUser != null) then cfg.webServerUser else ""; 153 + in { 154 ${pool} = '' 155 listen = "${phpSocket}" 156 + listen.owner = ${socketOwner} 157 listen.group = root 158 listen.mode = 0600 159 user = ${user} ··· 167 # References: 168 # https://fralef.me/piwik-hardening-with-nginx-and-php-fpm.html 169 # https://github.com/perusio/piwik-nginx 170 + "${user}.${config.networking.hostName}" = mkMerge [ cfg.nginx { 171 + # don't allow to override root, as it will almost certainly break piwik 172 + root = mkForce "${pkgs.piwik}/share"; 173 + 174 + # allow to override SSL settings if necessary, i.e. when using another method than ACME 175 + # but enable them by default, as sensitive login and piwik data should not be transmitted in clear text. 176 + forceSSL = mkDefault true; 177 + enableACME = mkDefault true; 178 179 locations."/" = { 180 index = "index.php"; ··· 208 locations."= /piwik.js".extraConfig = '' 209 expires 1M; 210 ''; 211 + }]; 212 }; 213 }; 214