How to install WordPress on CentOS, Fedora, or Red Hat with Apache, MariaDB, and PHP-FPM

Installing WordPress from the upstream tarball keeps the site layout, upgrade path, and troubleshooting flow predictable on current dnf-based hosts. That is usually the cleanest fit when the server needs a standard Apache virtual host, a local database, and a filesystem tree that matches WordPress.org instead of a distribution-specific wrapper package.

On current Fedora and RHEL-style systems, httpd serves the site, php-fpm executes PHP over a local Unix socket, and MariaDB stores posts, users, settings, and plugin data. The wp-config.php file connects those layers, while the virtual host and .htaccess support decide whether the installer and later pretty permalinks resolve correctly.

Examples below target current Fedora, CentOS Stream, and Red Hat Enterprise Linux style hosts that use dnf, httpd, and php-fpm. WordPress currently recommends PHP 8.3 or newer, MariaDB 10.6 or newer or MySQL 8.0 or newer, and HTTPS support; current Fedora 42 packaging also uses php-pecl-zip instead of the older php-zip name, and enforcing SELinux still needs a writable label on upload paths before media uploads work cleanly.

Steps to install WordPress on CentOS, Fedora, or Red Hat with Apache, MariaDB, and PHP-FPM:

  1. Install Apache, MariaDB, PHP-FPM, and the common WordPress PHP extensions.
    $ sudo dnf install -y httpd mariadb-server php php-fpm php-mysqlnd php-xml php-gd php-intl php-mbstring php-pecl-zip curl rsync tar

    Current Fedora-family packaging uses php-pecl-zip for ZIP support, so older guides that still list php-zip are stale.

  2. Enable and start the Apache, MariaDB, and PHP-FPM services.
    $ sudo systemctl enable --now httpd mariadb php-fpm
    $ systemctl is-active httpd mariadb php-fpm
    active
    active
    active

    Current RHEL 9-style systems run Apache PHP requests through php-fpm rather than mod_php, so a stopped php-fpm service breaks every .php request even when httpd is active.

  3. Open the local MariaDB shell and create a dedicated database and database user for WordPress.
    $ sudo mariadb
    MariaDB [(none)]> CREATE DATABASE wordpress CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
    MariaDB [(none)]> CREATE USER 'wordpress'@'localhost' IDENTIFIED BY 'strong_password_here';
    MariaDB [(none)]> GRANT ALL PRIVILEGES ON wordpress.* TO 'wordpress'@'localhost';
    MariaDB [(none)]> FLUSH PRIVILEGES;
    MariaDB [(none)]> EXIT;

    sudo mariadb is the safest default on current package installs because the local root account commonly authenticates through the Unix socket instead of a preset password.

    Replace strong_password_here with a unique password that is not reused for any other account on the server.

  4. Create a dedicated document root for the WordPress virtual host.
    $ sudo mkdir -p /var/www/example.com/public_html
  5. Download the current WordPress tarball to a temporary directory and extract it.
    $ cd /tmp
    $ curl -LO https://wordpress.org/latest.tar.gz
    $ tar -xzf latest.tar.gz
  6. Copy the extracted WordPress files into the site document root.
    $ sudo rsync -a /tmp/wordpress/ /var/www/example.com/public_html/

    The trailing slashes keep the contents of the extracted wordpress directory in the document root instead of nesting another wordpress directory under it.

  7. Create wp-config.php from the sample file and add the database connection values.
    $ sudo cp /var/www/example.com/public_html/wp-config-sample.php /var/www/example.com/public_html/wp-config.php
    $ sudo vi /var/www/example.com/public_html/wp-config.php
    define( 'DB_NAME', 'wordpress' );
    define( 'DB_USER', 'wordpress' );
    define( 'DB_PASSWORD', 'strong_password_here' );
    define( 'DB_HOST', 'localhost' );

    Keep DB_HOST as localhost when MariaDB runs on the same host.

  8. Replace the placeholder authentication keys and salts in wp-config.php with fresh values from the official WordPress API.
    $ curl -s https://api.wordpress.org/secret-key/1.1/salt/

    Paste the returned define(… ) lines over the default salt block before saving the configuration file.

  9. Set ownership and permissions so Apache and PHP-FPM can read the site tree safely.
    $ sudo chown -R apache:apache /var/www/example.com/public_html
    $ sudo find /var/www/example.com/public_html -type d -exec chmod 755 {} \\;
    $ sudo find /var/www/example.com/public_html -type f -exec chmod 644 {} \\;
    $ sudo chmod 640 /var/www/example.com/public_html/wp-config.php
  10. Create the upload directory and persist an SELinux write label for it when the host runs in enforcing mode.
    $ sudo mkdir -p /var/www/example.com/public_html/wp-content/uploads
    $ getenforce
    Enforcing
    
    $ sudo dnf install -y policycoreutils-python-utils
    $ sudo semanage fcontext -a -t httpd_sys_rw_content_t '/var/www/example.com/public_html/wp-content/uploads(/.*)?'
    $ sudo restorecon -Rv /var/www/example.com/public_html/wp-content/uploads

    Skip the labeling commands when getenforce returns Permissive or Disabled.

    Without a writable SELinux context, the installer can succeed while media uploads later fail with unexplained permission errors.

  11. Create an Apache virtual host for the site.
    $ sudo vi /etc/httpd/conf.d/example.com.conf
    <VirtualHost *:80>
        ServerName example.com
        ServerAlias www.example.com
        DocumentRoot /var/www/example.com/public_html
    
        <Directory /var/www/example.com/public_html>
            AllowOverride All
            Require all granted
            DirectoryIndex index.php
        </Directory>
    
        ErrorLog /var/log/httpd/example.com-error.log
        CustomLog /var/log/httpd/example.com-access.log combined
    </VirtualHost>

    WordPress writes permalink rules to .htaccess, so AllowOverride All must stay enabled for the document root.

    Replace the example hostnames with the real DNS names for the site before reloading Apache.

  12. Test the Apache configuration and reload the service after the syntax check passes.
    $ sudo httpd -t
    Syntax OK
    $ sudo systemctl reload httpd
  13. Verify that the installer endpoint responds before completing the browser-based setup.
    $ curl -I http://www.example.com/wp-admin/install.php
    HTTP/1.1 200 OK
    Content-Type: text/html; charset=utf-8

    If this request fails, confirm the DNS record or local host mapping points to the server, the virtual host name matches the URL, and the php-fpm service is still active.

  14. Open http://www.example.com/wp-admin/install.php// in a browser and finish the initial WordPress setup by creating the site title, administrator account, and password.

    After the installer finishes, continue with HTTPS and XML-RPC hardening from the related pages.