Moving all PHP files out of the docroot
This documentation needs review. See "Help improve this page" in the sidebar.
Traditionally all Drupal core, vendor and module PHP files are in the webserver accessible document root folder. This is a security weakness because Remote Code Execution vulnerabilities are found all the time when random PHP files are directly accessible. For example Drupal 8.2.7 had to fix a vulnerability in the vendor directory where a library shipped a PHP file exploitable by directly accessing it.
It is possible to run a Drupal 8 site with a clean docroot folder that does not contain code files and is therefore a lot more secure by default.
Core patch for image styles
To make image style generation work apply the image style system patch.
Directory setup
Assuming you have a Drupal 8 folder like this:
drupal-8
- core
- index.php
- modules
- profiles
- sites
- themes
- vendor
Create a new folder "docroot" in your Drupal 8 folder, so it looks like this:
drupal-8
- core
- docroot
- index.php
- modules
- profiles
- sites
- themes
- vendor
docroot will be the new folder that the webserver points to.
Webserver config change
Point your webserver config to the new docroot subfolder.
Apache example:
<VirtualHost *:80>
ServerAlias drupal-8.localhost
DocumentRoot /home/klausi/workspace/drupal-8/docroot
<Directory "/home/klausi/workspace/drupal-8/docroot">
Options FollowSymLinks
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
Nginx example:
server {
server_name drupal-8.localhost;
root /home/klausi/workspace/drupal-8/docroot;
# Other config options here ...
}
index.php and robots.txt in docroot
Create a small index.php file in the docroot folder that will just include the index.php file from Drupal core:
chdir('..');
require 'index.php';
Create links for robots.txt (and .htaccess if using Apache) in the docroot folder:
cd docroot
ln -s ../robots.txt
ln -s ../.htaccess
Public files directory
Create a folder for public files in docroot/files. It must be writeable by the webserver.
mkdir docroot/files
Edit your settings.php file (usually sites/default/settings.php) and set the following:
$settings['file_public_path'] = 'docroot/files';
// Replace http://drupal-8.localhost with your site's URL or $base_url if you have defined that.
$settings['file_public_base_url'] = 'http://drupal-8.localhost/files';
rsync script to mirror asset files
Since Drupal core and modules ship with JavaScript, CSS and image files we need to copy those to the webserver accessible docroot with a script like this placed in the old document root:
#!/bin/bash
SYNC_FOLDERS="core libraries modules profiles themes"
for DIR in $SYNC_FOLDERS; do
rsync -mr --include='*.'{js,css,svg,png,jpg,jpeg,ico} --include='*/' --exclude='*' $DIR/ docroot/$DIR/
done
Execute this script every time you do a deployment. It can be part of your deployment script that runs git pull, composer install and drush updb for example.
Conclusion
Congratulations! You have now a much more secure Drupal 8 installation that has zero code files in the publicly accessible document root.
Help improve this page
You can:
- Log in, click Edit, and edit this page
- Log in, click Discuss, update the Page status value, and suggest an improvement
- Log in and create a Documentation issue with your suggestion