Say Goodbye to Library Conflict Worries When Upgrading Servers
If you’ve ever operated CentOS 7, you’re likely familiar with the struggle of upgrading PHP from 5.4 to 7.4. You usually had to hunt for third-party repos like REMI or EPEL. Then came the moments of praying they wouldn’t break existing system packages. I’ve spent the last 6 months migrating over 50 servers from CentOS 7 to CentOS Stream 9, and the new software management approach has truly been a game-changer.
Traditional Linux distributions are often very conservative. They lock down runtime versions (Node.js, Python, PHP) to ensure the system never crashes. However, this stability can sometimes hold back developers who need the latest technology. CentOS Stream 9 addresses this with AppStream and DNF Modules. After half a year of running this in production for e-commerce projects, I find this the most “bang-for-your-buck” feature for SysAdmins.
Understanding BaseOS, AppStream, and Modules
To avoid confusion when typing commands, you need to clearly distinguish between the three main components of this new architecture:
- BaseOS: The minimal core packages required for the virtual machine to boot and run stably. These change very rarely.
- AppStream: A repository for applications, development tools, and databases. The biggest plus is that it allows multiple versions of the same software to coexist.
- DNF Modules: A way to package related applications into a group. A Module has multiple Streams (versions like Node.js 18, 20) and Profiles (installation types like minimal or full-stack for developers).
Instead of installing individual .rpm files, we manage them with a new mindset. You just need to select the desired Module, specify the version (Stream), and choose the appropriate configuration (Profile) for your production environment.
Hands-on: Installing and Switching Runtimes in a Flash
Below is the workflow I typically use to set up servers for clients. All operations begin with a very intuitive module management command.
1. Check Supported Versions
Don’t rush to install immediately. Check what’s available on the system with the command:
dnf module list nodejs
The screen will display a list of versions like 18 and 20. The [d] symbol means the default version, while [e] is the version you are currently using. This helps you avoid installing an old version for a new project.
2. Installing Node.js 20 for Modern Projects
If the project requires Node.js 20 but the default version is lower, you don’t need to spend time downloading and compiling source code. Just run these two commands:
# Enable version 20 stream
sudo dnf module enable nodejs:20
# Install common profile (sufficient for most applications)
sudo dnf module install nodejs:20
It only takes about 30 seconds for the system to automatically resolve complex dependencies. Check again with node -v, and you’ll see the desired result.
3. The Cleanest Way to Switch Between PHP 8.1 and 8.2
This is a feature I’m extremely fond of. When migrating applications, I usually test on PHP 8.1 before upgrading to 8.2. DNF Modules make this process incredibly neat.
To upgrade, perform a Reset process to avoid system clutter:
# Reset module to clear old version configurations
sudo dnf module reset php
# Enable and install the new version
sudo dnf module enable php:8.2
sudo dnf module install php:8.2/common
Hard-earned lesson: Never skip the dnf module reset command. If you install directly over the old version, legacy dependencies can cause “ghost” bugs that are very difficult to debug later.
4. Optimizing Storage with Profiles
Each module is typically divided into multiple Profiles. For Python, if you only need to run code on the server, choose the minimal version. If you need to build libraries, choose the development version. View the profile list with the command:
dnf module info --profiles python39
The installation syntax is module:stream/profile. For example: sudo dnf module install python39/build.
Small Tips for More Effective AppStream Management
Through actual operations, I’ve derived three rules to keep the server clean:
- Prioritize official sources: Always check
dnf module listbefore looking for external repos. Packages from AppStream are thoroughly tested for security by the RHEL team. - Be careful with shortcut installation commands: If you use
dnf install [package_name], the system will grab the default version. Always usemodule enableto precisely control the version you want. - Check for leftover configuration files: After changing the PHP version, check the
/etc/php.d/directory. Sometimes old extensions leave behind config files that conflict with the new version.
Conclusion
Mastering AppStream and DNF Modules makes CentOS Stream 9 administration much more professional. It removes the barrier between a stable Enterprise OS and the constantly changing needs of developers. Instead of fumbling with dozens of repos of unknown origin, you can now upgrade runtimes with just a few simple commands. If you’re starting with RHEL 9 or AlmaLinux, get into the habit of using Modules today to keep your servers stable and easy to maintain.

