Version 1.33.0 - June 23, 2026
Features
- Supply Depot — Custom Apps: The Supply Depot is NOMAD's new home for installable apps, and it now lets you run your own custom Docker containers — not just the curated catalog. Specify an image, port mappings, volume binds, environment variables, and memory/CPU limits, and NOMAD spins it up as a managed sibling container. A live, debounced pre-flight check warns about port conflicts and resource limits as you type and hard-blocks unsafe configurations, with an "install anyway" override for warning-only cases (e.g. an untrusted registry or a
:latesttag). Installed custom apps can be edited, updated (re-pull latest + recreate with a safe rollback if the new container fails), and removed (optionally deleting the image), and every installed app — curated or custom — gets per-container Logs and Stats modals. Host-path binds are hardened against escapes and logs/stats are scoped to NOMAD-managed containers only. Thanks @jakeaturner for the contribution! - Supply Depot — Curated App Onboarding & Fixes: Each curated app now ships with NOMAD-specific getting-started docs (first run, default logins, where data lives, what does and doesn't work offline), deep-linked from a Manage › Docs item on the card. Alongside it is a round of install fixes so the nine documented apps — Stirling PDF, File Browser, Calibre-Web, IT Tools, Excalidraw, Homebox, Vaultwarden, Jellyfin, Meshtastic Web — work out of the box: seeded logins instead of random passwords buried in logs, a bundled Calibre library, HTTPS-by-default where the app requires a secure context (Vaultwarden), corrected internal ports (Meshtastic Web), pre-created media folders (Jellyfin), and a swap to a maintained image (Homebox). You can now also edit curated apps, not just custom ones — edits are merged into the app's existing config (preserving advanced settings like GPU device requests) and flag the app so the seeder stops overwriting it, while untouched apps still receive catalog updates. Thanks @chriscrosstalk for the contribution!
- Automatic Core Updates: NOMAD's own admin/core image can now update itself hands-off, gated by layered safety checks. It's opt-in and off by default, runs only inside a user-configured time window, and applies only same-major, strictly-newer GA releases (major bumps stay manual) past a configurable cool-off — behind pre-flight checks for the update sidecar, no in-flight updates/downloads/installs, and sufficient host disk. It auto-disables after repeated genuine failures, while transient offline release lookups are treated as harmless skips. Settings → Updates exposes the toggle, window, cool-off, and live status. This is the first leg of the auto-update trilogy. Thanks @jakeaturner for the contribution!
- Automatic App Updates: Installed apps (the "Supply Depot" sibling containers) can now keep themselves up to date with opt-in, hands-off minor/patch updates, mirroring the core auto-update feature. Updates are gated behind a two-level opt-in — a global master switch in Settings → Updates and a per-app toggle in the Supply Depot — and respect the shared update window, cool-off period, disk/in-progress pre-flight checks, and per-app failure backoff. Major versions are never auto-applied. Thanks @jakeaturner for the contribution!
- Automatic Content Updates: Completing the auto-update trilogy, installed Kiwix ZIM files and PMTiles maps can now update themselves on an opt-in basis. Content updates run on their own dedicated overnight window and bandwidth cap (separate from the app/core schedule, since content downloads are multi-GB), check the upstream Kiwix and PMTiles catalogs directly (no more reliance on external Project N.O.M.A.D. API), and keep the AI Knowledge Base in sync when a ZIM is replaced. Thanks @jakeaturner for the contribution!
- Supply Depot — Custom Launch URLs: You can now override an app's "Open" link with a reverse-proxy or local-DNS address (e.g.
https://jellyfin.myhomelab.net). The override is stored separately so the default link is always recoverable, survives reseeds/upgrades, and is validated on both client and server. Thanks @jakeaturner for the contribution! - Supply Depot — Version & Update visibility: App cards now show the installed version next to the app name (e.g.
Kiwix · 3.7.0), and the "Update available" pill now stands out with a solid desert-orange fill so available updates actually draw the eye. Thanks @chriscrosstalk for the contribution! - Maps — Persistent View: The Maps page now remembers your position and zoom across refreshes instead of resetting to the default US-wide view. The saved view is bounds-checked, so a corrupt value safely falls back to the default. Thanks @chriscrosstalk for the contribution!
- Content Manager — Rescan Library: A new "Rescan Library" button rebuilds the Kiwix index from the ZIM files currently on disk, so files sideloaded outside NOMAD's download flow (USB stick, SSH, network share) can be served without dropping to a terminal. It reports how many new books were found and, in library mode, hot-reloads without a container restart. Thanks @chriscrosstalk for the contribution!
- Configuration — Redis database selection: Added a
REDIS_DBenvironment variable so operators can pick a Redis logical database (0–15) for the job queue and live-update transport. This prevents key collisions when a single Redis instance is shared across multiple stacks (common in homelabs). Defaults to db 0, preserving existing behavior. Thanks @johno10661 for the contribution! - Advanced Settings — Internet Test URL: Added a new Advanced Settings page with an option to override the default internet test "beacon" URL (more advanced settings to come). Previously, overriding this URL required an ENV variable change and container restart. The legacy ENV variable is still respected if you've set it. Thanks @jakeaturner for the contribution!
- RAG: Embedding jobs can now be cancelled, allowing users to clear stuck jobs that haven't explicitly failed. Thanks @jakeaturner for the contribution!
Bug Fixes
- Storage: When the admin storage volume is relocated to another disk, child apps (Kiwix, Ollama, Qdrant, Flatnotes, Kolibri) now automatically follow to the new location instead of mounting the old, empty path. The host storage root is now derived from the admin's actual mount, with an explicit
NOMAD_STORAGE_PATHoverride and clearer compose comments. Thanks @chriscrosstalk for the fix! - System: A failed service update now rolls back to the previous container if the new one fails to start, so the service stays up on the old version instead of being left down. Also clears any stale leftover container so a retry can't wedge indefinitely. Thanks @chriscrosstalk for the fix!
- System: Service install failures caused by a host port conflict (commonly a native Ollama install already on port 11434) now show a clear, actionable message with the exact commands to resolve it, instead of a raw Docker error. Thanks @chriscrosstalk for the fix!
- System: The per-service Update button is now disabled and shows "Updating..." while an update is in flight, preventing double-clicks that previously raced into Docker errors. The in-progress state is durable, so it survives a page reload during a multi-GB pull. Thanks @chriscrosstalk for the fix!
- System Updates: Update checks no longer crash for images with more than 1,000 tags (e.g Ollama). Registry pagination URLs are now resolved correctly, so the "Check for Updates" flow returns versions instead of failing silently — fixing Ollama appearing pinned at an old version. Thanks @chriscrosstalk for the fix!
- System: Internet status checks no longer report "No internet connection" on networks that block or hijack Cloudflare's 1.1.1.1. The check now probes additional hosts the app already contacts (GitHub and the Project N.O.M.A.D. API) in parallel and accepts any HTTP response as "online." Thanks @akashsalan for the fix!
- AI Assistant: Oversized embedding chunks are now truncated and retried instead of being silently dropped, ending the retry storm that could peg the GPU and flood logs (the "api/embed for weeks" issue). The OpenAI-compatible fallback path now also passes context and truncation settings. Thanks @chriscrosstalk for the fix!
- AI Assistant: Chat suggestions now use your selected model (falling back to the smallest installed model) instead of the largest. This prevents a flagship model that exceeds available VRAM from hanging the chat page and returning a 500 error. Thanks @johno10661 for the fix!
- AI Assistant: The assistant no longer disclaims "Sorry, I couldn't find specific context regarding X..." when relevant material was actually retrieved. The RAG prompt now treats retrieved context as the authoritative source and falls back to general knowledge silently, the model-visible relevance scores that primed smaller models to distrust correct context were replaced with neutral source-title labels, and a conservative heading-match boost improves the ranking of already-retrieved chunks. Thanks @jakeaturner for the fix!
- Knowledge Base: The embedded-chunk count for batched ZIM ingestion is now persisted accurately across continuation batches, instead of reporting only the final batch's count. Thanks @Metbcy for the fix!
- Knowledge Base: The "ingestion may have stalled" (partial-stall) warning no longer fires falsely on link-out- or PDF-heavy ZIMs that legitimately have little embeddable text. Thanks @chriscrosstalk for the fix!
- Knowledge Base: ZIM ingestion progress no longer freezes at 99% on multi-page archives (e.g. iFixit). Progress now creeps forward monotonically and only reports 100% on the genuinely final batch. Thanks @chriscrosstalk for the fix!
- Content: Installing a newer version of a curated map or ZIM now removes the superseded file from disk, preventing silent accumulation of orphaned content (potentially hundreds of GB). Deletion is gated behind strict safety rails — only tracked, genuinely-replaced, strictly-newer files within the content store are ever removed; sideloaded files are never touched. Thanks @chriscrosstalk for the fix!
- Content: Curated Wikipedia-themed ZIMs (e.g.
wikipedia_en_medicine_maxifrom Medicine → Comprehensive) are no longer wiped on restart. Reconciliation now skips only the single file actually managed by the Wikipedia selector, matched by exact filename. Thanks @chriscrosstalk for the fix! - Maps: Having both an old and new copy of the same map region on disk no longer blanks the entire map. Map sources are now de-duplicated to the newest file per region, and already-broken installs recover automatically on the next page load. Thanks @chriscrosstalk for the fix!
- Information Library (Kiwix): Kiwix now self-heals a missing or corrupt library file on startup by rebuilding it from the ZIM files on disk, instead of coming up with an empty library and no path to recovery. Thanks @chriscrosstalk for the fix!
- Docker: Failed image pulls (dropped/metered connection, bad manifest, disk full mid-pull) are now correctly treated as failures across all pull paths, instead of proceeding to create a container from a missing or partial image and surfacing a confusing downstream error. Thanks @chriscrosstalk for the fix!
- Security: Hardened the private-URL/SSRF guard by replacing the regex blocklist with proper IP-range classification (
ipaddr.js) and normalizing the host first. This blocks alternate IP encodings and trailing-dot bypasses (e.g.localhost.) while no longer over-blocking legitimate public addresses. RFC1918 ranges and bare LAN hostnames remain allowed for local appliances. Thanks @chriscrosstalk for the fix! - Install: Hardened the install script — the NVIDIA toolkit GPG step now runs non-interactively so it doesn't silently skip on non-TTY installs, and helper-script downloads now retry to reduce transient partial-install failures. Thanks @Gujiassh for the fix!
Improvements
- License & Docs: Corrected the package license metadata to
Apache-2.0(the project has been Apache-2.0 for some time), added a real project description, and fixed a dead Troubleshooting link plus several README typos. Thanks @aqilaziz for the contribution! - Docs: Fixed a few typos and punctuation in the README. Thanks @teccdev for the contribution!
- Dependencies: Bumped React and React DOM. Thanks @jakeaturner for the contribution!
- Dependencies: Bumped autoprefixer. Thanks @jakeaturner for the contribution!
- Dependencies: Bumped BullMQ to 5.77.6 and updated affected job calls to the new arguments shape. Thanks @jakeaturner for the contribution!
- Supply Depot: Pinned all curated image versions to ensure consistent baseline deployments. Thanks @jakeaturner for the contribution!
- Supply Depot: Bumped the default versions of CyberChef to 10.24.0 and Ollama to 0.24.0. Thanks @jakeaturner for the contribution!
📝 All Changes
- fix: lazy-connect + retry for ioredis to avoid blocked startup (f4af81e)
- chore(release): set version to 1.33.0-rc.1 (76ce725)
- chore(docs): update release notes (9609edc)
- fix(supply-depot): bump default Ollama and CyberChef image versions (#1036) (0143afe)
- fix(supply-depot): ensure all curated images pinned to specific versions (#1033) (5af27e9)
- feat(RAG): adds the ability to cancel all embedding jobs (#1034) (88ac4d5)
- chore(docs): update release notes (f0142b6)
- feat: configurable internet test url override in new Advanced Settings page (4a795df)
- fix(UI): unifies Supply Depot icon and improves loading UX (#1022) (02c9f72)
- feat(KnowledgeBase): add document viewer, download, metadata, and sorting (#721) (5181637)
- fix(zim): stabilize uploader state to avoid cancel on tab refocus (fad9e30)
- feat(zim): add zim uploader in content manager (a7d0585)
- fix(queue): share one ioredis connection across BullMQ queues and workers (#1009) (fe6735f)
- chore(deps): bump mysql2 in admin (#1021) (b507b8b)
- feat: replace legacy Kolibri image default with latest v19 image (#1019) (8982d93)
- fix: pin default meshcore web image (1b040c8)
- build: ensure openssl installed in admin container (475781f)
- feat(supply-depot): add MeshCore Web with self-signed HTTPS (bd65c88)
- feat(supply-depot): add uninstall for curated apps (#1006) (83576ec)
- docs: document Supply Depot + auto-updates in README (e2beb7e)
- docs: update in-app docs for v1.33 Supply Depot + auto-updates (536ad49)
- chore: force bump main version (61ef8f3)
- docs: update release notes (5eb208f)
- fix(bullmq): bump to 5.77.6 and update set calls w new args shape (37ad684)
- chore(deps): bump autoprefixer (d497244)
- chore(deps): bump react and react-dom (b6a0805)
- feat(content): opt-in automatic updates for installed ZIM & map content (6a2d4c2)
- fix(system): prevent false offline reports when Cloudflare endpoint is unreachable (9de6473)
- fix(content): remove superseded curated map/ZIM files when a new version installs (bbd62d8)
- fix(chat): prefer selected model for suggestions, fall back to smallest (2ae30a4)
- refactor(supply-depot): extract version and subtitle helpers instead of IIFE for readability (e5565d1)
- feat(supply-depot): show installed version on cards + make Update pill stand out (4ece29b)
- fix(updates): resolve relative registry pagination URL so tag listing doesn't crash (#945) (5de58da)
- feat(maps): persist map view across refresh (da60c6c)
- fix(maps): dedupe map sources by region so duplicate files don't blank the map (9b84d3a)
- fix(AI): truncate-and-retry oversized embed chunks; stop 30x retry storm (#881) (a315ce0)
- fix(content): narrow Wikipedia reconcile-skip to the managed selection file (df47139)
- fix(system): disable Update button while a service update is in flight (#931) (663c159)
- fix(kiwix): self-heal a missing or corrupt library XML on startup (1b9f4f3)
- feat(supply-depot): add custom launch URLs for apps (026ab6d)
- fix(security): harden assertNotPrivateUrl with ipaddr.js + host normalization (ca5ec17)
- fix(docker): reject failed image pulls instead of treating them as success (98d2356)
- fix(KB): stop ZIM ingestion progress freezing at 99% on multi-page archives (36068c6)
- fix(KB): stop partial_stall warning firing on atypical ZIMs (link-out/PDF-heavy) (3977c72)
- fix(system): roll back service update when the new container fails to start (25000b9)
- docs: fix out of place JSDoc comment (dfc284c)
- fix(system): show a clear message when a service port is already in use (3f574e4)
- feat(supply-depot): opt-in automatic updates for installed apps (cf8db62)
- feat(system): add opt-in automatic updates for the core NOMAD app (02d985d)
- fix(KB): persist accumulated chunk count across batched ZIM dispatches (d175259)
- feat(config): respect REDIS_DB env var for queue and transmit (f553a0d)
- fix(install): harden toolkit and helper script downloads (e1c7435)
- chore: align package license with Apache-2.0 and fix README docs links/typos (ccc221f)
- fix(storage): match default prefix too when relocating child-app binds (057fb69)
- fix(storage): derive child-app bind paths from the admin's actual storage mount (fab15c6)
- fix: minor type guarding fixes after axios bump (b2bea19)
- fix(supply-depot): reintroduce app update UI (555ffa8)
- feat(supply-depot): per-app onboarding docs, install fixes, and in-app Docs links (f488f08)
- fix(supply-depot): show clean port + lock on card pill for https:port ui_location (b867419)
- feat(supply-depot): scheme-aware service links (https:port) for TLS-serving apps (3501144)
- fix(supply-depot): correct Meshtastic Web internal port (80->8080); add catalog port audit script (7b1b480)
- feat: edit curated apps + fix dropdown clip + stale _old rollback (02c33b2)
- feat: supply depot (be434d7)
- feat(zim): add "Rescan Library" button for sideloaded ZIM files (e38dbf8)
- chore(deps): bump axios to 1.17.0 in admin (7943ae5)
- Fix a few typos and punctuation in README.md (820c5c4)
- fix(rag): improve context-reliance hedging and use heading metadata at query time (b8961d2)
- docs: update release notes (17630c0)