NUT v2.8.4: compiled from the source code#477
NUT v2.8.4: compiled from the source code#477alexcustos wants to merge 7 commits intohassio-addons:mainfrom
Conversation
WalkthroughThe PR replaces pre-built NUT packages with a multi-stage Docker build that compiles NUT from source, adds build-time metadata labels, and changes runtime directory handling in the init script from Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🧰 Additional context used🧠 Learnings (1)📚 Learning: 2025-11-22T20:51:21.979ZApplied to files:
🔇 Additional comments (6)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
nut/Dockerfile (1)
18-19: Add SHA256 checksum verification for NUT 2.8.4 release download.The tarball download on line 18 lacks integrity verification. The NUT project provides official SHA-256 checksums for all releases, including v2.8.4. Adding verification improves build reproducibility and detects potential corruption or tampering.
Update the Dockerfile to validate the downloaded archive:
&& curl -L -O https://github.com/networkupstools/nut/releases/download/v2.8.4/nut-2.8.4.tar.gz \ + && echo "0130ba82ea79f04ba4f34c5249a85943977efd984ed7df6aec1a518d5a3594f8 nut-2.8.4.tar.gz" | sha256sum -c - \ && tar -xzvf nut-2.8.4.tar.gz \
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
nut/Dockerfile(1 hunks)nut/config.yaml(1 hunks)nut/rootfs/etc/cont-init.d/nut.sh(1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: PaulSD
Repo: hassio-addons/addon-nut PR: 474
File: nut/Dockerfile:11-13
Timestamp: 2025-11-22T20:51:21.979Z
Learning: The hassio-addons/addon-nut repository uses ghcr.io/hassio-addons/debian-base:9.1.0 as its base image, which is based on debian:13.2-slim (trixie/stable). This addon should use trixie-based images going forward.
📚 Learning: 2025-11-22T20:51:21.979Z
Learnt from: PaulSD
Repo: hassio-addons/addon-nut PR: 474
File: nut/Dockerfile:11-13
Timestamp: 2025-11-22T20:51:21.979Z
Learning: The hassio-addons/addon-nut repository uses ghcr.io/hassio-addons/debian-base:9.1.0 as its base image, which is based on debian:13.2-slim (trixie/stable). This addon should use trixie-based images going forward.
Applied to files:
nut/Dockerfile
🔇 Additional comments (6)
nut/rootfs/etc/cont-init.d/nut.sh (1)
14-14: Directory creation ensures NUT runtime initialization succeeds.Line 14 correctly creates the required runtime directories for the source-compiled NUT installation. The
mkdir -pensures the command is idempotent and won't fail if directories already exist, supporting the new initialization workflow.nut/config.yaml (1)
2-2: Version reflected in addon name.The name change to "Network UPS Tools v2.8.4" aligns with the source compilation to v2.8.4 in the Dockerfile and matches the PR objectives to upgrade from v2.8.1.
nut/Dockerfile (4)
1-5: Multi-stage build architecture is well-structured.The base → builder → app pattern is appropriate for this use case, enabling efficient artifact reuse while keeping the final image lean by excluding build tools and headers. The use of trixie-based
ghcr.io/hassio-addons/debian-base:9.1.0aligns with repository standards.Also applies to: 27-27
9-13: Build dependencies appear comprehensive for NUT compilation.The included libraries (libusb-1.0-0-dev, libsnmp-dev, libssl-dev, libxml2-dev, libmodbus-dev, libltdl-dev) support the major feature set that will be enabled via the configure flags on line 21–23.
41-41: usbutils version 1:018-2 is valid and available in Debian Trixie.The pinned version exists in the Debian Trixie repositories and is compatible with the base image.
35-35: NUT_QUIET_INIT_UPSNOTIFY is a documented NUT variable—no action needed.The environment variable
NUT_QUIET_INIT_UPSNOTIFY=truesuppresses initialization-time console/log messages from NUT daemons about their inability to send lifecycle notifications to service managers (e.g., systemd). This is a valid, documented variable in NUT 2.8.4 and is appropriate for container images where such startup verbosity should be minimized.
nut/Dockerfile
Outdated
| && ./configure --prefix=/usr --sysconfdir=/etc/nut --enable-static \ | ||
| --with-usb --with-modbus --with-snmp --with-nut-scanner --with-ssl \ | ||
| && make \ |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
NUT 2.8.4 lbrb_log_delay_sec lbrb_log_delay_without_calibrating APC driver options
💡 Result:
Summary — what these options do (usbhid-ups / APC driver):
-
lbrb_log_delay_sec = N
Delay propagating/logging LB (low battery) or LB+RB (low + replace battery) states until they persist N seconds. Useful for APC BX/BVK/BK models that briefly toggle LB/RB/OK during calibration or firmware quirks. [1][2] -
lbrb_log_delay_without_calibrating
Apply the lbrb_log_delay_sec behaviour even when the UPS is not reporting a calibration sequence (i.e., suppress short LB/RB flaps regardless of a calibrating indication). [1][2] -
Context and reason
These options were added to suppress spurious short-lived low-battery / replace-battery notifications seen on some APC models (notably BXnnnnMI circa 2023–2024 and some BVK/BK variants). They were introduced in the recent NUT 2.8.x series (PR/NEWS entries). [2][3]
How to set (example ups.conf snippet)
- In the usbhid-ups driver section (replace name/path as appropriate):
driver = usbhid-ups
port = auto
pollinterval = 2
lbrb_log_delay_sec = 3
lbrb_log_delay_without_calibrating
Notes / recommendations
- Choose lbrb_log_delay_sec small (1–5s) to ignore brief spurious events but not hide real battery problems. [1][2]
- If unsure, test with logging enabled and adjust the seconds until spurious LB/RB events stop appearing. [1][3]
Sources
[1] usbhid-ups manual page (options: lbrb_log_delay_sec, lbrb_log_delay_without_calibrating).
[2] NUT release notes / changelog describing the option addition for APC BX/BVK/BK workarounds.
[3] NUT user/developer discussion (bug reports/PR) mentioning example settings and use for BX series.
🌐 Web query:
NUT 2.8.4 changelog APC BX950MI USB driver support
💡 Result:
Short answer: Yes — NUT 2.8.4 (usbhid-ups) includes improved APC USB/HID support and the APC Back-UPS BX950MI is reported working with the usbhid-ups driver. See the 2.8.4 release notes (usbhid-ups improvements) and the GitHub issue where BX950MI users confirm operation. [1][2][3]
Sources:
- NUT 2.8.4 release notes — mentions usbhid-ups improvements. [1]
- GitHub issue reporting APC BX950MI supported by usbhid-ups (#2741). [2]
- NUT 2.8.4 download page (version/timestamp). [3]
🌐 Web query:
NUT configure --with-usb flag APC-specific driver options documentation
💡 Result:
Short answer
- ./configure --with-usb builds/installs NUT's USB-based drivers (auto-detects libusb; you can force a version with --with-usb=libusb-0.1 or =libusb-1.0). It requires the libusb development files. [1]
APC-specific driver docs and notes
- usbhid-ups — USB/HID driver (used by some APC models). See the usbhid-ups man page for its driver parameters (port, pollfreq, explore, etc.) and supported-hardware notes. [2]
- apc_modbus — APC Smart‑UPS Modbus protocol driver (supports serial/TCP/USB Modbus; USB/RTU requires a libmodbus build with USB/RTU support). See the apc_modbus man page for options and build/RTU-USB notes. [3]
- Hardware compatibility / model-specific variables and reports are on the NUT device database (APC pages) — useful to check which driver a given APC model prefers. [4]
Useful links (for reading / man pages)
- NUT configure/driver selection documentation (explain --with-usb and --with-drivers). [1]
- usbhid-ups man page (driver options). [2]
- apc_modbus man page (driver options + RTU-USB build caveats). [3]
- NUT APC device database (model-specific variable lists / driver reports). [4]
If you want, tell me the APC model and I’ll point to the exact driver options and sample ups.conf entries for that unit.
The configure flags provide necessary USB driver support, but APC-specific options require runtime configuration.
NUT 2.8.4's lbrb_log_delay_sec and lbrb_log_delay_without_calibrating options exist in the usbhid-ups driver to suppress spurious low-battery notifications on APC BX/BVK models. The --with-usb flag correctly compiles the usbhid-ups driver that supports these features. However, these are runtime configuration options (set in ups.conf), not compile-time features—the Dockerfile enables the driver, but actual feature enablement depends on runtime ups.conf configuration with entries like lbrb_log_delay_sec = 3.
🤖 Prompt for AI Agents
In nut/Dockerfile around lines 21-23, the configure flags correctly build the
usbhid-ups driver but the APC-specific lbrb_log_delay_sec and
lbrb_log_delay_without_calibrating options are runtime ups.conf settings, not
compile-time flags; do not change the --with-usb configure line, instead add a
runtime solution: include a default ups.conf template in the image with APC
sections that set lbrb_log_delay_sec = 3 and lbrb_log_delay_without_calibrating
= <desired>, and/or update the container entrypoint to populate ups.conf from
environment variables or a mounted file so operators can enable those options at
startup.
|
Something like this has been proposed several times before, and has been shot down every time. (eg. #199) Of course, you can always publish your own Add-on that works any way you want. Or, alternatively, I have an Add-on which uses NUT 2.8.4 from Debian Unstable/Sid here: |
|
I expected something like this, and I have no problem with it at all. But nuking such PRs without a trace wastes a lot of people's time, including yours. You could let one of them dangle or get it documented somewhere, at least. |
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
nut/Dockerfile (1)
36-36: Verify the runtime configuration story for APC lbrb options.Per the PR objectives, the goal is to support
lbrb_log_delay_secandlbrb_log_delay_without_calibratingoptions for the APC BX950MI. The--with-usbflag correctly compiles the usbhid-ups driver that supports these options, but these are runtimeups.confconfiguration settings, not compile-time features.Confirm that the rootfs includes:
- A templated or default
ups.confwith APC sections configured with these options.- Or, an init script entry point that allows operators to configure these options via environment variables or a mounted configuration file at startup.
The past review notes this concern, and the AI summary indicates
mkdir -p /var{/run/nut,/state/ups}was added to the init script. Please verify that runtime configuration is also addressed.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
nut/Dockerfile(1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: PaulSD
Repo: hassio-addons/addon-nut PR: 474
File: nut/Dockerfile:11-13
Timestamp: 2025-11-22T20:51:21.979Z
Learning: The hassio-addons/addon-nut repository uses ghcr.io/hassio-addons/debian-base:9.1.0 as its base image, which is based on debian:13.2-slim (trixie/stable). This addon should use trixie-based images going forward.
📚 Learning: 2025-11-22T20:51:21.979Z
Learnt from: PaulSD
Repo: hassio-addons/addon-nut PR: 474
File: nut/Dockerfile:11-13
Timestamp: 2025-11-22T20:51:21.979Z
Learning: The hassio-addons/addon-nut repository uses ghcr.io/hassio-addons/debian-base:9.1.0 as its base image, which is based on debian:13.2-slim (trixie/stable). This addon should use trixie-based images going forward.
Applied to files:
nut/Dockerfile
🔇 Additional comments (5)
nut/Dockerfile (5)
1-5: Base image and multi-stage structure look good.Correct use of
ghcr.io/hassio-addons/debian-base:9.1.0(trixie-based) and clean multi-stage pattern for build separation.
12-13: Build dependencies are comprehensive.The installed packages align well with the configure flags used (--with-usb, --with-modbus, --with-snmp, --with-ssl). The autotools chain and development libraries are all present.
21-23: Clarify necessity of--enable-staticflag.The
--enable-staticflag may increase binary size or create static linking issues. Verify if this is intentional or if it can be removed.Does the NUT 2.8.4 build require
--enable-staticfor this use case, or should it be removed to reduce image size?
28-44: Multi-stage app stage and runtime setup look appropriate.Clean artifact copy from builder, minimal runtime dependencies, and environment variable configuration are all correct. The usbutils version is pinned, which aids reproducibility.
46-73: Build metadata and labels are well-structured.All OCI-compliant labels and Home Assistant-specific metadata are properly configured with build-time arguments. No issues detected.
|
Nice! I'm not against the from upstream releases approach 👍 Previous attempts included using upstream testing/development branches or the use of testing/unstable repositories. I'm currently focussing on the Home Assistant releases and in my private life I'm moving to a new place; so I'll get back to this, but it might take a few days or weeks (at worst). ../Frenck Blogging my personal ramblings at frenck.dev |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
nut/Dockerfile (1)
29-29: Optional: Reconsider--enable-staticflag.Line 29 enables static library builds with
--enable-static. While this may be intentional (e.g., to reduce runtime dependencies), static libraries typically increase the image size without benefits at runtime. Verify whether this flag is necessary for the addon's use case, or consider removing it to reduce final image size.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
nut/Dockerfile(1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: PaulSD
Repo: hassio-addons/addon-nut PR: 474
File: nut/Dockerfile:11-13
Timestamp: 2025-11-22T20:51:21.979Z
Learning: The hassio-addons/addon-nut repository uses ghcr.io/hassio-addons/debian-base:9.1.0 as its base image, which is based on debian:13.2-slim (trixie/stable). This addon should use trixie-based images going forward.
📚 Learning: 2025-11-22T20:51:21.979Z
Learnt from: PaulSD
Repo: hassio-addons/addon-nut PR: 474
File: nut/Dockerfile:11-13
Timestamp: 2025-11-22T20:51:21.979Z
Learning: The hassio-addons/addon-nut repository uses ghcr.io/hassio-addons/debian-base:9.1.0 as its base image, which is based on debian:13.2-slim (trixie/stable). This addon should use trixie-based images going forward.
Applied to files:
nut/Dockerfile
🔇 Additional comments (3)
nut/Dockerfile (3)
1-80: Runtime configuration reminder from prior reviews.Previous review comments noted that APC-specific options (
lbrb_log_delay_sec,lbrb_log_delay_without_calibrating) are runtime configuration settings inups.conf, not compile-time features. While the--with-usbflag (line 30) correctly compiles theusbhid-upsdriver, users must still configureups.confat runtime to enable these APC workarounds. Ensure that the container's entrypoint or documentation guides users to add these settings to theirups.conffor the BX950MI use case mentioned in the PR objectives.
49-49: usbutils version 1:018-2 is available in Debian Trixie and compatible with the base image.The pinned version
usbutils=1:018-2is the standard package in the Debian Trixie (stable) archive and is available across all supported architectures including amd64 and arm64, making it compatible withdebian:13.2-slim.
17-32: ✅ Multi-stage build and checksum verification address prior concerns.The refactored multi-stage build (lines 17–32) correctly:
- Downloads the NUT 2.8.4 tarball and its
.sha256file (lines 23–24)- Verifies integrity via
sha256sum --check(line 25)—this resolves the previous major issue about missing cryptographic verification- Configures with comprehensive flags (
--with-usb,--with-modbus,--with-snmp,--with-ssl) to enable usbhid-ups driver support needed for APC BX950MI- Installs to
/appwithDESTDIR, then copies artifacts to the final image root (line 41)The
.sha256file from NUT's GitHub release uses the standard format (HASH filename) compatible withsha256sum --check, so the verification will function correctly.Build paths and artifact placement are correct.
nut/rootfs/etc/cont-init.d/nut.sh
Outdated
| declare upsmonpwd | ||
| declare username | ||
|
|
||
| mkdir -p /var{/run/nut,/state/ups} |
There was a problem hiding this comment.
You should use /run/nut rather than /var/run/nut (since /var/run is a symlink to /run).
What is /var/state/ups used for?
There was a problem hiding this comment.
That's correct, I just followed whatever was in the script. I've updated the original code as well.
There was a problem hiding this comment.
/var/state/ups is for the active driver state. In my case, the folder contains:
upssched - empty dir
usbhid-ups-bx950mi - fifo
usbhid-ups-bx950mi.pid
There was a problem hiding this comment.
Ok. /var/state/ups doesn't seem to be used for my use case, but fine if it is used for other use cases.
Should you set permissions on it as well?
There was a problem hiding this comment.
Yes, but why was it needed in the first place? You can't chown to root without root permissions, and there is no reason to limit the access permissions since those files are not secret.
nut/config.yaml
Outdated
| @@ -1,5 +1,5 @@ | |||
| --- | |||
| name: Network UPS Tools | |||
| name: Network UPS Tools v2.8.4 | |||
There was a problem hiding this comment.
I don't think this should include the version number.
There was a problem hiding this comment.
It was there for debugging. Sorry, I didn't mean to mess with the name.
nut/Dockerfile
Outdated
| mkdir -p /{app,build} \ | ||
| && cd /build \ | ||
| && NUT_FILENAME="nut-${NUT_VERSION}.tar.gz" \ | ||
| && NUT_RELEASES_URL="https://github.com/networkupstools/nut/releases" \ |
There was a problem hiding this comment.
NUT_RELEASES_URL isn't currently used.
If you want to dynamically retrieve the latest release, you can use something like this:
NUT_RELEASES_URL='https://api.github.com/repos/networkupstools/nut/releases/latest' \
&& NUT_VERSION="$(curl -sS "$NUT_RELEASES_URL" | perl -n -e '/"name":[ \t]*"v([a-zA-Z0-9.-]+)"/ and print $1 and exit')"
However, frenck or others might (or might not, I can't speak for them) prefer that the version number be hard-coded and updated by dependabot. You might want to look into whether this is something dependabot can manage.
There was a problem hiding this comment.
There should be an easy and clear way to switch the release version. Having it in the NUT_VERSION variable is a good enough solution, I think.
There was a problem hiding this comment.
Ok, but in that case we need to ensure dependabot can update it. Can you test/verify that dependabot can deal with this?
There was a problem hiding this comment.
It looks like Dependabot can't handle artifacts from releases/download at all. I can write a CI/CD script for this if needed. GitHub Actions can trigger them on schedule.
| && cd ${NUT_FILENAME%.tar.gz} \ | ||
| && ./configure --prefix=/usr --datadir=/usr/share/nut --sysconfdir=/etc/nut --with-drvpath=/usr/libexec/nut \ | ||
| --enable-static \ | ||
| --with-usb --with-modbus --with-snmp --with-nut-scanner --with-ssl \ |
There was a problem hiding this comment.
Yes, --with-all is the way to go, but I don't like enabling entities I can't test. When everything else is okay, we can give it a try.
nut/Dockerfile
Outdated
| # Copy nut files | ||
| COPY --from=builder /app / | ||
|
|
||
| ENV NUT_QUIET_INIT_UPSNOTIFY=true |
There was a problem hiding this comment.
I think this would make more sense in the startup scripts than in the Dockerfile.
There was a problem hiding this comment.
It looks like a global variable for both upsd and upsmon, and the Dockerfile is a good place for setting such environments. But I have nothing against either approach.
There was a problem hiding this comment.
Keep in mind that variables set in /etc/cont-init.d/nut.sh already apply to both upsd and upsmon.
Regardless ... If you would prefer to set it here, I won't fight it, but maybe just add a comment explaining why it is here, so other future reviewers don't question it like I did. Maybe something like:
# Suppress warnings related to s6 not supporting lifecycle notifications.
# Set here instead of in startup scripts so that it will also be set if users manually run NUT
# commands in the container for troubleshooting.
|
(For reference: I am not the maintainer ... Just another user who has recently reviewed issues and submitted PRs here.) |
|
There hasn't been any activity on this pull request recently. This pull request has been automatically marked as stale because of that and will be closed if no further activity occurs within 7 days. Thank you for your contributions. |
|
Any updates ? #No-stale |
Sorry, I'm not using it anymore. I moved the NUT server into an LXC container on my Proxmox. |
|
There hasn't been any activity on this pull request recently. This pull request has been automatically marked as stale because of that and will be closed if no further activity occurs within 7 days. Thank you for your contributions. |
|
It would be cool to merge this PR |
I agree |
I agree |
Proposed Changes
The current upstream version (2.8.1) is too old and lacks many useful features. And it looks like we won't have anything new there for two years or so.
This build solved my issue with my APC BX950MI. The old driver doesn't support the new
lbrb_log_delay_secandlbrb_log_delay_without_calibratingoptions so it fired LOWBATT and REPLBATT alerts for no reason.Related Issues
#460
#399
Summary by CodeRabbit
New Features
Chores
✏️ Tip: You can customize this high-level summary in your review settings.