in , , ,

Installing Drupal 9 On CentOS Stream

Installing Drupal 9 On Centos Stream VPS

We will try to install Drupal 9 on a CentOS Stream 9 VPS/Server, and we will walk through all necessary steps to build and deploy our Drupal 9 application.

Web Technology To Use

As described in the next figure, we will use:

Nginx Apache Drupal MariaDB

  1. Nginx as a reverse proxy (Port 443, 80)
  2. Apache as a web-server (Port 81)
  3. Drupal 9 CMS Our PHP Web Application
  4. MariaDB Database Server

We will consider an example domain name:, with server IP-Address:

But while you apply this tutorial for your project, do not forget to replace your domain name and IP-Address values with yours.

Configure The CentOS Stream Server

We will:

  1. Update our server.
  2. Install required packages ( i.e. MariaDB, Nginx, Apache, and PHP )
  3. Firewalls for all ports except HTTP(S) and SSH.
  4. Install fail2bab to harden SSH access.
  5. Installing Drupal

Step1: Update CentOS Stream Server

Update Our System

To update our Centos stream we just need to run the command.

# dnf update

Disable SELinux

We need to disable SELinux, by editing the file /etc/selinux/config and setting SELINUX=disabled

# vim /etc/selinux/config
# To revert back to SELinux enabled:
# grubby --update-kernel ALL --remove-args selinux
# SELINUXTYPE= can take one of these three values:
# targeted - Targeted processes are protected,
# minimum - Modification of targeted policy. Only selected processes are protected.
# mls - Multi Level Security protection.

Then restart your device…

Step2: Install  And Configure Nginx As A Reverse Proxy

Install And Configure Nginx

To Install And Enable Nginx, simply run the command

# dnf install nginx
# systemctl enable nginx

Configure Nginx

And to configure Nginx As A Reverse Proxy for your web server, create a new config file for your website domain in the Nginx configuration directory /etc/nginx/conf.d with the name of your domain as .

Edit your website domain config file /etc/nginx/conf.d/ and append the following settings into it.

PS: don't forget to replace your server name with your domain name, also listen IP-Address to your server's public IP-Address. (colored with green bold).

# Define Your Server To Listen To Your Plubic IP ADDRESS && HTTP Port 80
# Then Redirect To HTTPS Port 443
server {
  access_log off;
  return 301$request_uri;
# If you want to redirect www to non-www domain, uncomment the next server block.
#server {
#  listen;
#  server_name;
#  access_log off;
#  return 301$request_uri;
server {
  listen ssl default;

  # We capture the logs
  access_log /var/log/nginx/;

  # Insert a full path of your Self-Signed certificate Or a Validation Signed one.
  # In the next step we will learn how to create our Self-Signed certificate or you can read this tutorial 
  # To make your Self-Signd Certificate in 3 Steps, and read this for Validation Signed one.
  ssl_certificate      /opt/cert/;
  ssl_certificate_key  /opt/cert/;
  ssl_dhparam          /opt/cert/dhparam.pem;
  # Restrict to secure protocols, depending on whether you have visitors
  # from older browsers
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

  # Restrict ciphers to known secure ones

  ssl_prefer_server_ciphers on;
  ssl_ecdh_curve secp384r1;
  # Disable Certificate Stapling and Verification if its a self-signed one.
  ssl_stapling off;
  ssl_stapling_verify off;

  # Caching SSL.
  ssl_session_cache shared:SSL:20m;
  ssl_session_timeout 180m;
  ssl_session_tickets on;
  # Adjustment Headers
  # Uncomment the next header if  you are using Validation Certification To Force using it and setting up ssl cache age. 
  #add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
  add_header X-Frame-Options SAMEORIGIN;
  add_header X-Content-Type-Options nosniff;
  add_header Access-Control-Allow-Origin *;
  add_header Access-Control-Allow-Credentials true;

  #Enable and configure GZIP
  gzip on;
  gzip_static on;
  gzip_comp_level    9;
  gzip_min_length    256;
  gzip_proxied       any;
  gzip_vary          on;
  gzip_buffers           16 8k;
  gzip_http_version  1.1;
  proxy_http_version 1.1;
    # text/html is always compressed by gzip module

  # To allow POST on static pages
  error_page 405 =200 $uri$is_args$args;
  location / {
    # Pass Every request to Apache at the Port 81
    proxy_pass               ;
    # Adjustement reverse proxy headers.
    proxy_read_timeout                 640;
    proxy_connect_timeout              640;
    proxy_redirect                     off;
    proxy_set_header Host              $host;
    proxy_set_header X-Real-IP         $remote_addr;
    proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header X-Forwarded-Port  443;
    proxy_buffers                      16 32k;
    proxy_buffer_size                  64k;
    proxy_request_buffering off;
    proxy_buffering off;
# Enable Caching Static files...
  location ~*  \.(jpg|jpeg|png|gif|ico|css|js|pdf|ttf|woff|eot|bz2|gz|woff2|svg|bmp)$ {

                proxy_pass               ;
                proxy_read_timeout                 640;
                proxy_connect_timeout              640;
                proxy_redirect                     off;

                proxy_set_header Host              $host;
                proxy_set_header X-Real-IP         $remote_addr;
                proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto https;
                proxy_set_header X-Forwarded-Port  443;
                proxy_buffers                      32 64k;
                proxy_buffer_size                  128k;
                proxy_request_buffering off;
                proxy_buffering off;
                access_log off;
                log_not_found on;
                # Extend Browsers Caching Time for static file 
                expires 60d;


Of course, we can ignore using SSL, and using HTTP Port 80 Only, so you will use the configuration as is shown in the github config file link, its the same example configuration, and so Ignore the next step (Step3).

Step3: Create Your SSL Self-Signed Or Validation Certificate

To create your self-signed SSL, go to the SSL store directory ie /opt/cert and start running the command

# mkdir /opt/cert
# cd /opt/cert
# openssl req -newkey rsa:2048 -new -nodes -x509 -days 13650 -keyout -out

Generating a RSA private key
writing new private key to ''
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:Wyoming
Locality Name (eg, city) []:Sheridan
Organization Name (eg, company) [Internet Widgits Pty Ltd]:CompanyName
Organizational Unit Name (eg, section) []:IT
Common Name (e.g. server FQDN or YOUR name) []
Email Address []

And for hardening this SSL Certificate we will generate Diffie-Hellman group dhparam.pem file

# openssl dhparam -out dhparam.pem 4096

PS: Creating dhparam.pem file may require several minutes to get finished.

Now we get the listed 3 certificate files in the certificate directory /opt/cert

  • dhparam.pem

Then make sure to enter the correct path of the certificate files, into the Nginx config file that we created in the previous step /etc/nginx/sites-available/

To have a validate signed certificate for your domain, you can follow the How to create your validated signed SSL by a trusted CA For Linux guide, and you can get your free one too from Let's Encrypt

Step4: Install Apache Web Server And Configure Our Virtual Host

Install And Configure Apache

To install the Apache web server, and then enable it for systemd, we will need to run the commands

# dnf install httpd httpd-tools
# systemctl enable httpd

After installing Apache, go to the main Apache configuration file at /etc/httpd/conf/httpd.conf to set it to listen to port 81 at localhost IP-Address.

So we edit the configuration file using vim editor and look for the Listen 80 line to change it to Listen as the following

# vim /etc/httpd/conf/httpd.conf

# Change this to Listen on a specific IP address, but note that if
# httpd.service is enabled to run at boot time, the address may not be
# available when the service starts.  See the httpd.service(8) man
# page for more information.


Create Our VirtualHost

To create our Virtual Host, we will go to the Apache config directory /etc/httpd/conf.d/, create a file, then add the below virtual host settings then save the file.

<VirtualHost *:81>
      DocumentRoot /home/drupalize/public_html
      ServerAlias *
<Directory "/home/drupalize/public_html">
    Options Indexes FollowSymLinks MultiViews
    AllowOverride All
    Require all granted

Step5: Install MariaDB The Database Server

Install MariaDB

To install, enable, and run the MariaDB we will run the commands

# dnf install mariadb mariadb-server
# systemctl enable mariadb
# systemctl start mariadb

MariaDB Basic Secure

After installation is complete, we need to apply the basic security configuration step.

We need to run the command mysql_secure_installation and Interact with outputs as the following:

  1. Enter current password for root (enter for none): [Press Enter With Empty Value]
  2. Switch to unix_socket authentication [Y/n] [Answer n]
  3. Change the root password? [Y/n] [Answer Y & Enter your database root password]
  4. Remove anonymous users? [Y/n] [Answer Y]
  5. Disallow root login remotely? [Y/n] [Answer Y]
  6. Remove test database and access to it? [Y/n] [Answer Y]
  7. Reload privilege tables now? [Y/n] [Answer Y]
# mysql_secure_installation


In order to log into MariaDB to secure it, we'll need the current
password for the root user. If you've just installed MariaDB, and
haven't set the root password yet, you should just press enter here.

Enter current password for root (enter for none):
OK, successfully used password, moving on...

Setting the root password or using the unix_socket ensures that nobody
can log into the MariaDB root user without the proper authorisation.

You already have your root account protected, so you can safely answer 'n'.

Switch to unix_socket authentication [Y/n] n
 ... skipping.

You already have your root account protected, so you can safely answer 'n'.

Change the root password? [Y/n] y
New password:
Re-enter new password:
Password updated successfully!
Reloading privilege tables..
 ... Success!

By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n] y
 ... Success!

Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n] y
 ... Success!

By default, MariaDB comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.

Remove test database and access to it? [Y/n] y
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n] y
 ... Success!

Cleaning up...

All done!  If you've completed all of the above steps, your MariaDB
installation should now be secure.

Thanks for using MariaDB!

Create A Database User for our Drupal Website

Log in to the database server as root (we set a database root password in the previous step), as below, and replace PassWord with yours.

We will create a new database named drupal, and a new database user named drupal_db_user with drupal_db_password.

You can replace the values with yours, and then flush MariaDB privileges as the following.

# mysql -uroot -pPassWord
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 11
Server version: 10.5.13-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> create database drupal;
Query OK, 1 row affected (0.001 sec)

MariaDB [(none)]> GRANT ALL PRIVILEGES ON drupal.* TO 'drupal_db_user'@'localhost' IDENTIFIED BY 'drupal_db_password';
Query OK, 0 rows affected (0.002 sec)

Query OK, 0 rows affected (0.002 sec)

MariaDB [(none)]> exit;

Step6: Install PHP

Install PHP and Drupal required extensions using the command

# dnf install php php-mysqlnd php-json php-gd php-xml php-openssl php-curl php-mbstring php-zip

Step7: Add New User To The System

We will need to add a new user to the system which usually has a username as the domain name, then we will set a password for the domain user.

After that, we will create the public web directory public_html, which must be exactly as we add in the above apache virtual host configuration.

Then append the domain user to the Apache System User Group

# adduser drupalize
# passwd drupalize
Changing password for user drupalize.
New password:[Enter your password here]
Retype new password:[Re-Eneter your password]
passwd: all authentication tokens updated successfully.

# chmod 755 /home/drupalize/
# cd /home/drupalize
# mkdir public_html
# usermod -a -G apache domain

Step8: Firewall And Fail2ban

Firewall Setting

Firewall all ports and keep the HTTP 80, HTTPS 443, and SSH 22 Open, by running

# firewall-cmd --add-service=http --permanent
# firewall-cmd --add-service=https --permanent
# firewall-cmd --add-service=ssh --permanent
# firewall-cmd --reload

Install And Run Fail2Ban

To Secure SSH from Brute Force attacks, we will install and run Fail2ban using EPEL repository as the following

# dnf install epel-release
# dnf update
# dnf install fail2ban
# systemctl enable fail2ban
# systemctl start fail2ban

Downloading And Installing Drupal 9

Step9: Download Drupal

Install Composer and tar packages using the command

# dnf install composer tar

Go to the public_html web directory /home/domain/public_html, and run the download and extract command to get the latest Drupal package as the following.

# curl -sSL | tar -xz --strip-components=1

Step10: Start The Installation Process

Now we can start our Web services as the following

# systemctl start nginx
# systemctl start httpd

Set Drupal Files and Permissions

Go to the /home/drupalize domain directory, and apply the following permission to the public_html and contents

# cd /home/drupalize
# mkdir public_html/sites/default/files
# cp public_html/sites/default/default.settings.php public_html/sites/default/settings.php
# chown -R drupalize.apache public_html
# chmod -R 2750 public_html
# chmod -R 2770 public_html/sites/default/files

The following permission is temporary until you complete the installation process, and you must set the settings.php to 2640 after finishing.

# chmod -R 2770 public_html/sites/default/settings.php

Drupal Installation Wizard

We will use the classic Web GUI installation wizard method, by firing the domain URL into the web browser.

For the first run, and if you are using a self-signed certificate, you will get this SSL validation error message, and will need to choose to proceed to domain unsafe

drupal 9 installation on centos stream

Start Your Installation Wizard Steps, and Choose your language, then press Save and Continue

drupal 9 start installation

The Next Step will be to choose your installation profile, as we will select the standard profile

drupal 9 installation select profile

The next step will be a verification process, then set up the Drupal database using the database information which we created in the step5

  • Database name: drupal
  • Database username: drupal_db_user
  • Database password: drupal_db_password

install drupal 9 database setup step

After entering the database information, the install site progress will start, and you will need to make the final step, with set up the site configuration

drupal 9 progress installation

drupal 9 site configuration installation

Entering your site configuration and finish the installation wizard.

Then return the settings.php file to set its permission to 2640, to keep drupal safe.

# chmod 2640 public_html/sites/default/settings.php

Now all done, and the installation mission is completed.

drupal 9 installation-finishing

What do you think?

Leave a Reply

Your email address will not be published. Required fields are marked *

      Installing python and virtualenv on centos stream

      Installing Python and Virtualenv On CentOS Stream 9


      Install Shadowsocks Python Server With Enable BBR On Ubuntu 20.04 LTS