The branch was 12 commits behind dev and GitHub reported it CONFLICTING, which is
why the real CI workflow had not run since 2026-08-10 - a conflicting PR has no
mergeable ref, so pull_request-triggered workflows are skipped. Only the
lightweight checks (semantic title, CodeQL, CodeRabbit) were still reporting,
which made the PR look green while nothing was actually being tested.
Three conflicts, all of them this branch's barrel-diet work meeting dev's new
What's Up Docker integration. In every case the branch's structure is kept and
WUD is absorbed into it rather than the reverse:
integrations/base/creator.ts keep the lazy loader map; add wud as
() => import(...) rather than dev's static import,
which would have undone the lazy creator
integrations/src/index.ts keep the slim barrel; re-export WudStats and
WudContainerUpdate as `export type`, which is
erased at build and so adds no runtime module
widgets/src/index.tsx stays deleted - this was the barrel that put
every widget in the initial client graph
Registering WUD in the slimmed structures then needed three more entries that the
merge could not infer: base/kind-map.ts (type-only kind -> class map),
widgets/src/import.ts (type-only WidgetImports map, both the import and the
member). Each was found by typecheck rather than guessed at.
Verified: 37/37 packages typecheck, 1866/1881 unit tests pass. The 3 failures are
home-assistant and pi-hole, both testcontainers-based; both pass 11/11 in
isolation and fail only under 150-file parallel load with the container's payload
half-initialised.
Two further wins, both measured on a restored 28-widget board behind a real
demo session (scripts/benchmarks/stress-restore.mts).
--max-semi-space-size=4 in run.sh. --max-old-space-size only bounds the old
generation; V8 also sizes the young generation generously (16 MB per
semi-space) and that slack is pure resident memory. 4 MB cut idle anonymous
memory 120.0 -> 97.2 MiB and peak 710.6 -> 560.2 MiB. It costs CPU, as any
GC-space reduction does — 15.8 -> 17.1 CPU-seconds over the run, ~8% — with
no board-load latency regression (median 594 -> 570 ms). Overridable via
HOMARR_MAX_SEMI_SPACE_SIZE.
serverExternalPackages for the remaining server-only dependencies. Bundling
a package inlines its transitive graph into a chunk that is compiled at boot
even when the code path never runs; leaving it external makes it a lazy
require. Adding winston, drizzle-orm, ical.js, jszip, ldapts, node-unifi,
@kubernetes/client-node and linkedom took idle to 90.3 MiB and board-loaded
209.6 -> 164.6 MiB, with slightly lower CPU (16.3s) and latency (549 ms).
The trade-off is image size: 388 -> 401 MB, because those packages now ship
in node_modules instead of being tree-shaken into chunks.
Cumulative vs the merge-base: idle 141.7 -> 90.3 MiB (-36%), board loaded
257.8 -> 164.6 MiB (-36%), under load 392.7 -> 302.5 MiB (-23%).
The harness now proves the session rather than inferring it: it asserts an
anonymous request to the private board is denied, requires the Auth.js
session cookie after sign-in, and reports whether it had to modify the
restored data at all (now "none"). It also records cgroup CPU seconds and
board-load latency, so a memory win bought with CPU cannot hide.
pnpm test 144/144 files, 1795 tests; typecheck and lint clean.
* fix: keep nginx IPv6 listen only when IPv6 is available (#4596)
Commit 2c48b1896 (1.45.2) made the internal nginx proxy listen on the IPv6
wildcard ('listen [::]:7575;'), which aborts nginx startup on hosts/VMs with
IPv6 disabled:
nginx: [emerg] socket() [::]:7575 failed (97: Address family not supported by protocol)
A plain revert would reintroduce #2697 and break IPv6-only/dual-stack
environments where this listener is required. Instead, only emit the IPv6
listen directive when the host actually has IPv6 configured.
Reuse the envsubst step run.sh already performs: compute NGINX_LISTEN_IPV6
from /proc/net/if_inet6 and substitute it into the template. proc files always
report size 0, so presence is detected by grepping the file (not 'test -s').
* fix: honor HOMARR_DISABLE_IPV6 override in nginx config generation
Review feedback on #6539: give users an explicit opt-out from the IPv6
listener even when the host reports IPv6. The issue reporter (#4596)
requested such an env var, and the pattern matches the existing
ENABLE_DNS_CACHING IPv6 toggle. Auto-detection behavior is unchanged when
the var is unset. Validated in containers: override wins, dual-stack
preserved by default, IPv4-only fallback on IPv6-less hosts.
* fix: rdb files can not be saved because of permission issues bug: redis can not save RDB files #318
* refactor: move db and redis dumps to /appdata directory
* feat: add user groups
* wip: add unit tests
* wip: add more tests and normalized name for creation and update
* test: add unit tests for group router
* fix: type issues, missing mysql schema, rename column creator_id to owner_id
* fix: lint and format issues
* fix: deepsource issues
* fix: forgot to add log message
* fix: build not working
* chore: address pull request feedback
* feat: add mysql migration and fix merge conflicts
* fix: format issue and test issue
* feat: make tasks script run in docker
* feat: make websocket server work in docker
* fix: format issue
* fix: broken lockfile
* fix: non matching typescript versions
* config: add dockerfile
* feat: add working dockerfile for nest and next app with sqlite migration
---------
Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>