Skip to content

[feature] Configured nginx to serve precompressed files (gzip/brotli) #599#601

Open
SAMurai-16 wants to merge 19 commits intoopenwisp:masterfrom
SAMurai-16:issues/599-configure-nginx
Open

[feature] Configured nginx to serve precompressed files (gzip/brotli) #599#601
SAMurai-16 wants to merge 19 commits intoopenwisp:masterfrom
SAMurai-16:issues/599-configure-nginx

Conversation

@SAMurai-16
Copy link
Copy Markdown

@SAMurai-16 SAMurai-16 commented Feb 14, 2026

Remove GZIP_STATIC_COMPRESSION and BROTLI_STATIC_COMPRESSION settings from Django configuration as they are no longer valid with the new openwisp-utils package. Configure nginx to serve precompressed files by adding gzip_static and brotli_static directives to the SSL configuration. This improves performance by serving pre-compressed .gz and .br files directly when available, rather than compressing on-the-fly.

Updated templates/openwisp2/settings.py to remove obsolete compression settings, modified defaults/main.yml to add precompressed file serving configuration, and updated documentation in docs/user/role-variables.rst.

Fixes #599

Checklist

  • I have read the OpenWISP Contributing Guidelines.
  • I have manually tested the changes proposed in this pull request.
  • I have written new test cases for new code and/or updated existing tests for changes to existing code.
  • I have updated the documentation.

Reference to Existing Issue

Closes #599 .

…on settings openwisp#599

Remove GZIP_STATIC_COMPRESSION and BROTLI_STATIC_COMPRESSION settings from Django
configuration as they are no longer valid with the new openwisp-utils package.
Configure nginx to serve precompressed files by adding gzip_static and brotli_static
directives to the SSL configuration. This improves performance by serving pre-compressed
.gz and .br files directly when available, rather than compressing on-the-fly.

Updated templates/openwisp2/settings.py to remove obsolete compression settings,
modified defaults/main.yml to add precompressed file serving configuration, and
updated documentation in docs/user/role-variables.rst.

Fixes openwisp#599
Copilot AI review requested due to automatic review settings February 14, 2026 11:30
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 14, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds two boolean vars to OpenWISP2 Nginx SSL config: openwisp2_nginx_gzip_static and openwisp2_nginx_brotli_static (defaults false) and documents them. The nginx Jinja2 site template now conditionally emits gzip_static on; and brotli_static on;. Ansible tasks install corresponding nginx modules (errors ignored), molecule test playbooks enable those vars and verify directives plus nginx -t, and explicit static-compression disables were removed from the Django settings template.

Sequence Diagram(s)

sequenceDiagram
  participant Ansible as "Ansible Controller"
  participant Apt as "Package Manager (apt)"
  participant Nginx as "Nginx"
  participant FS as "Filesystem (precompressed files)"
  participant Client as "HTTP Client"

  Ansible->>Apt: Install nginx + gzip/brotli modules (conditional)
  Apt-->>Ansible: Install result (errors ignored)
  Ansible->>Nginx: Render site-conf.j2 with gzip_static/brotli_static based on vars
  Ansible->>Nginx: Reload/restart Nginx
  Client->>Nginx: Request static asset (e.g., asset.js)
  Nginx->>FS: Check for precompressed variants (asset.js.gz / asset.js.br)
  alt precompressed exists and directive enabled
    Nginx-->>Client: Serve precompressed file with appropriate Content-Encoding
  else
    Nginx-->>Client: Serve regular asset
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

  • #599 — Matches objective: enables configuring nginx to serve precompressed gzip/brotli and removes explicit disables.
  • openwisp/docker-openwisp#560 — Related: implements toggles, module installation, template directives, and removal of explicit gzip/brotli disables.
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly summarizes the main change: configuring nginx to serve precompressed files (gzip/brotli), which is the primary objective of the changeset.
Linked Issues check ✅ Passed All requirements from issue #599 are met: removed Django compression settings from settings.py and configured nginx to serve precompressed files with gzip_static and brotli_static directives.
Out of Scope Changes check ✅ Passed All changes align with the linked issue objectives. The PR modifies configuration files, templates, documentation, and test files to implement precompressed file serving via nginx.
Description check ✅ Passed The PR description addresses the issue objectives, includes a proper reference to issue #599, and documents the key changes made across multiple files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@defaults/main.yml`:
- Around line 163-164: The template unconditionally emits brotli_static which
breaks nginx if ngx_brotli isn't present; update the role to either install
ngx_brotli when brotli_static is "on" or make the template conditional: add a
boolean var like brotli_module_installed (default false) and modify the
site-conf.j2 to only render the brotli_static line when brotli_module_installed
is true and openwisp2_nginx_ssl_config.brotli_static == "on"; alternatively,
make the role install/enable ngx_brotli when
openwisp2_nginx_ssl_config.brotli_static is "on" so the directive is safe to
emit.
🧹 Nitpick comments (1)
docs/user/role-variables.rst (1)

165-166: Add a short note about the precompression prerequisite.

These directives only serve precompressed assets when .gz/.br files exist. A brief note in this section will prevent confusion for users who expect on-the-fly compression.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c9ee54c and bc25de4.

📒 Files selected for processing (3)
  • defaults/main.yml
  • docs/user/role-variables.rst
  • templates/openwisp2/settings.py
💤 Files with no reviewable changes (1)
  • templates/openwisp2/settings.py
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Agent
  • GitHub Check: Build debian13
  • GitHub Check: Build ubuntu2204
  • GitHub Check: Build ubuntu2404
  • GitHub Check: Build debian12

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR removes obsolete Django compression settings (GZIP_STATIC_COMPRESSION and BROTLI_STATIC_COMPRESSION) that are no longer valid with the updated openwisp-utils package, and configures nginx to serve pre-compressed files directly using gzip_static and brotli_static directives. This shifts compression responsibility from Django to nginx for improved performance.

Changes:

  • Removed deprecated Django compression settings from settings.py template
  • Added gzip_static and brotli_static nginx directives to default configuration
  • Updated documentation to reflect new nginx compression configuration

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
templates/openwisp2/settings.py Removed obsolete GZIP_STATIC_COMPRESSION and BROTLI_STATIC_COMPRESSION Django settings
defaults/main.yml Added gzip_static and brotli_static directives to openwisp2_nginx_ssl_config
docs/user/role-variables.rst Updated documentation with new nginx compression directives

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- "application/x-font-ttf"
- "font/opentype"
gzip_static: "on"
brotli_static: "on"
Copy link

Copilot AI Feb 14, 2026

Choose a reason for hiding this comment

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

The brotli_static directive requires the nginx brotli module to be installed, but this module is not included in standard nginx packages. Without installing libnginx-mod-brotli (Debian/Ubuntu) or building nginx with the brotli module, this directive will cause nginx to fail with an "unknown directive" error. You need to either add a task to install the brotli module package in tasks/apt.yml or remove this directive until the module is installed.

Suggested change
brotli_static: "on"

Copilot uses AI. Check for mistakes.
- "application/x-font-ttf"
- "font/opentype"
gzip_static: "on"
brotli_static: "on"
Copy link

Copilot AI Feb 14, 2026

Choose a reason for hiding this comment

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

The brotli_static directive requires the nginx brotli module to be installed, but this module is not included in standard nginx packages. Without installing libnginx-mod-brotli (Debian/Ubuntu) or building nginx with the brotli module, this directive will cause nginx to fail with an "unknown directive" error. You need to either add a task to install the brotli module package in tasks/apt.yml or remove this directive until the module is installed.

Suggested change
brotli_static: "on"

Copilot uses AI. Check for mistakes.
…on settings openwisp#599

Remove GZIP_STATIC_COMPRESSION and BROTLI_STATIC_COMPRESSION settings from Django
configuration as they are no longer valid with the new openwisp-utils package.
Configure nginx to serve precompressed files by adding gzip_static and brotli_static
directives to the SSL configuration. This improves performance by serving pre-compressed
.gz and .br files directly when available, rather than compressing on-the-fly.

Updated templates/openwisp2/settings.py to remove obsolete compression settings,
modified defaults/main.yml to add precompressed file serving configuration, and
updated documentation in docs/user/role-variables.rst.

Fixes openwisp#599
…on settings openwisp#599

Remove GZIP_STATIC_COMPRESSION and BROTLI_STATIC_COMPRESSION settings from Django
configuration as they are no longer valid with the new openwisp-utils package.
Configure nginx to serve precompressed files by adding gzip_static and brotli_static
directives to the SSL configuration. This improves performance by serving pre-compressed
.gz and .br files directly when available, rather than compressing on-the-fly.

Updated templates/openwisp2/settings.py to remove obsolete compression settings,
modified defaults/main.yml to add precompressed file serving configuration, and
updated documentation in docs/user/role-variables.rst.

Fixes openwisp#599
@SAMurai-16
Copy link
Copy Markdown
Author

hi @nemesifier the checks are failing even if there are no changes in the repo.

The failing test appears to be a CI environment issue rather than a code problem. Could you please advise on how to proceed?

Copy link
Copy Markdown
Member

@nemesifier nemesifier left a comment

Choose a reason for hiding this comment

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

@SAMurai-16 when the CI build does not fail due to your changes, the best thing is to:

  1. don't fight it in this PR, do your changes as if the CI Build is not failing
  2. open another PR which aims to A) Demonstrate the build fails on master, B) Help to debug it and fix it is always welcome.

…on settings openwisp#599

Remove GZIP_STATIC_COMPRESSION and BROTLI_STATIC_COMPRESSION settings from Django
configuration as they are no longer valid with the new openwisp-utils package.
Configure nginx to serve precompressed files by adding gzip_static and brotli_static
directives to the SSL configuration. This improves performance by serving pre-compressed
.gz and .br files directly when available, rather than compressing on-the-fly.

Updated templates/openwisp2/settings.py to remove obsolete compression settings,
modified defaults/main.yml to add precompressed file serving configuration, and
updated documentation in docs/user/role-variables.rst.

Fixes openwisp#599
coderabbitai[bot]
coderabbitai bot previously approved these changes Feb 14, 2026
@SAMurai-16
Copy link
Copy Markdown
Author

@SAMurai-16 when the CI build does not fail due to your changes, the best thing is to:

  1. don't fight it in this PR, do your changes as if the CI Build is not failing
  2. open another PR which aims to A) Demonstrate the build fails on master, B) Help to debug it and fix it is always welcome.

@nemesifier i have raised an issue regarding this, do check out #602

SAMurai-16 and others added 4 commits February 24, 2026 16:51
…on settings openwisp#599

Remove GZIP_STATIC_COMPRESSION and BROTLI_STATIC_COMPRESSION settings from Django
configuration as they are no longer valid with the new openwisp-utils package.
Configure nginx to serve precompressed files by adding gzip_static and brotli_static
directives to the SSL configuration. This improves performance by serving pre-compressed
.gz and .br files directly when available, rather than compressing on-the-fly.

Updated templates/openwisp2/settings.py to remove obsolete compression settings,
modified defaults/main.yml to add precompressed file serving configuration, and
updated documentation in docs/user/role-variables.rst.

Fixes openwisp#599
@nemesifier nemesifier changed the title [nginx] Configure precompressed file serving, remove Django compression settings #599 [feature] Configure precompressed file serving, remove Django compression settings #599 Mar 6, 2026
@nemesifier nemesifier changed the title [feature] Configure precompressed file serving, remove Django compression settings #599 [feature] Configured nginx to serve precompressed files (gzip/brotli) #599 Mar 6, 2026
- "application/x-font-ttf"
- "font/opentype"
# Enable precompressed gzip files serving (requires nginx with gzip_static module)
openwisp2_nginx_gzip_static: false
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

WARNING: Missing tests for new configuration variables

No tests have been added to verify that the new openwisp2_nginx_gzip_static and openwisp2_nginx_brotli_static variables are correctly rendered in the nginx configuration template. The PR checklist item for tests is also unchecked.

Per project policy, new features should include tests. Consider adding molecule/verify tests or template rendering tests that confirm:

  1. When openwisp2_nginx_gzip_static: true, the rendered nginx config contains gzip_static on;
  2. When openwisp2_nginx_brotli_static: true, the rendered nginx config contains brotli_static on;
  3. When both are false (default), neither directive appears in the config.

@kilo-code-bot
Copy link
Copy Markdown

kilo-code-bot bot commented Mar 6, 2026

Code Review Summary

Status: 8 Issues Found | Recommendation: Address before merge

Fix these issues in Kilo Cloud

Overview

Severity Count
CRITICAL 1
WARNING 4
SUGGESTION 3
Issue Details (click to expand)

CRITICAL

File Line Issue
tasks/apt.yml 55 set_fact runs unconditionally but gzip_static_check/brotli_check are only registered when openwisp2_nginx_install is true. Jinja2 does not short-circuit and, so accessing .stdout on an undefined variable raises AnsibleUndefinedVariable when nginx is not installed.

WARNING

File Line Issue
tasks/apt.yml 49 Trailing whitespace on - name: Check if nginx brotli module is available line triggers yamllint warnings
molecule/resources/verify.yml 79 Trailing whitespace on - name: Check if nginx brotli module is available line triggers yamllint warnings
molecule/resources/verify.yml 91 Trailing whitespace on shell: "grep 'brotli_static on;'..." line triggers yamllint warnings
molecule/resources/verify.yml 83–86 Test asserts gzip_static on; is present when module is available, but does not assert the directive is absent when openwisp2_nginx_gzip_static: false. The false path is untested.

SUGGESTION

File Line Issue
docs/user/role-variables.rst 171 Trailing whitespace after detected (two trailing spaces)
tasks/apt.yml 61–62 Redundant logic: the | default('auto') filter is unreachable since openwisp2_nginx_gzip_static is always defined; simplify to (openwisp2_nginx_gzip_static == true or openwisp2_nginx_gzip_static == 'auto')
templates/nginx/site-conf.j2 42 gzip_static module may not be available in all nginx installations (nginx-light does not include it)
Other Observations (not in diff)

Issues found in unchanged code or context that cannot receive inline comments:

File Observation
molecule/resources/converge.yml Sets openwisp2_nginx_gzip_static: true and openwisp2_nginx_brotli_static: true for testing, but the CI environment may not have the brotli module available. If the module is absent, the brotli test in verify.yml is silently skipped — consider documenting this expectation.
templates/openwisp2/settings.py Removal of BROTLI_STATIC_COMPRESSION = False and GZIP_STATIC_COMPRESSION = False is intentional — these settings are no longer valid with the new openwisp-utils package. Without them, CompressStaticFilesStorage will now generate .gz/.br files during collectstatic, which is the correct behavior to support the new nginx directives.
PR checklist The false case (directive absent when feature explicitly disabled) is not covered by the molecule tests.
Files Reviewed (7 files)
  • defaults/main.yml — 2 new variables added with auto default
  • docs/user/role-variables.rst — documentation updated, 1 trailing whitespace issue
  • molecule/resources/converge.yml — test variables set to true
  • molecule/resources/verify.yml — typo fixed, nginx compression tests added, 2 trailing whitespace issues, test coverage gap
  • tasks/apt.yml — module detection + set_fact added, 1 CRITICAL undefined variable bug, 1 trailing whitespace
  • templates/nginx/site-conf.j2 — conditional directives added correctly
  • templates/openwisp2/settings.py — obsolete Django settings removed correctly

…penwisp#599

Remove GZIP_STATIC_COMPRESSION and BROTLI_STATIC_COMPRESSION settings from Django configuration as they are no longer valid with the new openwisp-utils package. Configure nginx to serve precompressed files by adding gzip_static and brotli_static directives to the SSL configuration. This improves performance by serving pre-compressed .gz and .br files directly when available, rather than compressing on-the-fly.

Updated templates/openwisp2/settings.py to remove obsolete compression settings, modified defaults/main.yml to add precompressed file serving configuration, and updated documentation in docs/user/role-variables.rst.

Fixes openwisp#599
tasks/apt.yml Outdated
apt:
name: libnginx-mod-http-gzip-static
when: openwisp2_nginx_install and openwisp2_nginx_gzip_static
ignore_errors: true # May not be available on all distributions
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

WARNING: ignore_errors: true silently swallows installation failures

If libnginx-mod-http-gzip-static fails to install (e.g., package not found), the task succeeds anyway. Then when nginx loads the config with gzip_static on; (rendered because openwisp2_nginx_gzip_static: true), nginx will fail with unknown directive "gzip_static". The user enabled the feature expecting it to work, but the failure is hidden.

Consider using failed_when: false with a register + subsequent warning task, or better yet, check if the module is actually loaded before rendering the directive in the template.

tasks/apt.yml Outdated
apt:
name: libnginx-mod-brotli
when: openwisp2_nginx_install and openwisp2_nginx_brotli_static
ignore_errors: true # May not be available on all distributions
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

WARNING: ignore_errors: true silently swallows installation failures

Same issue as the gzip module task above: if libnginx-mod-brotli fails to install, the task succeeds silently, but nginx will then fail to start because brotli_static on; will be rendered in the config without the module being available. This creates a hard-to-debug failure mode where the user enabled the feature but gets a broken nginx.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
molecule/resources/verify.yml (1)

40-46: ⚠️ Potential issue | 🟡 Minor

Duplicate redis service checks - remove the incorrect one.

There are now two redis status checks: one checking redis-server (line 41) and one checking redis (line 45). Based on the role's handler and service task definitions, the correct systemd service name is redis, not redis-server (which is the APT package name).

The redis-server check on line 41 should be removed to avoid redundancy and potential confusion.

🔧 Proposed fix
-    - name: Check if redis-server is running
-      command: systemctl status redis-server
-      changed_when: false
-
     - name: Check if redis is running
       command: systemctl status redis
       changed_when: false
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@molecule/resources/verify.yml` around lines 40 - 46, Remove the duplicate
systemd status check for the APT package name: delete the task whose name is
"Check if redis-server is running" (the command using "systemctl status
redis-server") so only the correct service check "Check if redis is running"
(command "systemctl status redis") remains; this aligns verify.yml with the
role's service/task names and avoids redundancy.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tasks/apt.yml`:
- Around line 43-53: The apt tasks "Install nginx gzip static module" and
"Install nginx brotli module" should stop silently swallowing failures; either
remove ignore_errors to fail fast or register each apt result (e.g., register:
gzip_mod_result and brotli_mod_result) and propagate those flags into the nginx
template rendering so gzip_static/brotli_static directives are only enabled when
installation succeeded; also make these tasks use the existing
retries/delay/register/until pattern used elsewhere to handle transient APT
errors (add retries/delay/until around the apt calls and register the final
result variable).

---

Outside diff comments:
In `@molecule/resources/verify.yml`:
- Around line 40-46: Remove the duplicate systemd status check for the APT
package name: delete the task whose name is "Check if redis-server is running"
(the command using "systemctl status redis-server") so only the correct service
check "Check if redis is running" (command "systemctl status redis") remains;
this aligns verify.yml with the role's service/task names and avoids redundancy.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 20b2b78c-fdf1-4535-a429-a0a59aa98005

📥 Commits

Reviewing files that changed from the base of the PR and between fd319d0 and ab1ca2c.

📒 Files selected for processing (4)
  • defaults/main.yml
  • molecule/resources/converge.yml
  • molecule/resources/verify.yml
  • tasks/apt.yml
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Build debian12
  • GitHub Check: Build debian13
  • GitHub Check: Build ubuntu2404
  • GitHub Check: Build ubuntu2204
🔇 Additional comments (3)
defaults/main.yml (1)

163-170: LGTM!

The new configuration variables are well-documented with clear warnings about module requirements and safe defaults (false). The placement as top-level variables (separate from openwisp2_nginx_ssl_config) is correct and consistent with how they're referenced in the task conditions.

molecule/resources/converge.yml (1)

15-18: LGTM!

Good test coverage setup - both compression modules are enabled to validate the full feature path through the nginx configuration template and module installation tasks.

molecule/resources/verify.yml (1)

69-79: LGTM!

Good verification coverage for the new compression features. The tests appropriately check:

  1. Both directives are present in the rendered nginx config
  2. The overall nginx configuration syntax is valid

This addresses the earlier review feedback about missing tests for the new configuration variables.

…penwisp#599

Remove GZIP_STATIC_COMPRESSION and BROTLI_STATIC_COMPRESSION settings from Django configuration as they are no longer valid with the new openwisp-utils package. Configure nginx to serve precompressed files by adding gzip_static and brotli_static directives to the SSL configuration. This improves performance by serving pre-compressed .gz and .br files directly when available, rather than compressing on-the-fly.

Updated templates/openwisp2/settings.py to remove obsolete compression settings, modified defaults/main.yml to add precompressed file serving configuration, and updated documentation in docs/user/role-variables.rst.

Fixes openwisp#599
block:
# Test that enabled features appear in nginx config
- name: Check nginx config contains gzip_static and brotli_static directives
shell: "grep 'gzip_static on;' /etc/nginx/sites-enabled/openwisp2 && grep 'brotli_static on;' /etc/nginx/sites-enabled/openwisp2"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

WARNING: Test hardcodes both directives unconditionally

This shell command checks for both gzip_static on; AND brotli_static on; in a single && chain, but the test will fail if only one of the two features is enabled. Since converge.yml enables both, this works for the current test scenario, but the test is fragile — if someone runs with only one feature enabled, the test will incorrectly fail.

Consider splitting into two separate tasks, each guarded by the corresponding variable:

- name: Check nginx config contains gzip_static directive
  shell: "grep 'gzip_static on;' /etc/nginx/sites-enabled/openwisp2"
  changed_when: false
  when: openwisp2_nginx_gzip_static | default(false)

- name: Check nginx config contains brotli_static directive
  shell: "grep 'brotli_static on;' /etc/nginx/sites-enabled/openwisp2"
  changed_when: false
  when: openwisp2_nginx_brotli_static | default(false)

…penwisp#599

Remove GZIP_STATIC_COMPRESSION and BROTLI_STATIC_COMPRESSION settings from Django configuration as they are no longer valid with the new openwisp-utils package. Configure nginx to serve precompressed files by adding gzip_static and brotli_static directives to the SSL configuration. This improves performance by serving pre-compressed .gz and .br files directly when available, rather than compressing on-the-fly.

Updated templates/openwisp2/settings.py to remove obsolete compression settings, modified defaults/main.yml to add precompressed file serving configuration, and updated documentation in docs/user/role-variables.rst.

Fixes openwisp#599
tasks/apt.yml Outdated

- name: Set nginx module availability facts
set_fact:
nginx_gzip_static_available: "{{ openwisp2_nginx_gzip_static and (gzip_static_module_install.skipped | default(false)) == false and gzip_static_module_install.failed | default(false) == false }}"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

CRITICAL: Undefined variable error when openwisp2_nginx_gzip_static is false

When openwisp2_nginx_gzip_static is false, the Install nginx gzip static module task is skipped and gzip_static_module_install is never registered. Accessing gzip_static_module_install.skipped on an undefined variable will raise an Ansible error — the | default(false) filter only catches the final undefined value, not attribute access on an undefined dict.

Same issue applies to brotli_module_install on line 60.

Fix by using (gzip_static_module_install is defined and not gzip_static_module_install.skipped and not gzip_static_module_install.failed) or by adding a when guard:

- name: Set nginx module availability facts
  set_fact:
    nginx_gzip_static_available: >-
      {{ openwisp2_nginx_gzip_static
         and (gzip_static_module_install is defined)
         and not (gzip_static_module_install.skipped | default(false))
         and not (gzip_static_module_install.failed | default(false)) }}
    nginx_brotli_static_available: >-
      {{ openwisp2_nginx_brotli_static
         and (brotli_module_install is defined)
         and not (brotli_module_install.skipped | default(false))
         and not (brotli_module_install.failed | default(false)) }}

register: gzip_static_check
changed_when: false

- name: Check if brotli_static directive is present (only when module available)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

SUGGESTION: Trailing whitespace on this line may trigger linting warnings.

Suggested change
- name: Check if brotli_static directive is present (only when module available)
- name: Check if brotli_static directive is present (only when module available)

block:
# Check if modules were successfully installed and directives are present
- name: Check if gzip_static directive is present (only when module available)
shell: "grep 'gzip_static on;' /etc/nginx/sites-enabled/openwisp2 || echo 'DIRECTIVE_NOT_FOUND'"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

WARNING: Test does not assert that the directive is present when the feature is enabled

The test uses || echo 'DIRECTIVE_NOT_FOUND' to avoid failure, and only logs the result via debug. This means the test will pass even if gzip_static on; is missing from the nginx config when openwisp2_nginx_gzip_static: true is set in converge.yml.

Since converge.yml sets openwisp2_nginx_gzip_static: true, the test should assert the directive is actually present:

- name: Check if gzip_static directive is present
  shell: "grep 'gzip_static on;' /etc/nginx/sites-enabled/openwisp2"
  register: gzip_static_check
  changed_when: false
  failed_when: gzip_static_check.rc != 0

…penwisp#599

Remove GZIP_STATIC_COMPRESSION and BROTLI_STATIC_COMPRESSION settings from Django configuration as they are no longer valid with the new openwisp-utils package. Configure nginx to serve precompressed files by adding gzip_static and brotli_static directives to the SSL configuration. This improves performance by serving pre-compressed .gz and .br files directly when available, rather than compressing on-the-fly.

Updated templates/openwisp2/settings.py to remove obsolete compression settings, modified defaults/main.yml to add precompressed file serving configuration, and updated documentation in docs/user/role-variables.rst.

Fixes openwisp#599
tasks/apt.yml Outdated
when: openwisp2_nginx_install
changed_when: false

- name: Check if nginx brotli module is available
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

SUGGESTION: Trailing whitespace on this line may trigger yamllint warnings

Suggested change
- name: Check if nginx brotli module is available
- name: Check if nginx brotli module is available

…penwisp#599

Remove GZIP_STATIC_COMPRESSION and BROTLI_STATIC_COMPRESSION settings from Django configuration as they are no longer valid with the new openwisp-utils package. Configure nginx to serve precompressed files by adding gzip_static and brotli_static directives to the SSL configuration. This improves performance by serving pre-compressed .gz and .br files directly when available, rather than compressing on-the-fly.

Updated templates/openwisp2/settings.py to remove obsolete compression settings, modified defaults/main.yml to add precompressed file serving configuration, and updated documentation in docs/user/role-variables.rst.

Fixes openwisp#599
coderabbitai[bot]
coderabbitai bot previously approved these changes Mar 7, 2026
Co-authored-by: kilo-code-bot[bot] <240665456+kilo-code-bot[bot]@users.noreply.github.com>
coderabbitai[bot]
coderabbitai bot previously approved these changes Mar 7, 2026
Co-authored-by: kilo-code-bot[bot] <240665456+kilo-code-bot[bot]@users.noreply.github.com>
…penwisp#599

Remove GZIP_STATIC_COMPRESSION and BROTLI_STATIC_COMPRESSION settings from Django configuration as they are no longer valid with the new openwisp-utils package. Configure nginx to serve precompressed files by adding gzip_static and brotli_static directives to the SSL configuration. This improves performance by serving pre-compressed .gz and .br files directly when available, rather than compressing on-the-fly.

Updated templates/openwisp2/settings.py to remove obsolete compression settings, modified defaults/main.yml to add precompressed file serving configuration, and updated documentation in docs/user/role-variables.rst.

Fixes openwisp#599
coderabbitai[bot]
coderabbitai bot previously approved these changes Mar 7, 2026
tasks/apt.yml Outdated

- name: Set nginx module availability facts
set_fact:
nginx_gzip_static_available: "{{ openwisp2_nginx_install and openwisp2_nginx_gzip_static and (gzip_static_check.stdout | default('not_available')) == 'available' }}"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

CRITICAL: Undefined variable error when openwisp2_nginx_install is false

The set_fact task runs unconditionally, but gzip_static_check and brotli_check are only registered when openwisp2_nginx_install is true. When openwisp2_nginx_install is false, accessing gzip_static_check.stdout raises AnsibleUndefinedVariable — the | default('not_available') filter cannot catch attribute access on an undefined variable.

Fix by adding a when: openwisp2_nginx_install guard to the set_fact task, and providing a fallback for when the task is skipped:

- name: Set nginx module availability facts
  set_fact:
    nginx_gzip_static_available: "{{ openwisp2_nginx_gzip_static and (gzip_static_check.stdout | default('not_available')) == 'available' }}"
    nginx_brotli_static_available: "{{ openwisp2_nginx_brotli_static and (brotli_check.stdout | default('not_available')) == 'available' }}"
  when: openwisp2_nginx_install

- name: Set nginx module availability facts (nginx not installed)
  set_fact:
    nginx_gzip_static_available: false
    nginx_brotli_static_available: false
  when: not openwisp2_nginx_install

Alternatively, use (gzip_static_check is defined and gzip_static_check.stdout == 'available') to safely handle the undefined case.

- "font/opentype"
# Enable precompressed gzip files serving (requires nginx with gzip_static module)
# Note: The directive is only added if the module is already compiled into nginx
# If the module is not available, nginx will fail with "unknown directive" error
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

WARNING: Comment is inaccurate — nginx will NOT fail when the module is unavailable

The current implementation in tasks/apt.yml checks nginx -V and only sets nginx_gzip_static_available: true when the module is already compiled in. The template then conditionally omits the gzip_static on; directive when the module is absent. So nginx will not fail — the directive is silently skipped.

This comment misleads users into thinking they need the module pre-installed to avoid nginx failures, when in fact the role gracefully handles the absence.

Suggested change
# If the module is not available, nginx will fail with "unknown directive" error
# If the module is not available, the directive will be silently omitted from the nginx config

openwisp2_nginx_gzip_static: false
# Enable precompressed brotli files serving (requires nginx with ngx_brotli module)
# Note: The directive is only added if the module is already compiled into nginx
# If the module is not available, nginx will fail with "unknown directive" error
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

WARNING: Comment is inaccurate — nginx will NOT fail when the brotli module is unavailable

Same issue as the gzip comment above: the current implementation silently omits brotli_static on; when the ngx_brotli module is not compiled into nginx. The comment incorrectly states nginx will fail with an "unknown directive" error.

Suggested change
# If the module is not available, nginx will fail with "unknown directive" error
# If the module is not available, the directive will be silently omitted from the nginx config

register: nginx_gzip_module_check
changed_when: false

- name: Check if nginx brotli module is available
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

SUGGESTION: Trailing whitespace on this line may trigger yamllint warnings

Suggested change
- name: Check if nginx brotli module is available
- name: Check if nginx brotli module is available

…penwisp#599

Remove GZIP_STATIC_COMPRESSION and BROTLI_STATIC_COMPRESSION settings from Django configuration as they are no longer valid with the new openwisp-utils package. Configure nginx to serve precompressed files by adding gzip_static and brotli_static directives to the SSL configuration. This improves performance by serving pre-compressed .gz and .br files directly when available, rather than compressing on-the-fly.

Updated templates/openwisp2/settings.py to remove obsolete compression settings, modified defaults/main.yml to add precompressed file serving configuration, and updated documentation in docs/user/role-variables.rst.

Fixes openwisp#599
- "font/opentype"
# Precompressed gzip files serving - automatically enabled when nginx gzip_static/brotli_static module is available
# The system detects module availability and enables the feature automatically
# These variables are kept for backwards compatibility but no longer control the behavior
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

WARNING: Variables declared as "backwards compatibility" are actually dead code — they are never read by the role

The comment claims these variables are kept for backwards compatibility, but openwisp2_nginx_gzip_static and openwisp2_nginx_brotli_static are never referenced in tasks/apt.yml. The set_fact task that controls the feature only checks openwisp2_nginx_install and the nginx -V output:

nginx_gzip_static_available: "{{ openwisp2_nginx_install and (gzip_static_check.stdout | default('not_available')) == 'available' }}"

This means:

  • A user who sets openwisp2_nginx_gzip_static: false expecting to disable the feature will find it still gets enabled if the module is available in their nginx build.
  • A user who sets openwisp2_nginx_gzip_static: true expecting to enable the feature will find it has no effect if the module is absent.

The variables should either be wired into the set_fact logic (e.g. openwisp2_nginx_gzip_static and (gzip_static_check.stdout ...) == 'available') or removed entirely. Keeping them as no-ops while documenting them as user-facing configuration options is misleading.

…penwisp#599

Remove GZIP_STATIC_COMPRESSION and BROTLI_STATIC_COMPRESSION settings from Django configuration as they are no longer valid with the new openwisp-utils package. Configure nginx to serve precompressed files by adding gzip_static and brotli_static directives to the SSL configuration. This improves performance by serving pre-compressed .gz and .br files directly when available, rather than compressing on-the-fly.

Updated templates/openwisp2/settings.py to remove obsolete compression settings, modified defaults/main.yml to add precompressed file serving configuration, and updated documentation in docs/user/role-variables.rst.

Fixes openwisp#599
coderabbitai[bot]
coderabbitai bot previously approved these changes Mar 7, 2026
when: openwisp2_nginx_install
changed_when: false

- name: Set nginx module availability facts
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

CRITICAL: set_fact runs unconditionally but gzip_static_check and brotli_check are only registered when openwisp2_nginx_install is true

Jinja2 does not short-circuit and — both sides of the expression are always evaluated. When openwisp2_nginx_install is false, gzip_static_check is an undefined variable, and accessing .stdout on it raises AnsibleUndefinedVariable. The | default('not_available') filter cannot rescue attribute access on an undefined dict.

Fix by adding a when: openwisp2_nginx_install guard and a fallback task:

- name: Set nginx module availability facts
  set_fact:
    nginx_gzip_static_available: >-
      {{ (gzip_static_check.stdout | default('not_available')) == 'available' and
         (openwisp2_nginx_gzip_static == true or openwisp2_nginx_gzip_static == 'auto') }}
    nginx_brotli_static_available: >-
      {{ (brotli_check.stdout | default('not_available')) == 'available' and
         (openwisp2_nginx_brotli_static == true or openwisp2_nginx_brotli_static == 'auto') }}
  when: openwisp2_nginx_install

- name: Set nginx module availability facts (nginx not installed)
  set_fact:
    nginx_gzip_static_available: false
    nginx_brotli_static_available: false
  when: not openwisp2_nginx_install

# - false: explicitly disable even when module is available
openwisp2_nginx_gzip_static: auto
# Precompressed brotli files serving control
# - 'auto' (default): automatically enabled when nginx ngx_brotli module is detected
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

SUGGESTION: Trailing whitespace at end of line

Suggested change
# - 'auto' (default): automatically enabled when nginx ngx_brotli module is detected
# - 'auto' (default): automatically enabled when nginx ngx_brotli module is detected

…penwisp#599

Remove GZIP_STATIC_COMPRESSION and BROTLI_STATIC_COMPRESSION settings from Django configuration as they are no longer valid with the new openwisp-utils package. Configure nginx to serve precompressed files by adding gzip_static and brotli_static directives to the SSL configuration. This improves performance by serving pre-compressed .gz and .br files directly when available, rather than compressing on-the-fly.

Updated templates/openwisp2/settings.py to remove obsolete compression settings, modified defaults/main.yml to add precompressed file serving configuration, and updated documentation in docs/user/role-variables.rst.

Fixes openwisp#599
Copy link
Copy Markdown
Member

@nemesifier nemesifier left a comment

Choose a reason for hiding this comment

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

It looks pretty good! I'll do some testing as soon as I can to confirm all works as expected and then merge. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feature] Configure nginx to serve precompressed files (gzip/brotli)

3 participants