fix(fedora-web): Exclude archives from mod_deflate to fix lookaside cache downloads #3170

Merged
kevin merged 1 commit from victorkoycheff/ansible:issue-12812-fix-deflate-headers into main 2026-02-27 18:34:37 +00:00
Contributor

Fixes #12812.

What this does:
Updates the SetEnvIfNoCase regex in roles/fedora-web/main/files/deflate.conf to explicitly exclude common binary/archive extensions from mod_deflate.

Why it's needed:
The frontend proxies were aggressively intercepting archive requests (like .crate, .tar.gz, .rpm) that weren't in the original image exclusion list, attempting to compress them, and appending a Content-Encoding: gzip (or x-gzip) header. Clients like curl and fedpkg were honoring this header by double-decompressing the files on the fly, resulting in raw tarballs with .crate extensions and immediate checksum failures.

Testing done:
I replicated the issue locally and confirmed that adding (?:gz|tgz|bz2|bz|xz|iso|tar|crate|zst|rpm|srpm) to the exclusion list prevents Apache from applying gzip encoding to these files, passing them through exactly as they are.

Signed-off-by: Victor Koycheff victorkoycheff@gmail.com

Fixes #12812. **What this does:** Updates the `SetEnvIfNoCase` regex in `roles/fedora-web/main/files/deflate.conf` to explicitly exclude common binary/archive extensions from `mod_deflate`. **Why it's needed:** The frontend proxies were aggressively intercepting archive requests (like `.crate`, `.tar.gz`, `.rpm`) that weren't in the original image exclusion list, attempting to compress them, and appending a `Content-Encoding: gzip` (or `x-gzip`) header. Clients like `curl` and `fedpkg` were honoring this header by double-decompressing the files on the fly, resulting in raw tarballs with `.crate` extensions and immediate checksum failures. **Testing done:** I replicated the issue locally and confirmed that adding `(?:gz|tgz|bz2|bz|xz|iso|tar|crate|zst|rpm|srpm)` to the exclusion list prevents Apache from applying gzip encoding to these files, passing them through exactly as they are. Signed-off-by: Victor Koycheff <victorkoycheff@gmail.com>
victorkoycheff force-pushed issue-12812-fix-deflate-headers from f54a3be1dd
Some checks are pending
Linter / yamllint (pull_request) Blocked by required conditions
Linter / ansible-lint (pull_request) Blocked by required conditions
to c31dc3de6e
All checks were successful
Linter / yamllint (pull_request) Successful in 24s
Linter / ansible-lint (pull_request) Successful in 28s
2026-02-25 07:59:25 +00:00
Compare
First-time contributor

I’m not fully convinced by the explanation, because the clients should only decode one layer of gzip encoding when they see the Content-Encoding: gzip header. If clients were indeed served two layers of gzip encoding as described above (equivalent to .crate.gz or .tar.gz.gz), that ought to be slightly wasteful of CPU and bandwidth but basically harmless, as the clients would decode the outer layer and produce the original file intact. Instead, it seems the original files are somehow served unmodified, but with the Content-Encoding: gzip header added, which causes the clients to decompress the pre-existing gzip layer. Still, whether or not the problem is truly fully understood, and even if the problem may reoccur in the future for some unforeseen archive format, this change ought to be helpful and a big step in the right direction. It’s wise to try to avoid double compression even if the resulting “turducken” were handled properly.

I’m not fully convinced by the explanation, because the clients should only decode one layer of gzip encoding when they see the `Content-Encoding: gzip` header. If clients were indeed served two layers of gzip encoding as described above (equivalent to `.crate.gz` or `.tar.gz.gz`), that ought to be slightly wasteful of CPU and bandwidth but basically harmless, as the clients would decode the outer layer and produce the original file intact. Instead, it seems the original files are somehow served unmodified, but with the `Content-Encoding: gzip` header added, which causes the clients to decompress the pre-existing gzip layer. Still, whether or not the problem is truly fully understood, and even if the problem may reoccur in the future for some unforeseen archive format, this change ought to be helpful and a big step in the right direction. It’s wise to try to avoid double compression even if the resulting “turducken” *were* handled properly.
victorkoycheff force-pushed issue-12812-fix-deflate-headers from c31dc3de6e
All checks were successful
Linter / yamllint (pull_request) Successful in 24s
Linter / ansible-lint (pull_request) Successful in 28s
to 3e97c302bd
All checks were successful
Linter / yamllint (pull_request) Successful in 24s
Linter / ansible-lint (pull_request) Successful in 26s
2026-02-25 16:31:33 +00:00
Compare
Author
Contributor

Thank you for the feedback @music. You're completely right about the mechanics here. The proxies weren't double-compressing; they were just passing the original files through while falsely classifyingthem with a Content-Encoding: gzip header. This caused clients to obediently decompress the payload on the fly, resulting in raw files being written to disk under compressed extensions (like .tar.gz), which immediately broke the checksums.

I have updated the commit message to accurately reflect this indeed 'false advertising' behavior. ; )

Thanks for the sharp eye

Thank you for the feedback @music. You're completely right about the mechanics here. The proxies weren't double-compressing; they were just passing the original files through while falsely classifyingthem with a `Content-Encoding: gzip` header. This caused clients to obediently decompress the payload on the fly, resulting in raw files being written to disk under compressed extensions (like `.tar.gz`), which immediately broke the checksums. I have updated the commit message to accurately reflect this indeed 'false advertising' behavior. ; ) Thanks for the sharp eye
victorkoycheff force-pushed issue-12812-fix-deflate-headers from 3e97c302bd
All checks were successful
Linter / yamllint (pull_request) Successful in 24s
Linter / ansible-lint (pull_request) Successful in 26s
to 0f787448f8
All checks were successful
Linter / yamllint (pull_request) Successful in 24s
Linter / ansible-lint (pull_request) Successful in 26s
2026-02-25 16:37:22 +00:00
Compare
Owner

So, this might be the right solution, but it's in the wrong place. ;(

This deflate.conf is used in the main 'fedoraproject.org' website config.

The issue to be fixed is happening in the src.fedoraproject.org site, which would be unaffected by this.

So, we need it in the right place, but I am not sure where that would be.
The path is:

request -> httpd on proxy -> anubis -> httpd on proxy -> varnish -> haproxy -> pkgs01 backend httpd

So, I guess the question is where the invalid header is being set.

So, this might be the right solution, but it's in the wrong place. ;( This deflate.conf is used in the main 'fedoraproject.org' website config. The issue to be fixed is happening in the src.fedoraproject.org site, which would be unaffected by this. So, we need it in the right place, but I am not sure where that would be. The path is: request -> httpd on proxy -> anubis -> httpd on proxy -> varnish -> haproxy -> pkgs01 backend httpd So, I guess the question is where the invalid header is being set.
victorkoycheff force-pushed issue-12812-fix-deflate-headers from 0f787448f8
All checks were successful
Linter / yamllint (pull_request) Successful in 24s
Linter / ansible-lint (pull_request) Successful in 26s
to de731d9035
Some checks failed
Linter / yamllint (pull_request) Has been cancelled
Linter / ansible-lint (pull_request) Has been cancelled
2026-02-26 07:20:03 +00:00
Compare
victorkoycheff force-pushed issue-12812-fix-deflate-headers from de731d9035
Some checks failed
Linter / yamllint (pull_request) Has been cancelled
Linter / ansible-lint (pull_request) Has been cancelled
to 56f5a7f2f5
All checks were successful
Linter / yamllint (pull_request) Successful in 26s
Linter / ansible-lint (pull_request) Successful in 29s
2026-02-26 07:20:23 +00:00
Compare
Author
Contributor

Thanks for the feedback @kevin

I did some more digging into the roles and found the culprit. In roles/httpd/website/templates/website.conf, there’s a global SetOutputFilter DEFLATE applied to the src.fedoraproject.org VirtualHost. Because src doesn't use the legacy deflate.conf exclusions, it was blindly adding the Content-Encoding: gzip header to archives without actually compressing them

I have refactored the PR as follows:

  1. Reverted the changes to roles/fedora-web/main/files/deflate.conf.
  2. Added SetEnv no-gzip 1 and SetEnv dont-vary 1 to the <Directory /srv/cache/lookaside> block in roles/distgit/templates/lookaside.conf.

Thus ensuring that mod_deflate is explicitly disabled for the lookaside cache at the directory level, regardless of which VirtualHost or alias is serving it.

Let me know if further refinement is needed

Thanks for the feedback @kevin I did some more digging into the roles and found the culprit. In **`roles/httpd/website/templates/website.conf`**, there’s a global **`SetOutputFilter DEFLATE`** applied to the `src.fedoraproject.org` VirtualHost. Because `src` doesn't use the legacy `deflate.conf` exclusions, it was blindly adding the `Content-Encoding: gzip` header to archives without actually compressing them I have refactored the PR as follows: 1. Reverted the changes to `roles/fedora-web/main/files/deflate.conf`. 2. Added `SetEnv no-gzip 1` and `SetEnv dont-vary 1` to the `<Directory /srv/cache/lookaside>` block in **`roles/distgit/templates/lookaside.conf`**. Thus ensuring that mod_deflate is explicitly disabled for the lookaside cache at the directory level, regardless of which VirtualHost or alias is serving it. Let me know if further refinement is needed
Owner

So, this is worth trying on staging I think...

Can you put all your changes in a
{% if env == 'staging' %}
block, so prod is not changed ? and remove WIP if you don't see any more changes needed before we try staging.

So, this is worth trying on staging I think... Can you put all your changes in a {% if env == 'staging' %} block, so prod is not changed ? and remove WIP if you don't see any more changes needed before we try staging.
victorkoycheff force-pushed issue-12812-fix-deflate-headers from 56f5a7f2f5
All checks were successful
Linter / yamllint (pull_request) Successful in 26s
Linter / ansible-lint (pull_request) Successful in 29s
to 14ab06dabb
Some checks failed
Linter / yamllint (pull_request) Has been cancelled
Linter / ansible-lint (pull_request) Has been cancelled
2026-02-27 07:10:46 +00:00
Compare
victorkoycheff changed title from WIP: fix(fedora-web): Exclude archives from mod_deflate to fix lookaside cache downloads to fix(fedora-web): Exclude archives from mod_deflate to fix lookaside cache downloads 2026-02-27 07:10:59 +00:00
victorkoycheff force-pushed issue-12812-fix-deflate-headers from 14ab06dabb
Some checks failed
Linter / yamllint (pull_request) Has been cancelled
Linter / ansible-lint (pull_request) Has been cancelled
to ac57bbb2ea
All checks were successful
Linter / yamllint (pull_request) Successful in 29s
Linter / ansible-lint (pull_request) Successful in 28s
2026-02-27 07:11:10 +00:00
Compare
Author
Contributor

Okay, I wrapped the changes in the staging block (unindented is better, right?)... I also dropped the WIP prefix, so this should be ready to try out on staging whenever. ; )

Okay, I wrapped the changes in the staging block (unindented is better, right?)... I also dropped the WIP prefix, so this should be ready to try out on staging whenever. ; )
@ -3,5 +3,12 @@ Alias /lookaside /srv/cache/lookaside
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
Owner

Hate to be nit picky, but can you drop this blank line for now?
With it, it means if someone runs the prod playbook this will have "changed" and it may restart things, etc.
Ideally this doesn't change production at all if it's run there.

Hate to be nit picky, but can you drop this blank line for now? With it, it means if someone runs the prod playbook this will have "changed" and it may restart things, etc. Ideally this doesn't change production at all if it's run there.
victorkoycheff marked this conversation as resolved
victorkoycheff force-pushed issue-12812-fix-deflate-headers from ac57bbb2ea
All checks were successful
Linter / yamllint (pull_request) Successful in 29s
Linter / ansible-lint (pull_request) Successful in 28s
to 4af6011bb8
All checks were successful
Linter / yamllint (pull_request) Successful in 31s
Linter / ansible-lint (pull_request) Successful in 26s
2026-02-27 18:20:17 +00:00
Compare
victorkoycheff force-pushed issue-12812-fix-deflate-headers from 4af6011bb8
All checks were successful
Linter / yamllint (pull_request) Successful in 31s
Linter / ansible-lint (pull_request) Successful in 26s
to 1fa76e4de0
All checks were successful
Linter / yamllint (pull_request) Successful in 24s
Linter / ansible-lint (pull_request) Successful in 27s
2026-02-27 18:23:13 +00:00
Compare
Author
Contributor

Nit pickiness is more than fine, negligence is the bad one ; )

I did the change as requested @kevin

Nit pickiness is more than fine, negligence is the bad one ; ) I did the change as requested @kevin
Owner

Thanks! Lets try it in staging then...

Thanks! Lets try it in staging then...
kevin merged commit 1fa76e4de0 into main 2026-02-27 18:34:37 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
infra/ansible!3170
No description provided.