nixos/nextcloud: Add option to pre-compress assets#239198
nixos/nextcloud: Add option to pre-compress assets#239198Mynacol wants to merge 1 commit intoNixOS:masterfrom
Conversation
|
Previous discussion at Mastodon And ping @onny |
|
This will break the integrity check, no? |
|
I'd strongly prefer to have the compression artifacts moved to another output (i.e. to make this opt-in).
Please elaborate why we also create zopfli artifacts in addition to gzip and brotli. |
I haven't thought of that, but my Nextcloud (with this PR) doesn't complain in any way. Probably because we just add new files alongside the unmodified files.
Zopfli is not another algorithm, but a special compressor for gzip trading high computational resources for a slightly better compression ratio.
While this seems like a bad tradeoff at first, it might be worthwile for resources being transferred millions of times. Zopfli is useful the earlier in the deployment chain it's applied, so ideal for nixpkgs.
That would indeed be preferable. I updated the PR accordingly. |
Rough idea: |
|
I just added a commit introducing the requested option. I opted to use symlinkJoin instead of the try_files method because it reduces the amount of places we need to change and think about this option in the future. (My last test didn't include the compressed output, but all the previous did. I have no time right now but wanna confirm everything later)
At first, my Nextcloud didn't complain, but now it does... I also thought about splitting the brotli and gzip outputs in two and using two options to selectively enable them, but I'm hesitant adding more configuration options than needed. On the other hand we enable transparent gzip compression regardless of user preference, so we might include these artifacts in all cases, but leave brotli separate. |
|
Random thought: if we only use the |
Yes, it will because it complains about the new files. (I just wanted to attach a screenshot but somehow the error is now not appearing. Not sure why but that already happened in the past for no reason and after some time it appeared again.) |
|
I tried to implement the recommendations today, but failed at a specific line, In Nextcloud I edit a function that generalizes over the different versions (nextcloud 25, 26, 27). How can I reference the output of the correct version? (Using |
|
you probably want to implement the change here https://github.com/NixOS/nixpkgs/blob/master/pkgs/servers/nextcloud/default.nix#L14 |
fe3482f to
8389f00
Compare
|
@ofborg build nextcloud29 |
|
I think this should use #292324 as soon as it's ready. |
|
Linked PR got merged |
|
I've used the following in my config: package = let
# hacks around hardcoded caBundle override from
# https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/web-apps/nextcloud.nix#L13-L15
pkg = (pkgs.compressDrvWeb (pkgs.nextcloud31.override {
inherit (config.security.pki) caBundle;
}) {
extraFindOperands = ''-not -iregex ".*(\/apps\/.*\/l10n\/).*"'';
}).overrideAttrs ({ passthru, ...}: {
passthru = passthru // {
override = _: pkg;
};
});
in
pkg; |
|
I finally got time to look at this PR again.
I get the feeling that @SuperSandro2000's overriding of I made a new experimental draft at #432093. My remaining issue is that using |
|
I must say a of this back and forth and the fact that this will add more complexity to Nextcloud and others makes me heavily question the gain of pre-compressed artifacts over letting nginx do it. |
82b6a4f to
c88a0f4
Compare
c88a0f4 to
2b8048b
Compare
|
Alright, this package is (understandably) just too complex to just do what I had in mind. To get things forward, I significantly reduced the scope for now. This time, the compression is not happening in the package, which would allow Hydra to do the work for all users, but in the nixos module. This makes the code almost trivial and users can just enable compression without having to do any overrides. This version has no problem with people modifying the underlying package because it is the last step before finalizing the webroot. Either the original or the modified package will be compressed if the option is enabled. If not, no compression is done. Now we can discuss:
And for some assurance: When someone else tries to push the compression to a point earlier in the chain, they have to cope with above mentioned problems. Some additional notes:
|
Ma27
left a comment
There was a problem hiding this comment.
Did anybody actually measure if the improvements are noticeable?
CCing the actual Nextcloud maintainers as well: @bachp @britter @provokateurin @dotlambda
Would it make sense to add the nextcloud nixos tests to the nixos module's passthru.tests (so ofborg will run them on any change here)?
This is already the case for quite a while though?
There was a problem hiding this comment.
Am I getting it right that we're serving storing the same data compressed in several formats now by default?
There was a problem hiding this comment.
Yes. compressDrvWeb by default compresses for gzip, brotli and zstd.
I wonder where we should draw the line between flexibility and option overload.
How would you think about the option type being a list of enum gzip, br and zstd? Or we leave it as-is, either compression for all three or none.
At least transfer size wise is it noticeable. See the original post for (old, but probably comparable) numbers.
In the package, the nixos tests are linked. But I don't see that for the nixos module? After I learned you can add e.g. Thanks for notifying the actual maintainers, I missed that! |
2b8048b to
07c19a3
Compare
|
I think this is in shape to be re-reviewed. The change is now really compact. Mentioning the Nextcloud maintainers to ask them for a review: @bachp @britter @dotlambda @Ma27 @provokateurin. Edit: also @SuperSandro2000 which previously reviewed this PR already. I already pointed out potential remaining questions:
|
First of all, no measurement of the timings, i.e. what the actual impact is when using on-the-fly compression. Then, what are the compression parameters used for on-the-fly vs. build-time compression (and the timing-differences when using actually equivalent configuration)? Btw, what's the reason for doing this in nixpkgs instead of when building the upstream tarball? The one thing I'm interested in is that this isn't the default considering the build-time compression speeds this will make testing cycles way more annoying. I'll defer the decisionmaking to someone else from the maintainer team though. |
|
I'm not really convinced by this change. Browsers already cache assets and you can also configure nginx to cache assets (but you can easily break your instance on upgrade if your cache invalidation is not working), so the amount of on-the-fly compression should not be high. Even though it's optional, IMO this adds complexity without much benefit. You can also easily have this in your NixOS configuration by overriding the |
I'm not sure what the correct way to fairly compare timings is. The pre-compressed method has by definition (almost) no overhead. On my laptop with 8 cores, compressing the whole tarball with
On-the-fly: The nextcloud nginx config in NixOS always enables gzip compression with level 4. More broadly,
Except my browser purposefully deletes caches on exit for privacy reasons. That's a me thing tho.
If y'all want to, we can disable it by default, no problem. However, I believe the overwhelming majority won't have any testing cycles at all while profiting from the smaller transfer sizes. A release note is a good idea anyway.
Good question. I didn't ask the upstream project. I reckoned this is in the working field of a distribution, tweaking and providing upstream projects as fit to the specific distribution.
Correct, that's how I use it for years already. However, it is more complicated because of this: services.nextcloud.package = (pkgs.compressDrvWeb pkgs.nextcloud31 {}).overrideAttrs ({passthru, ...}: {
passthru =
passthru
// {
override = _: config.services.nextcloud.package;
};
});
I kept the complexity to an absolute minimum. A single line of implementation code that wraps the webroot once. The package and module as a whole get more complicated, correct, but IMO in a reasonable amount.
That would be a great and useful alternative if it is ultimately not merged. |
07c19a3 to
274fffe
Compare
This adds an option which pre-compresses assets of the nextcloud webroot at system build time using `compressDrvWeb`. The nextcloud nginx config unconditionally activates gzip compression to significantly reduce the transmission size of these assets. By pre-compressing them, even better compression factors can be reached while avoiding the constant on-the-fly compression of the same files. The advantages are even bigger when using sendfile on either an unencrypted HTTP connection or in combination with KTLS by avoiding a copy into the userspace. The trade-off is an increased storage size holding these pre-compressed artifacts.
274fffe to
e96522b
Compare
|
@bachp @britter @dotlambda @Ma27 @provokateurin Alright, this is my final straw. Since my last comment, I rebased this PR and disabled the option by default. I also slightly expanded the option description. Either you take this feature (potentially with some improvements), or I don't see a way to alter it so it suits you. The remaining motivation for this PR is to avoid people needing to do something like the following: package = (pkgs.compressDrvWeb pkgs.nextcloud31 {}).overrideAttrs ({passthru, ...}: {
passthru =
passthru
// {
override = _: config.services.nextcloud.package;
};
});and instead offer the same with a one-liner: enableCompressedAssets = true;@ofborg test nextcloud |
Description of changes
The schema is similar to Mastodon's packaging script, gnerating gzip and brotli compressed files ahead-of-time.
The find command only selects those folders that are publicly viewable according to the nginx config, and only compresses file types that are allowed in the nginx config.
The index.html and robots.txt files are too small to be relevant.
The gzip files are used through the default nginx config, brotli requires the administrators to set
services.nginx.recommendedBrotliSettings = true.Space changes
560MB /nix/store/i6b1aqrbjgvx6jc8psv1kcyhkayqg8xx-nextcloud-27.0.0 (previous)
683MB /nix/store/h2ai1zkdqp280xv4wp7xrfn4ax86l9xf-nextcloud-27.0.0 (new)
Bandwidth savings
I observed the login page with Firefox. The server has
services.nginx.recommendedGzipSettingsandservices.nginx.recommendedBrotliSettingsenabled.16.53MB uncompressed (according to Firefox dev tools)
3.94MB on-the-fly compressed (old)
1.64MB ahead-of-time compressed (new)
That's a 2.4x compression improvement!
Compute savings
No measurements for CPU compute savings on the server side, but we avoid compressing the same files over and over again. Helps the environment 🌍
Brotli and gzip should be equally fast at decompression irrespective of compression level.
Build time increase
The build time increases by 15-23 minutes. Most of this can be attributed to zopfli. Only brotli (and standard gzip) would take more like 4 minutes.
Things done
sandbox = trueset innix.conf? (See Nix manual)nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD". Note: all changes have to be committed, also see nixpkgs-review usage./result/bin/): tested nextcloud26 in production