Install and Secure your Drupal website

Installing and Securing Drupal ubuntu debian redhat centOS

Introduction

Drupal is a popular open-source content management system (CMS) used to build websites and web applications. With its modular architecture and thousands of add-on modules, Drupal is highly flexible and customizable. However, like any complex web application, Drupal requires proper configuration and hardening to ensure security.

This guide will walk you through installing Drupal 10 from scratch in a Linux environment. It will also cover essential security measures to lock down access and protect against common web vulnerabilities. By the end, you will have a Drupal site ready for development with a solid security foundation.

Prerequisites

Before installing Drupal, ensure your Linux server meets the following requirements:

  • Ubuntu 20.04 or higher
  • Apache 2 web server
  • MySQL 5.7 or higher OR MariaDB 10 or higher
  • PHP 7.3 or higher with required extensions
  • Composer – Dependency Manager for PHP
  • Writable directories for Drupal and its files

Also, make sure you have an available domain or subdomain that points to your server’s IP address.

Log in as a non-root user with sudo privileges to perform the installation.

Step 1 – Install LAMP Stack

Drupal requires the Linux, Apache, MySQL/MariaDB, PHP (LAMP) stack to operate. Use the following commands to install these components:

$ sudo apt update
$ sudo apt install apache2 mariadb-server php php-mysql php-json php-gd php-mbstring php-xml php-curl

Install other required PHP extensions:

$ sudo apt install php-zip php-soap php-gd

Enable Apache modules needed by Drupal:

$ sudo a2enmod rewrite headers env dir mime

Secure MySQL installation:

$ sudo mysql_secure_installation

Start MySQL and Apache services:

$ sudo systemctl start mysql
$ sudo systemctl start apache2 

Check that Apache is running properly by accessing your server’s domain or IP address in your browser. You should see the default Apache page.

Step 2 – Download Drupal

First, navigate to the Drupal downloads page and get the latest Drupal 10 release:

$ cd /tmp
$ wget https://www.drupal.org/download-latest/tar.gz

Extract the tar.gz file into the Apache web root directory:

$ sudo tar -xvf drupal-10*.tar.gz -C /var/www/html

The extracted directory will be named something like drupal-10.1.6. Rename it to simply drupal:

$ sudo mv /var/www/html/drupal-10.1.6 /var/www/html/drupal

Set ownership to the web server user:

$ sudo chown -R www-data:www-data /var/www/html/drupal

Adjust file permissions:

$ sudo chmod -R 775 /var/www/html/drupal

Drupal 10 files are now in place and ready for installation.

Step 3 – Create MySQL Database

Log in to MySQL prompt:

$ mysql -u root -p

Create a database and user for Drupal:

CREATE DATABASE drupal10db; 
CREATEUSER'drupal10user'@'localhost' IDENTIFIED BY'DBpa55word';
GRANTALLON drupal10db.*TO'drupal10user'@'localhost';
exit

Replace ‘DBpa55word’ with a secure password.

This creates a dedicated DB user with full privileges for Drupal database.

Step 4 – Configure Apache Virtual Host

Create Drupal virtual host config:

$ sudo nano /etc/apache2/sites-available/drupal10.conf

Add the following, updating paths/domains as needed:

<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    DocumentRoot "/var/www/drupal10/web"
    ServerName drupal10.example.com
    <Directory /var/www/drupal10/web>
        Options FollowSymlinks
        AllowOverride All
        Require all granted
    </Directory>
    ErrorLog ${APACHE_LOG_DIR}/drupal10-error.log
    CustomLog ${APACHE_LOG_DIR}/drupal10-access.log combined
</VirtualHost>

Enable the new virtual host and restart Apache:

$ sudo a2ensite drupal10.conf
$ sudo systemctl restart apache2

Step 5 – Install Drupal

Access your domain in a web browser and start Drupal 10 installation.

Select language then choose Standard installation profile.

On the Verify requirements page, ensure all items are checked. Resolve any issues listed.

For the database configuration use the MySQL database, user, and password created earlier.

** IMPORTANT: Disable sending usage statistics to contribute Drupal improvements. This helps protect privacy.

Create a site name, default admin user, and strong password.

Wait for installation to complete then log in with the admin user.

The base Drupal site is now installed and ready for development!

Step 6 – Configure Security Settings

After installation, it’s important to review security related settings and apply best practices to lock down Drupal.

In Administration sidebar, go to Configuration > System > Basic site settings then under Front page content set homepage to be a blank page.

Still under System, go to Cron and enable Cron handling. This is needed for scheduled tasks.

Under Content authoring section, go to Text formats and configure

  • Restrict HTML tags
  • Disable JavaScript input format

This helps prevent XSS issues when allowing users to post content.

Next, under Media, disable the Local files source. Instead, configure cloud storage for uploads like S3 or equivalent.

Under Configuration > Media > File system, set the Default download method to Privately accessible files.

For higher security, in Configuration > Media settings set Public file system path to private://

This prevents accessing uploaded file paths directly through the site URL.

In Configuration > System > File system ensure the sites/default/files Public file system path is set to private://

This prevents accessing site file assets directly through the site URL.

Under Configuration > System > Logging and errors enable verbose Database logging, Failed login attempts and Page not found errors.

Still under Logging and errors, click Clean URLs Ensure “Enable clean URLs” checkbox is ticked. This improves SEO

Scroll down to Bandwidth optimization section and enable the following:

  • Aggregate CSS files
  • Aggregate JavaScript files
  • Optimize CSS files
  • Optimize JavaScript files

This reduces requests and improves performance.

In Configuration > SEO start by setting a site Default front page title, Default

Under Search engine optimization tick the checkbox for “Generate meta tags” Enable clean URLs and the globe favicon.

For social media, configure Facebook and Twitter options.

In Configuration > System > PHP set Uploads directory outside web root to sites/default/files/private

This prevents accessing uploaded files directly through URL path.

Set Max POST size and Max file upload size to align with site requirements.

Important: To apply the above changes either:

  1. Use Drush command line drush cr
  2. OR go to /update.php URL directly e.g. example.com/update.php

This will clear caches and rebuild routes for the changes to take effect.

Step 7 – Review Permissions

Since Drupal requires write access to certain directories, permissions should be properly configured based on least privilege principles.

Check write permissions are set only on required directories:

$ sudo chown -R www-data:www-data /var/www/drupal10/web/sites/default
$ sudo find /var/www/drupal10/web/sites/default -type d -exec chmod 775 {} \;  
$ sudo find /var/www/drupal10/web/sites/default -type f -exec chmod 664 {} \;

Set recommended file system permissions:

$ sudo find /var/www/drupal10/web -type d -exec chmod 755 {} \;
$ sudo find /var/www/drupal10/web -type f -exec chmod 644 {} \;

Secure the settings.php file:

$ sudo chmod 444 /var/www/drupal10/web/sites/default/settings.php

Constant review of file permissions is important to avoid insecure defaults.

Step 8 – Secure The Database

Since the database stores sensitive data, take precautions to prevent data loss or breaches:

  • Avoid using the database root user. Instead, grant limited privileges to Drupal user.
  • Set a strong password for MySQL users with length > 12 chars and special characters.
  • Don’t expose database to public network. Put it inside private subnet instead of DMZ or public subnet.
  • Enable MySQL reverse proxy to add an additional layer of security for database traffic.
  • Perform frequent backups and test restores.

Follow backups best practices:

  • Schedule daily database dumps
  • Backup website files and code
  • Store backups separately from the web root
  • Encrypt backup files
  • Test restoration on staging environment.

This protects against data loss from user errors, system crashes or ransomware attacks.

Step 9 – Secure The Web Server

Since Apache server will be Internet-facing it requires robust protections:

Disable unused modules to reduce attack surface area:

$ sudo a2dismod status actions alias autoindex

Configure mod_security Web Application Firewall (WAF) to filter traffic:

$ sudo apt install modsecurity libapache2-mod-security2 
$ sudo nano /etc/modsecurity/modsecurity.conf

Enable mod_security rules engine:

SecRuleEngine On  

Proxy traffic via a Web Application Firewall (WAF) for deep package inspection:

$ sudo apt install mod_security crudini
$ crudini --set /etc/modsecurity/modsecurity.conf \
  owasp.crs components.response.body_access false
$ sudo systemctl restart apache2

Use HTTPS with a valid SSL certificate to enable encryption. Redirect all traffic to HTTPS version.

Harden the site with additional security headers:

$ sudo nano /etc/apache2/sites-available/drupal10.conf 
Header set X-Frame-Options "SAMEORIGIN"
Header set X-XSS-Protection "1; mode=block"
Header set X-Content-Type-Options "nosniff"
Header set Referrer-Policy "same-origin"
Header always append X-Frame-Options SAMEORIGIN

Save file and restart Apache.

This helps guard against common XSS, clickjacking and MIME attacks.

For performance, enable browser caching of static assets:

<FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|webp|js|css|swf)(\.gz)?$">
Header set Cache-Control "max-age=604800, public"
</FilesMatch>

604800 seconds = 1 week. This avoids re-downloading unchanged assets.

Monitor site traffic logs for anomalies indicating attacks. Implement log analysis and alerting.

Stay up to date on Drupal security advisories and apply latest patches.

Step 10 – Automate Drupal Cron

Cron manages scheduled tasks like caching, updates, data optimization.

Option 1 – Run cron manually

Enable crontab access for web server user:

$ sudo crontab -u www-data -e

Add cron entry:

* * * * * /usr/bin/php /var/www/drupal10/web/core/scripts/cron.sh >> /var/www/drupal10/cron.log

Option 2 – Automated cron

Use Drupal Queue Cron module to trigger cron without sys admin access

$ composer require drupal/queue_cron
$ drush en -y queue_cron

Adjust cron settings in Drupal UI at admin/config/system/cron.

Option 3 – Use system cron daemon

$ sudo systemctl edit cron

Paste:

[Service]  
User=www-data

Save and exit.

$ sudo systemctl restart cron

This runs cron jobs as web server user.

Adjust cron settings in Drupal UI at admin/config/system/cron.

Step 11 – Ongoing Maintenance

Set up regular tasks to ensure long term security:

  • Review logs – Scan Apache/Drupal logs for signs of attacks
  • Apply updates – Patch Drupal core, contrib modules, PHP, OS security issues promptly
  • Review permissions – Fix insecure defaults
  • Backup data – Automate daily database + file backups to alternate location
  • Test restore – Verify backups integrity; test restores in staging site
  • Renew SSL certificate – Use auto-renewal to avoid expiry/warnings
  • Monitor site – Use intrusion detection and firewalls to get attack alerts

Conclusion

With these steps, you now have a secure Drupal 10 installation tuned for performance, with protections against common vulnerabilities.

Be sure to follow security best practices moving forward to ensure your Drupal site remains hardened over time. Enable logging/monitoring and apply a “defense in depth” strategy with multiple layers of security.

Stay vigilant about emerging threats by following Drupal security advisories. Automate patches to ensure you don’t miss critical updates.

With ongoing hardening and proactive maintenance, you can confidently build out your Drupal functionality while keeping the backend locked down from intruders.

LEAVE A COMMENT