Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions nixos/doc/manual/release-notes/rl-2411.section.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
- `authelia` has been upgraded to version 4.38. This version brings several features and improvements which are detailed in the [release blog post](https://www.authelia.com/blog/4.38-release-notes/).
This release also deprecates some configuration keys, which are likely to be removed in future version 5.0, but they are still supported and expected to be working in the current version.

- `compressDrv` can compress selected files in a derivation. `compressDrvWeb` compresses files for common web server usage (`.gz` with `zopfli`, `.br` with `brotli`).

- `hardware.display` is a new module implementing workarounds for misbehaving monitors
through setting up custom EDID files and forcing kernel/framebuffer modes.

Expand Down
63 changes: 63 additions & 0 deletions pkgs/build-support/compress-drv/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
lib,
xorg,
runCommand,
}:
/**
# compressDrv compresses files in a given derivation.

## Inputs:

`formats` ([String])

: List of file extensions to compress. Example: `["txt" "svg" "xml"]`.

`compressors` (String -> 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 should have a single " {}", which will be the replaced with the
target filename.

Compressor must:
- read symlinks (thus --force is needed to gzip, zstd, xz).
- keep the original file in place (--keep).

Example:

```
{
xz = "${xz}/bin/xz --force --keep {}";
}
```

See compressDrvWeb, which is a wrapper on top of compressDrv, for broader use
examples.
*/
drv:
{ formats, compressors, ... }:
let
validProg =
ext: prog:
let
matches = (builtins.length (builtins.split "\\{}" prog) - 1) / 2;
in
lib.assertMsg (
matches == 1
) "compressor ${ext} needs to have exactly one '{}', found ${builtins.toString matches}";
mkCmd =
ext: prog:
assert validProg ext prog;
''
find -L $out -type f -regextype posix-extended -iregex '.*\.(${formatsPipe})' -print0 \
| xargs -0 -P$NIX_BUILD_CORES -I{} ${prog}
'';
formatsPipe = builtins.concatStringsSep "|" formats;
in
runCommand "${drv.name}-compressed" { } ''
mkdir $out
(cd $out; ${xorg.lndir}/bin/lndir ${drv})

${lib.concatStringsSep "\n\n" (lib.mapAttrsToList mkCmd compressors)}
''
42 changes: 42 additions & 0 deletions pkgs/build-support/compress-drv/test.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
gzip,
runCommand,
compressDrv,
}:
let
example = runCommand "sample-drv" { } ''
mkdir $out
echo 42 > $out/1.txt
echo 43 > $out/1.md
touch $out/2.png
'';
drv = compressDrv example {
formats = [ "txt" ];
compressors.gz = "${gzip}/bin/gzip --force --keep --fast {}";
};
wrapped = compressDrv drv {
formats = [ "md" ];
compressors.gz = "${gzip}/bin/gzip --force --keep --fast {}";
};
in
runCommand "test-compressDrv" { } ''
set -ex

ls -l ${drv}
test -h ${drv}/1.txt
test -f ${drv}/1.txt.gz
cmp ${drv}/1.txt <(${gzip}/bin/zcat ${drv}/1.txt.gz)

test -h ${drv}/2.png
test ! -a ${drv}/2.png.gz

# compressDrv always points to the final file, no matter how many times
# it's been wrapped
cmp <(readlink -e ${drv}/1.txt) <(readlink -e ${wrapped}/1.txt)

test -f ${wrapped}/1.txt.gz
test -f ${wrapped}/1.md.gz
test ! -f ${drv}/1.md.gz

mkdir $out
''
103 changes: 103 additions & 0 deletions pkgs/build-support/compress-drv/web.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
{
zopfli,
brotli,
compressDrv,
}:
/**
# compressDrvWeb compresses a derivation for common web server use.

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 is common formats that compress
well. The list may be expanded.

`extraFormats` ([String])

: Extra extensions to compress in addition to `formats`.

`compressors` (String -> String)

: See parameter `compressors` of compressDrv.
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My knowledge on the documentation infrastructure is a little outdated, so excuse my ignorance, but does this doc-comment appear in one of the manuals?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure how to check; I mostly cargo-culted the comment format from the functions I like in lib/.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @NixOS/documentation-team any suggestions?

Copy link
Contributor

@hsjobeki hsjobeki Aug 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using doc-comments would be beneficial, since they can be retrieved with :doc in the repl. since release 2.24
And we plan to render them into the manual.

/** */

Content should be markdown, so its rendered properly

My knowledge on the documentation infrastructure is a little outdated, so excuse my ignorance, but does this doc-comment appear in one of the manuals?

No not yet.

@motiejus It is planned to migrate all doc comments into one common format:

https://github.com/NixOS/rfcs/blob/c65c8321782b40844167beb48818471f70900d9d/rfcs/0145-doc-strings.md#migration-example

(:doc doesn't work in this particular case, because some features are still missing, but https://noogle.dev should find it after its merged)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did my best following the examples here and in attrsets.

My system is still on 2.18, which makes it nontrivial to see the end result. I'll have a look once this lands somewhere or my nix is 2.24.

drv:
{
formats ? [
"css"
"js"
"svg"
"ttf"
"eot"
"txt"
"xml"
"map"
"html"
"json"
"webmanifest"
],
extraFormats ? [ ],
compressors ? {
"gz" = "${zopfli}/bin/zopfli --keep {}";
"br" = "${brotli}/bin/brotli --keep --no-copy-stat {}";
},
...
}:
compressDrv drv {
formats = formats ++ extraFormats;
compressors = compressors;
}
18 changes: 2 additions & 16 deletions pkgs/by-name/gi/gitea/package.nix
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,13 @@
, git
, bash
, coreutils
, compressDrvWeb
, gitea
, gzip
, openssh
, pam
, sqliteSupport ? true
, pamSupport ? stdenv.hostPlatform.isLinux
, runCommand
, brotli
, xorg
, nixosTests
, buildNpmPackage
}:
Expand Down Expand Up @@ -90,19 +88,7 @@ in buildGoModule rec {
'';

passthru = {
data-compressed = runCommand "gitea-data-compressed" {
nativeBuildInputs = [ brotli xorg.lndir ];
} ''
mkdir -p $out/{options,public,templates}
lndir ${frontend}/public $out/public
lndir ${gitea.data}/options $out/options
lndir ${gitea.data}/templates $out/templates

# Create static gzip and brotli files
find -L $out -type f -regextype posix-extended -iregex '.*\.(css|html|js|svg|ttf|txt)' \
-exec gzip --best --keep --force {} ';' \
-exec brotli --best --keep --no-copy-stat {} ';'
'';
data-compressed = lib.warn "gitea.passthru.data-compressed is deprecated. Use \"compressDrvWeb gitea.data\"." (compressDrvWeb gitea.data);

tests = nixosTests.gitea;
};
Expand Down
2 changes: 2 additions & 0 deletions pkgs/test/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ with pkgs;
cc-multilib-gcc = callPackage ./cc-wrapper/multilib.nix { stdenv = gccMultiStdenv; };
cc-multilib-clang = callPackage ./cc-wrapper/multilib.nix { stdenv = clangMultiStdenv; };

compress-drv = callPackage ../build-support/compress-drv/test.nix { };

fetchurl = callPackages ../build-support/fetchurl/tests.nix { };
fetchtorrent = callPackages ../build-support/fetchtorrent/tests.nix { };
fetchpatch = callPackages ../build-support/fetchpatch/tests.nix { };
Expand Down
4 changes: 4 additions & 0 deletions pkgs/top-level/all-packages.nix
Original file line number Diff line number Diff line change
Expand Up @@ -39878,6 +39878,10 @@ with pkgs;
};
};

compressDrv = callPackage ../build-support/compress-drv { };

compressDrvWeb = callPackage ../build-support/compress-drv/web.nix { };

duti = callPackage ../os-specific/darwin/duti {
inherit (darwin.apple_sdk.frameworks) ApplicationServices;
};
Expand Down