Skip to content
VDS · Operating systems

AlmaLinux and CentOS Stream: dnf instead of apt

How to adapt Debian instructions for the RHEL family: command and package equivalents, firewalld instead of ufw, SELinux, and the EPEL repository.

Updated August 23, 2026

AlmaLinux 9 and 10 and CentOS Stream 9 work differently from Debian and Ubuntu. Let's go over the things people stumble over most often.

Command equivalents

Debian / UbuntuAlmaLinux / CentOS Stream
apt update && apt upgradednf upgrade
apt install packagednf install package
apt remove packagednf remove package
apt search stringdnf search string
apt list --installeddnf list installed
ufwfirewall-cmd
group sudogroup wheel
/etc/apt/sources.list/etc/yum.repos.d/

Package names differ too: apache2 is httpd here, nginx is the same, mysql-server is mariadb-server, python3-pip is python3-pip, but dnsutils is called bind-utils.

First steps

dnf upgrade -y
dnf install -y curl nano git htop tar policycoreutils-python-utils
timedatectl set-timezone Europe/Moscow
hostnamectl set-hostname my-vds

A user with administrator rights:

adduser artem
passwd artem
usermod -aG wheel artem

The EPEL repository

Many familiar packages aren't in the base repositories — they're in EPEL:

dnf install -y epel-release
dnf upgrade -y
dnf install -y btop fail2ban

Firewall

Instead of ufw, this uses firewalld:

systemctl enable --now firewalld
firewall-cmd --permanent --add-service=ssh
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --permanent --add-port=8080/tcp
firewall-cmd --reload
firewall-cmd --list-all

Without --permanent, the rule will disappear after a reboot, and without --reload, it won't apply right now. You need both parts.

SELinux

The main source of mysterious failures: file permissions are correct, the service is running, but there's no access. To check the mode:

getenforce

Common cases and solutions:

setsebool -P httpd_can_network_connect 1
semanage port -a -t http_port_t -p tcp 8080
restorecon -Rv /var/www

The first allows the web server to make outbound connections (needed when proxying to an application), the second allows listening on a non-standard port, and the third fixes file labels after copying from someone else's directory.

You can see what's actually happening here:

ausearch -m avc -ts recent

You don't need to disable SELinux entirely: almost always, one of the three techniques above is enough.

What else is different

  • The Apache web server is called httpd, and its configs live in /etc/httpd/, not /etc/apache2/.
  • nginx doesn't have sites-available and sites-enabled directories — configs go in /etc/nginx/conf.d/*.conf.
  • The web server user is nginx or apache, not www-data. This matters with chown.

Guest agent

dnf install -y qemu-guest-agent
systemctl enable --now qemu-guest-agent

If you're not sure whether to go with this family at all, see which OS to choose. You can change the OS with a reinstall, but with complete data loss.