AlmaLinux DNF Module Streams: Pinning Application Versions Across a Fleet
How AlmaLinux module streams pin application versions per host, with a worked Node.js example, the reset-versus-disable distinction, and the drift checks that catch mistakes.
23 Apr 2026, 08:39 UTC

If you need the same application version on every AlmaLinux host in a fleet, the DNF module stream is the mechanism that pins it — but only if you treat it as per-host state that your configuration management enforces, not as a one-off command. The short version: run dnf module enable <name>:<stream>, install the package under its plain name, and record that enable step in your automation. To change versions later, dnf module reset first; dnf module disable is not the same operation.
What a module stream actually locks
AlmaLinux's repositories are split into a base set of packages and a smaller set of modules. A module is a named container for one or more streams — parallel versions of the same software, such as several PHP or Node.js release lines. Each stream bundles the application package plus the libraries and runtime it was built against, so enabling a stream gives you a coherent set rather than a single RPM.
The part that matters for engineering decisions: the stream selection is stored on the host, not in the repository. Two identical AlmaLinux machines can have different streams enabled, and dnf update will keep each one inside its own stream. That is what makes modules useful for version pinning — and what makes them risky if only some of your hosts were configured.
Worked example: pinning Node.js on AlmaLinux 9
Run these as root or with sudo on the target host. The stream numbers below illustrate the pattern; confirm the exact list on your own system, because AlmaLinux adds and retires streams across minor releases.
- See what is available and what is already active:
The output marks the default stream withdnf module list nodejs[d], an enabled stream with[e], and an installed one with[i]. If a stream shows[e]that you did not set, something else — an image build, a kickstart, or a previous admin — already made the decision for you. - Enable the stream you want:
Enabling only records the choice and makes that stream's packages the ones DNF will resolve. It does not install anything yet.dnf module enable nodejs:20 - Install the package by its plain name:
DNF now resolvesdnf install nodejsnodejsfrom the enabled stream, pulling the matching runtime and any optional dependencies the stream declares. - Verify the result:
node -v dnf module list --installed rpm -q nodejsnode -vshows the runtime version,dnf module list --installedshows which module and stream the host is committed to, andrpm -qconfirms the exact package build. Check all three — a matching major version with an unexpected package build usually means a package was installed from outside the stream.
In configuration management, the enable step is the thing to encode. A task that runs dnf module enable before installing the package is idempotent: on a host already on that stream it reports no change, and on a drifted host it corrects the drift.
Switching streams: reset, disable, or remove
These three commands are commonly confused, and picking the wrong one is the most frequent cause of a half-migrated host.
| Command | Effect | Use when |
|---|---|---|
dnf module reset <name> | Clears the enabled or disabled state so the module falls back to its default stream | You want to move to a different stream or back to the base package |
dnf module disable <name> | Marks the module unavailable so its packages are not offered | You want to block the software entirely, for example to prevent an accidental install |
dnf module remove <name> | Removes the packages installed from that module | You are decommissioning the application |
A typical version move looks like this:
dnf module reset nodejs
dnf module enable nodejs:22
dnf distro-sync
node -v
dnf distro-sync brings installed packages into line with the newly enabled stream, which is what actually replaces the runtime. Treat this as a state-changing operation: it can upgrade or downgrade packages, and any application code that depended on the old runtime needs checking before you roll it out beyond a canary host.
Common mistakes
- Assuming
dnf updatewill cross streams. It will not. A host on an older stream stays there indefinitely, so a fleet can look fully patched while running several different application versions. - Mixing streams inside a cluster. If half your web nodes run one PHP stream and half another, you get inconsistent runtime behaviour that is hard to reproduce. Treat the stream as part of the host's role definition.
- Installing a package explicitly and expecting module rules to hold. An explicit
dnf install <package>-<version>or a package from a third-party repository can override the module's default resolution. If a host's version does not match its stream, look for a manually installed RPM first. - Enabling a stream that conflicts with what is already installed. If base-repository packages are already present, enabling a module stream can produce dependency conflicts. Enable before installing, not after.
- Forgetting that streams are fixed per release. Enabling a stream name that does not exist in your AlmaLinux minor release fails outright; it will not silently fall back.
Limits and how to check your work
Modules are a version-selection tool, not a patching tool. Within a stream you still receive normal security updates, but the stream itself will not move to a new major version on its own — that is a deliberate migration you schedule. AlmaLinux also ships fewer modules than it once did, because several applications moved into the base repositories; if dnf module list <name> returns nothing, the software is simply a regular package on that release, and you pin it with repository versionlock instead.
To confirm a host is where you think it is, check three things: dnf module list --installed for the committed stream, the application's own version output, and rpm -q for the package build. If those disagree, an explicit package install has overridden the module, and you should reconcile it before trusting the host in a fleet-wide rollout.
Note for review: the specific stream numbers available for a given application vary by AlmaLinux minor release. Confirm the list with dnf module list on a representative host before encoding stream names in automation.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.