How to Install Drupal with Nginx and Let’s Encrypt SSL on Debian 11

0

Drupal is an open-source content management system that allows you to build, manage, and maintain your website’s content with no coding knowledge necessary.

There are many different content management solutions to choose from, but not all are right for every project. If you want to build or rebuild your website with something flexible and powerful, look no further than Drupal.

If you do not have any web hosting yet to develop a Drupal website, we recommend installing it on your local Debian machine or VPS.

Here, we will install Drupal with Nginx and Let’s Encrypt SSL on Debian 11.

Prerequisites

Install LEMP Stack

Follow the below links to install the LEMP stack on your Debian system for Drupal installation.

Install EMP (Nginx, MariaDB, and PHP) on Debian 11

Install PHP Extensions for Drupal

Use the apt command to install PHP extensions for Drupal installation.

sudo apt update

sudo apt install -y php-mysql php-gd php-dom php-curl php-imagick php-zip php-xml php-mbstring php-json php-pdo php-cli php-apcu

sudo apt install --no-install-recommends -y php-uploadprogress

Setup Nginx Virtual Host for Drupal

We will start with creating a virtual host for a Drupal installation. You can find all Nginx’s virtual host configuration files under /etc/nginx/conf.d directory.

Typically, a virtual host file contains a domain name, port number, document root, log location, fast CGI, etc.

I am assuming the following,

Domain name: itzgeek.net, www.itzgeek.net
Port No: 80
Document root: /usr/share/nginx/www.itzgeek.net/html
Logs: /usr/share/nginx/www.itzgeek.net/logs

First, create a virtual host configuration file.

sudo nano /etc/nginx/conf.d/www.itzgeek.net.conf

Then, place the following content into the above configuration file. You will need to change server_name as per your requirement.

server {
	server_name itzgeek.net www.itzgeek.net;
	root /usr/share/nginx/www.itzgeek.net/html;
	
	index index.php index.html;
	
	access_log /usr/share/nginx/www.itzgeek.net/logs/access.log;
	error_log /usr/share/nginx/www.itzgeek.net/logs/error.log;
	

	
	location = /favicon.ico {
        log_not_found off;
        access_log off;
    }

    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }

    location ~* \.(txt|log)$ {
        deny all;
    }

    location ~ \..*/.*\.php$ {
        return 403;
    }

    location ~ ^/sites/.*/private/ {
        return 403;
    }

    # Block access to scripts in site files directory
    location ~ ^/sites/[^/]+/files/.*\.php$ {
        deny all;
    }

    # Allow "Well-Known URIs" as per RFC 5785
    location ~* ^/.well-known/ {
        allow all;
    }

    # Block access to "hidden" files and directories whose names begin with a
    # period. This includes directories used by version control systems such
    # as Subversion or Git to store control files.
    location ~ (^|/)\. {
        return 403;
    }

    location / {
        try_files $uri /index.php?$query_string; # For Drupal >= 7
    }

    location @rewrite {
        rewrite ^ /index.php; # For Drupal >= 7
    }

    # Don't allow direct access to PHP files in the vendor directory.
    location ~ /vendor/.*\.php$ {
        deny all;
        return 404;
    }

    # Protect files and directories from prying eyes.
    location ~* \.(engine|inc|install|make|module|profile|po|sh|.*sql|theme|twig|tpl(\.php)?|xtmpl|yml)(~|\.sw[op]|\.bak|\.orig|\.save)?$|^(\.(?!well-known).*|Entries.*|Repository|Root|Tag|Template|composer\.(json|lock)|web\.config)$|^#.*#$|\.php(~|\.sw[op]|\.bak|\.orig|\.save)$ {
        deny all;
        return 404;
    }

    location ~ '\.php$|^/update.php' {
        fastcgi_split_path_info ^(.+?\.php)(|/.*)$;
        try_files $fastcgi_script_name =404;
        include fastcgi_params;
        fastcgi_param HTTP_PROXY "";
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_param QUERY_STRING $query_string;
        fastcgi_intercept_errors on;
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
    }

    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
        try_files $uri @rewrite;
        expires max;
        log_not_found off;
    }

    # Fighting with Styles? This little gem is amazing.
    location ~ ^/sites/.*/files/styles/ { # For Drupal >= 7
        try_files $uri @rewrite;
    }

    # Handle private files through Drupal. Private file's path can come
    # with a language prefix.
    location ~ ^(/[a-z\-]+)?/system/files/ { # For Drupal >= 7
        try_files $uri /index.php?$query_string;
    }

    # Enforce clean URLs
    # Removes index.php from urls like www.example.com/index.php/my-page --> www.example.com/my-page
    # Could be done with 301 for permanent or other redirect codes.
    if ($request_uri ~* "^(.*/)index\.php/(.*)") {
        return 307 $1$2;
    }
}

Create directories for placing Drupal files and Nginx logs.

sudo mkdir -p /usr/share/nginx/www.itzgeek.net/html/

sudo mkdir -p /usr/share/nginx/www.itzgeek.net/logs/

Verify the Nginx configuration file with the below command.

sudo nginx -t

If you get the following, it means that the virtual host configuration is correct.

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Restart the Nginx and PHP-FPM services.

sudo systemctl reload nginx php7.4-fpm

Install Let’s Encrypt SSL Certificate

Create DNS Record

Go to your domain registrar and create an A and CNAME (optional if you do not want to use www subdomain) record for your domain.

  1. Non-www Domain Name (Ex. itzgeek.net) >> A record point to your server IP
  2. www Domain Name (Ex. www.itzgeek.net) >> CNAME record point to itzgeek.net

For this demo, I will create two records so that my Drupal website will be accessible at www.itzgeek.net.

DNS Records
DNS Records

Install Certbot client

The Certbot client, which helps us generate and install the Let’s Encrypt SSL certificate in Nginx, is now available as a snap package for Debian. So, first, install snapd daemon on your system.

sudo apt update

sudo apt install -y snapd

Then, update snapd to the latest version.

sudo snap install core && sudo snap refresh core

Finally, install the Certbot client using the below command.

sudo snap install --classic certbot

sudo ln -s /snap/bin/certbot /usr/bin/certbot

Install SSL Certificate

Use the below command to generate and install the Let’s Encrypt SSL certificate in the Nginx web server.

sudo certbot --nginx
1. Enter email address to receive notification on urgent renewal and security notices
2. Type Y and press Enter to register with the ACME server
3. Type Y or N to receive emails about EFF news, campaigns, newsletter.
4. Certbot will automatically detect the Drupal domain and ask you to activate HTTPS for your Drupal website. Type 1 or appropriate numbers separated by a comma in case you have multiple websites.
Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: itzgeek.net
2: www.itzgeek.net
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): 1,2

Wait for the SSL installation to complete. You will now be able to access the website with HTTPS.

Note: If you access the website now, you will get a 403 forbidden error because you are yet to place Drupal files.

Redirect non-www HTTP requests to www HTTPS with Nginx

You will need to configure the Nginx server to redirect the traffic from the non-www HTTP site to the WWW HTTPS site, I.e., http://itzgeek.net >> https://www.itzgeek.net.

Auto-Renew SSL Certificate

The Certbot client now includes auto-renewal of SSL certificates through the systemd. So, you will not have to renew the certificates manually.

Install Drupal with Nginx

Create Database for Drupal

First, login into MariaDB/MySQL database server.

sudo mysql -u root -p

Then, create the database for Drupal installation along with the database user and password.

CREATE DATABASE drupaldb;

CREATE USER 'drupaluser'@'localhost' IDENTIFIED BY 'password';

GRANT ALL PRIVILEGES ON drupaldb.* TO 'drupaluser'@'localhost';

EXIT

Download Drupal Package

Download the latest version of the Drupal installer by using the following command.

wget https://www.drupal.org/download-latest/tar.gz -O drupal-latest.tar.gz

Then, extract the downloaded file.

tar -zxvf drupal-latest.tar.gz

And then, move the files to your website document root directory.

sudo mv drupal-*/* /usr/share/nginx/www.itzgeek.net/html/

Update the ownership and a group of the Drupal website directory.

sudo chown -R www-data:www-data /usr/share/nginx/www.itzgeek.net/

Install Drupal CMS

Open your browser and visit your Drupal domain to perform the Drupal installation.

https://your-drupal-website

1. Choose Language for your Drupal installation and website and then click Save and continue

2. Select an installation profile that is suitable for you and then click Save and continue

3. Enter the Drupal database details in the Database configuration page and then click Save and continue

4. Wait for the Drupal installation to complete

5. You will need to Configure site by entering Site Information, Site Maintenance Account, Region Settings, and Update Notifications. Finally, click Save and continue

6. Upon completion, the installer will redirect you to the Drupal back-end to manage the installation. Alternatively, you can access the Drupal back-end by going to https://your-drupal-website/user/login

Access Drupal Website

Now, you will be able to access the site with your domain name.

https://your-drupal-website

"<yoastmark

Screenshot of Drupal CMS Back-End:

"<yoastmark

After the installation, enable the Trusted Host Settings to protect your Drupal website against HTTP HOST Header attacks.

Conclusion

That’s All. I hope you have learned how to install Drupal with Nginx and Let’s Encrypt SSL on Debian 11.

You might also like