From 0906838193b480792f154320f41f26f8258dee5d Mon Sep 17 00:00:00 2001 From: catborise Date: Mon, 12 Oct 2026 08:27:14 +0300 Subject: [PATCH] fix(nginx): browsers revalidate static files Static URLs carry no version, but nginx served them with expires max, so after an update or a theme change browsers kept the old CSS and JS. They now revalidate each load (304 when unchanged). CI checks the header, the 304 and that a changed file is sent again. --- .github/workflows/test.yml | 18 ++++++++++++++++++ README.md | 1 + conf/nginx/webvirtcloud.conf | 4 +++- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index aa799485..b1792580 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -156,6 +156,24 @@ jobs: - name: Import Compiled Dependencies run: docker exec wvc /srv/webvirtcloud/venv/bin/python3 -c "import libvirt, ldap, lxml.etree, psycopg, sass" + # Static URLs carry no version: browsers must revalidate them + - name: Static Files Revalidated + run: | + url=http://127.0.0.1:8080/static/css/wvc-main.min.css + header() { tr -d '\r' | awk -v h="$1" 'tolower($0) ~ "^" h ":" {sub(/^[^:]*: */, ""); print}'; } + h=$(curl -s -m 5 -D - -o /dev/null "$url") + [ "$(echo "$h" | header cache-control)" = no-cache ] || { echo "$h"; exit 1; } + etag=$(echo "$h" | header etag) + [ -n "$etag" ] + h=$(curl -s -m 5 -D - -o /dev/null -H "If-None-Match: $etag" "$url") + echo "$h" | head -1 | grep -q " 304" || { echo "$h"; exit 1; } + [ "$(echo "$h" | header cache-control)" = no-cache ] + docker exec wvc sh -c 'echo "/* changed */" >> /srv/webvirtcloud/staticfiles/css/wvc-main.min.css' + h=$(curl -s -m 5 -D - -o /dev/null -H "If-None-Match: $etag" "$url") + echo "$h" | head -1 | grep -q " 200" || { echo "$h"; exit 1; } + new=$(echo "$h" | header etag) + [ -n "$new" ] && [ "$new" != "$etag" ] + # The browser reaches the console through nginx on the panel's port - name: Console Through Nginx Only run: | diff --git a/README.md b/README.md index ccd7e615..9c91110b 100644 --- a/README.md +++ b/README.md @@ -555,6 +555,7 @@ A rollback leaves the clone on a detached HEAD at the restored commit; the updat - After a live migration the VM's NVRAM file is deleted on the source, when it is in libvirt's `/var/lib/libvirt/qemu/nvram` and the destination does not share that directory (a VM created there later with the same name would start with those UEFI variables). - gstfsd finds the guest's operating system the way libguestfs inspects it, so a root on LVM works, and it always answers (an error when it finds no or several operating systems). Update `/usr/local/bin/gstfsd` on every compute (see [Adding a Compute Node](#adding-a-compute-node), step 3). - A theme picked on the Settings page rewrites two tracked files; the update and rollback steps put back the shipped theme. Pick yours again afterwards, also after Docker recreates the container. +- With the bundled nginx config, browsers revalidate static files on each load (304 when unchanged), so an update or a theme change shows without a hard reload. Files cached before this update can stay until a hard reload (Ctrl+F5) of each affected page, or until the site's browser cache is cleared once; an external caching proxy may need a purge. - Docker no longer publishes port 6080; the console goes through nginx on the panel's port (`WS_PUBLIC_PORT`, default 80). ## Usage diff --git a/conf/nginx/webvirtcloud.conf b/conf/nginx/webvirtcloud.conf index 714c1487..83f0b223 100644 --- a/conf/nginx/webvirtcloud.conf +++ b/conf/nginx/webvirtcloud.conf @@ -14,7 +14,9 @@ server { location /static/ { alias /srv/webvirtcloud/staticfiles/; - expires max; + # URLs carry no version: browsers revalidate (304 if unchanged), so an + # update or a theme change shows on the next load + expires -1; } location / {