Why CentOS Stream 9 and Nginx?
When I first started working with servers, I often used Apache because it was convenient—you just dropped files in and they would run. However, when managing sites with thousands of concurrent visitors, I noticed Apache consumes RAM very quickly. A server with 2GB of RAM can crash under Apache’s load, while Nginx only uses about 150-200MB to handle the same amount of traffic.
After CentOS 8 reached its End of Life (EOL), I considered migrating to AlmaLinux or Rocky Linux. Ultimately, I chose CentOS Stream 9 for projects that need RHEL-based stability while still offering newer software packages. In this article, I will guide you through setting up a professional WordPress site. Notably, I won’t tell you to disable SELinux like many other guides online. We will do it the right way: by enabling the firewall and configuring strict SELinux policies.
Core Concepts: What is the LEMP Stack?
To run WordPress smoothly, we need the LEMP framework:
- Linux: The operating system (CentOS Stream 9).
- Engine-X (Nginx): The web server that handles connections, much lighter and faster than Apache.
- MariaDB: The database management system (a highly stable open-source fork of MySQL).
- PHP: The primary programming language for WordPress.
Step 1: Update the System and Configure Firewalld
The first thing to do after SSHing into the server is to update everything. Never skip this step, as important security patches are often included here.
sudo dnf update -y
Next, open the ports in Firewalld. By default, CentOS locks down ports to protect the server. If you don’t open ports 80 and 443, you won’t be able to access the website from a browser.
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
Step 2: Install Nginx and MariaDB
Installing Nginx is quick and easy with the dnf command:
sudo dnf install nginx -y
sudo systemctl enable --now nginx
For MariaDB, after installation, you must run the security script. In the past, I was careless and skipped this step, which resulted in the database being constantly scanned by bots for passwords.
sudo dnf install mariadb-server mariadb -y
sudo systemctl enable --now mariadb
sudo mariadb-secure-installation
The system will ask for the DB root password. Since it’s a fresh installation, there isn’t one, so just press Enter. Then, choose Y to set a new, strong password. For the subsequent questions, also choose Y to remove anonymous users and test databases.
Step 3: Install PHP 8.2
WordPress currently performs best on PHP 8.1 or 8.2. On CentOS Stream 9, we install the necessary modules for image processing and data compression:
sudo dnf install php-fpm php-mysqli php-json php-gd php-intl php-pecl-apcu php-opcache php-mbstring php-xml php-zip -y
sudo systemctl enable --now php-fpm
Important note: Nginx and PHP-FPM need to “speak” the same language. By default, PHP-FPM runs under the apache user; you need to change it to nginx to avoid permission errors.
Open the file /etc/php-fpm.d/www.conf and modify the following two lines:
user = nginx
group = nginx
Step 4: Create a Database for WordPress
Now it’s time to create a “home” for your data. Log in to MariaDB:
sudo mariadb -u root -p
Run the following commands (remember to replace your_password with a hard-to-guess string):
CREATE DATABASE wordpress_db;
CREATE USER 'wp_user'@'localhost' IDENTIFIED BY 'your_password';
GRANT ALL PRIVILEGES ON wordpress_db.* TO 'wp_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;
Step 5: Configure Nginx Virtual Host
Download the latest WordPress version to the web directory:
cd /var/www
sudo curl -O https://wordpress.org/latest.tar.gz
sudo tar -xf latest.tar.gz
sudo chown -R nginx:nginx /var/www/wordpress
sudo chmod -R 755 /var/www/wordpress
Next, create an Nginx configuration file at /etc/nginx/conf.d/wordpress.conf:
server {
listen 80;
server_name yourdomain.com; # Replace with your actual domain
root /var/www/wordpress;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php-fpm/www.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
Test the configuration and restart: sudo nginx -t && sudo systemctl restart nginx.
Step 6: Handling SELinux – The Key to Security
If you access the site and see a “403 Forbidden” error, it’s because SELinux is blocking Nginx. Instead of disabling it (which is very dangerous), run the following commands to grant proper file write permissions:
# Install management tools if not already present
sudo dnf install policycoreutils-python-utils -y
# Allow Nginx to manage web files
sudo semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/wordpress(/.*)?"
sudo restorecon -Rv /var/www/wordpress
# Allow network connections (to install plugins, send emails)
sudo setsebool -P httpd_can_network_connect 1
My experience: If you don’t run restorecon, the changes won’t take effect. You’ll spend all day struggling with 777 permissions and the site still won’t work.
Step 7: Enable Free SSL with Let’s Encrypt
A website without HTTPS will be flagged as “Not Secure” by Google and will suffer in SEO rankings. We use Certbot to obtain a free SSL certificate in just 30 seconds.
sudo dnf install certbot python3-certbot-nginx -y
sudo certbot --nginx -d yourdomain.com
Certbot will automatically reconfigure Nginx and set up automatic certificate renewal for you. Very convenient!
Conclusion
Setting up WordPress on CentOS Stream 9 is not difficult if you understand the process. The key is the smooth coordination between Firewalld and SELinux to create a true fortress for your website.
If any step reports an error during installation, take a close look at the logs at /var/log/nginx/error.log. All the clues are there. Good luck with your deployment!

