diff --git a/flake.nix b/flake.nix index 8e0c895..bea248d 100644 --- a/flake.nix +++ b/flake.nix @@ -104,10 +104,11 @@ }) (_: _: {deploy-rs-pkg = null;}) (_: super: { + inherit (super.callPackage ./pkgs/compress-drv.nix {}) compressDrvWeb; + tmuxbash = super.callPackage ./pkgs/tmuxbash.nix {}; nicer = super.callPackage ./pkgs/nicer.nix {}; gamja = super.callPackage ./pkgs/gamja.nix {}; - compressAll = super.callPackage ./pkgs/compress-all.nix {}; }) ]; in diff --git a/hosts/vno1-oh2/configuration.nix b/hosts/vno1-oh2/configuration.nix index 4efd83f..75629bd 100644 --- a/hosts/vno1-oh2/configuration.nix +++ b/hosts/vno1-oh2/configuration.nix @@ -299,7 +299,7 @@ redir https://jakstys.lt ''; "irc.jakstys.lt".extraConfig = let - gamja = pkgs.compressAll (pkgs.gamja.override { + gamja = pkgs.compressDrvWeb (pkgs.gamja.override { gamjaConfig = { server = { url = "irc.jakstys.lt:6698"; diff --git a/modules/services/gitea/default.nix b/modules/services/gitea/default.nix index d05e002..fe9e53a 100644 --- a/modules/services/gitea/default.nix +++ b/modules/services/gitea/default.nix @@ -78,7 +78,7 @@ route /static/assets/* { uri strip_prefix /static/assets file_server * { - root ${pkgs.compressAll pkgs.gitea.data {}}/public + root ${pkgs.compressDrvWeb pkgs.gitea.data {}}/public precompressed br gzip } } diff --git a/pkgs/compress-all.nix b/pkgs/compress-all.nix deleted file mode 100644 index 47a34de..0000000 --- a/pkgs/compress-all.nix +++ /dev/null @@ -1,126 +0,0 @@ -/* -compress-all compresses files in a given derivation. - -Useful when one wants to pre-compress certain static assets and pass them to -the web server. For example, `pkgs.gamja` creates this derivation: - - /nix/store/2wn1qbk8gp4y2m8xvafxv1b2dcdqj8fz-gamja-1.0.0-beta.9/ - ├── index.2fd01148.js - ├── index.2fd01148.js.map - ├── index.37aa9a8a.css - ├── index.37aa9a8a.css.map - ├── index.html - └── manifest.webmanifest - -`pkgs.compressAll pkgs.gamja`: - - /nix/store/f5ryid7zrw2hid7h9kil5g5j29q5r2f7-gamja-1.0.0-beta.9-compressed - ├── index.2fd01148.js -> /nix/store/2wn1qbk8gp4y2m8xvafxv1b2dcdqj8fz-gamja-1.0.0-beta.9/index.2fd01148.js - ├── index.2fd01148.js.br - ├── index.2fd01148.js.gz - ├── index.2fd01148.js.map -> /nix/store/2wn1qbk8gp4y2m8xvafxv1b2dcdqj8fz-gamja-1.0.0-beta.9/index.2fd01148.js.map - ├── index.2fd01148.js.map.br - ├── index.2fd01148.js.map.gz - ├── index.37aa9a8a.css -> /nix/store/2wn1qbk8gp4y2m8xvafxv1b2dcdqj8fz-gamja-1.0.0-beta.9/index.37aa9a8a.css - ├── index.37aa9a8a.css.br - ├── index.37aa9a8a.css.gz - ├── index.37aa9a8a.css.map -> /nix/store/2wn1qbk8gp4y2m8xvafxv1b2dcdqj8fz-gamja-1.0.0-beta.9/index.37aa9a8a.css.map - ├── index.37aa9a8a.css.map.br - ├── index.37aa9a8a.css.map.gz - ├── index.html -> /nix/store/2wn1qbk8gp4y2m8xvafxv1b2dcdqj8fz-gamja-1.0.0-beta.9/index.html - ├── index.html.br - ├── index.html.gz - ├── manifest.webmanifest -> /nix/store/2wn1qbk8gp4y2m8xvafxv1b2dcdqj8fz-gamja-1.0.0-beta.9/manifest.webmanifest - ├── manifest.webmanifest.br - └── manifest.webmanifest.gz - - -When this `-compressed` directory is passed to a properly configured web -server, it will serve those pre-compressed files: - - $ curl -I -H 'Accept-Encoding: br' https://irc.example.org/ - <...> - content-encoding: br - <...> - -For example, a caddy configuration snippet for gamja to serve -the static assets (JS, CSS files) pre-compressed: - - virtualHosts."irc.example.org".extraConfig = '' - root * ${pkgs.compressAll pkgs.gamja {}} - file_server browse { - precompressed br gzip - } - ''; - -This feature is also available in nginx via `ngx_brotli` and -`ngx_http_gzip_static_module`. - - -Inputs: -- formats :: [String] - - The default list of file extensions to compress. - - Default: common formats that compress well. The list may be appended (but - not reduced) without warning. - -- extraFormats :: [String] - - Extra extensions to compress in addition to `extensions`. - -- compressors :: [String] - - A list of compressor names to use. - - Default: ["gz" "br"] - -- compressor- :: String - - Maps a desired extension (e.g. `gz`) to a compress program (e.g. `zopfli - --keep {}`). - - The compressor program that will be executed to get the `COMPRESSOR` - extension. The program is passed to xargs like this: - - xargs -I{} -n1 ${prog} - - Example: - - compressor-xz = "${xz}/bin/xz --keep {}"; - compressor-zst = "${zstd}/bin/zstd --keep {}"; -*/ -{ - lib, - runCommand, - xorg, - zopfli, - brotli, -}: drv: { - formats ? ["css" "js" "svg" "ttf" "eot" "txt" "xml" "map" "html" "json" "webmanifest"], - extraFormats ? [], - compressors ? ["gz" "br"], - ... -} @ args: let - compressorMap = - { - compressor-gz = "${zopfli}/bin/zopfli --keep {}"; - compressor-br = "${brotli}/bin/brotli --keep --no-copy-stat {}"; - } - // lib.filterAttrs (k: _: (lib.hasPrefix "compressor-" k)) args; - compressCommands = - map - (ext: let - prog = builtins.getAttr "compressor-${ext}" compressorMap; - in "tee >(xargs -I{} -n1 -P$NIX_BUILD_CORES ${prog})") - compressors; - formatsbar = builtins.concatStringsSep "|" (formats ++ extraFormats); -in - runCommand "${drv.name}-compressed" {} '' - mkdir $out - ${xorg.lndir}/bin/lndir ${drv}/ $out/ - - find -L $out -type f -regextype posix-extended \ - -iregex '.*\.(${formatsbar})' | \ - ${builtins.concatStringsSep " | \\\n " compressCommands} - '' diff --git a/pkgs/compress-drv.nix b/pkgs/compress-drv.nix new file mode 100644 index 0000000..4e54db8 --- /dev/null +++ b/pkgs/compress-drv.nix @@ -0,0 +1,172 @@ +{ + lib, + runCommand, + xorg, + zopfli, + brotli, +}: let + compressDrv = drv: { + formats, + compressors, + ... + } @ args: let + compressorMap = lib.filterAttrs (k: _: (lib.hasPrefix "compressor-" k)) args; + compressCommands = + map + (ext: let + prog = builtins.getAttr "compressor-${ext}" compressorMap; + in "tee >(xargs -I{} -n1 -P$NIX_BUILD_CORES ${prog})") + compressors; + formatsbar = builtins.concatStringsSep "|" formats; + in + runCommand "${drv.name}-compressed" {} '' + mkdir $out + ${xorg.lndir}/bin/lndir ${drv}/ $out/ + + find -L $out -type f -regextype posix-extended \ + -iregex '.*\.(${formatsbar})' | \ + ${builtins.concatStringsSep " | \\\n " compressCommands} + ''; +in { + /* + compressDrv compresses files in a given derivation. + + Inputs: + + - formats :: [String] + + List of file extensions to compress. + + Example: ["txt" "svg" "xml"] + + - compressors :: [String] + + A list of compressor names to use. Each element will need to have + an associated compressor in the same arguments (see below). + + Example: ["gz" "zstd"] + + - compressor- :: String + + Map a desired extension (e.g. `gz`) to a compress program. + + The compressor program that will be executed to get the `COMPRESSOR` + extension. The program is passed to xargs like this: + + xargs -I{} -n1 ${prog} + + Example: + + compressor-xz = "${xz}/bin/xz --keep {}"; + + See compressDrvWeb, which is a wrapper on top of compressDrv, for broader + use examples. + */ + inherit (compressDrv); + + /* + compressDrvWeb compresses a derivation for "web server" usage. + + Useful when one wants to pre-compress certain static assets and pass them to + the web server. For example, `pkgs.gamja` creates this derivation: + + /nix/store/2wn1qbk8gp4y2m8xvafxv1b2dcdqj8fz-gamja-1.0.0-beta.9/ + ├── index.2fd01148.js + ├── index.2fd01148.js.map + ├── index.37aa9a8a.css + ├── index.37aa9a8a.css.map + ├── index.html + └── manifest.webmanifest + + `pkgs.compressDrvWeb pkgs.gamja`: + + /nix/store/f5ryid7zrw2hid7h9kil5g5j29q5r2f7-gamja-1.0.0-beta.9-compressed + ├── index.2fd01148.js -> /nix/store/2wn1qbk8gp4y2m8xvafxv1b2dcdqj8fz-gamja-1.0.0-beta.9/index.2fd01148.js + ├── index.2fd01148.js.br + ├── index.2fd01148.js.gz + ├── index.2fd01148.js.map -> /nix/store/2wn1qbk8gp4y2m8xvafxv1b2dcdqj8fz-gamja-1.0.0-beta.9/index.2fd01148.js.map + ├── index.2fd01148.js.map.br + ├── index.2fd01148.js.map.gz + ├── index.37aa9a8a.css -> /nix/store/2wn1qbk8gp4y2m8xvafxv1b2dcdqj8fz-gamja-1.0.0-beta.9/index.37aa9a8a.css + ├── index.37aa9a8a.css.br + ├── index.37aa9a8a.css.gz + ├── index.37aa9a8a.css.map -> /nix/store/2wn1qbk8gp4y2m8xvafxv1b2dcdqj8fz-gamja-1.0.0-beta.9/index.37aa9a8a.css.map + ├── index.37aa9a8a.css.map.br + ├── index.37aa9a8a.css.map.gz + ├── index.html -> /nix/store/2wn1qbk8gp4y2m8xvafxv1b2dcdqj8fz-gamja-1.0.0-beta.9/index.html + ├── index.html.br + ├── index.html.gz + ├── manifest.webmanifest -> /nix/store/2wn1qbk8gp4y2m8xvafxv1b2dcdqj8fz-gamja-1.0.0-beta.9/manifest.webmanifest + ├── manifest.webmanifest.br + └── manifest.webmanifest.gz + + + When this `-compressed` directory is passed to a properly configured web + server, it will serve those pre-compressed files: + + $ curl -I -H 'Accept-Encoding: br' https://irc.example.org/ + <...> + content-encoding: br + <...> + + For example, a caddy configuration snippet for gamja to serve + the static assets (JS, CSS files) pre-compressed: + + virtualHosts."irc.example.org".extraConfig = '' + root * ${pkgs.compressDrvWeb pkgs.gamja {}} + file_server browse { + precompressed br gzip + } + ''; + + This feature is also available in nginx via `ngx_brotli` and + `ngx_http_gzip_static_module`. + + Inputs: + - formats :: [String] + + List of file extensions to compress. + + Default: common formats that compress well. The list may be appended + expanded. + + - extraFormats :: [String] + + Extra extensions to compress in addition to `formats`. + + - compressors :: [String] + + A list of compressor names to use. Each element will need to have + an associated compressor in the same arguments (see below). + + Default: ["gz" "br"] + + - compressor- :: String + + Map a desired extension (e.g. `gz`) to a compress program. + + The compressor program that will be executed to get the `COMPRESSOR` + extension. The program is passed to xargs like this: + + xargs -I{} -n1 ${prog} + + Default: + + compressor-gz = "${zopfli}/bin/zopfli --keep {}"; + compressor-br = "${brotli}/bin/brotli --keep --no-copy-stat {}"; + */ + + compressDrvWeb = drv: { + formats ? ["css" "js" "svg" "ttf" "eot" "txt" "xml" "map" "html" "json" "webmanifest"], + extraFormats ? [], + compressors ? ["gz" "br"], + ... + } @ args: + compressDrv drv ({ + formats = formats ++ extraFormats; + compressors = compressors; + compressor-gz = "${zopfli}/bin/zopfli --keep {}"; + compressor-br = "${brotli}/bin/brotli --keep --no-copy-stat {}"; + } + // lib.filterAttrs (k: _: (lib.hasPrefix "compressor-" k)) args); +} diff --git a/statix.toml b/statix.toml index c2c0666..0b220fd 100644 --- a/statix.toml +++ b/statix.toml @@ -1 +1,11 @@ ignore = ['modules/base/boot'] + +# If the attrset has an optional field, `inherit` will not inherit it: +# compressDrvWeb = drv: { +# compressors ? ["gz" "br"], +# ... +# } @ args: +# compressDrv drv { +# inherit (compressors) <<- function 'compressDrv' called without required argument 'compressors' +# } +disabled = ["manual_inherit"]