
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:
- Use Drush command line
drush cr
- 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.