On this page
- Password protect the staging server but not local or production
- Protect the production domain by allowing admin operations only through a shielded sub-domain
- Additional security
- Run cron locally
- The settings.local.php file
- Multisite setup
- Caching mechanism
- Search
- Consuming external services
- Perform a PHP upgrade
- An example of an upgrade from PHP 7.2 to 7.4
- Used terminal commands
- Run the website on the new PHP version to test
- Access recent log messages (watchdog)
- Additional sources
What's more?
This documentation is deprecated.
There might be additional server setup you would like to replicate in your development environment.
Password protect the staging server but not local or production
Usually, you don't want your staging server to be publically available, apart from hiding it from prying eyes mainly to avoid it being indexed by search engines. This can be accomplished with Htaccess password protection (aka shielding). However, you don't want Htaccess password protection to kick in on your local or production environment. This can be easily accomplished by making an addition to the .htaccess file in the Drupal root. There is no need for additional Drupal modules, like Shield.
Next, you have to generate a user with a hashed password and put it in a .htpasswd file in the same folder. Remember that you use the full path to it in the .htaccess file, for example, /var/www/html/staging.domain.com/web/.htpasswd.
Protect the production domain by allowing admin operations only through a shielded sub-domain
With the Limit Domain Access By Role module, you can whitelist a shielded technical sub-domain (e.g. your-client.your-agency.com) to allow admin roles to interact only there. It points to the same folder as the production domain (e.g. your-client.com), so any admin operations affect the same database, but direct access to the production domain is disallowed for admin roles.
This way, a malicious user that somehow manages to get an admin role assigned or obtain credentials of user #1, will not be able to login with it on the production domain. Even if they know the URL of the technical sub-domain, that one requires then an additional Htaccess password, one of the strongest methods of protection.
To implement, just swap in the linked instructions in the section above the suggested staging domain with the used technical sub-domain and enable the Limit Domain Access By Role module. Additionally, it gives the advantage to be able to test if the technical domain is still running when the production domain is down, indicating probably the DNS server is the culprit.
Additional security
Website security often consists of a series of measures. If one fails, the next one will be there. The more hurdles there are, the better. Even if some can be circumvented, they might still make it harder to get in, especially for automated malicious scripts that rely on a common file location or set up. Apart from allowing admin operations only through a shielded sub-domain as described above, there are other measures to "disorientate" potential malicious visitors:
- Change the location from the commonly used web directory path such as /var/www/html to something less predictable.
- Instead of using 'admin' as the username of user #1, use another name, even just changing one character like 'atmin'. Obviously, its profile page should not be accessible and you should not use the superuser to create content either, to avoid the username being exposed as the author.
- On the production site always use
composer install --no-dev, so that unnecessary and vulnerable packages as PHPUnit are not available as attacking points. - Always secure the files on your website properly. Why (and how to do it in Drupal) | Lucius.
Run cron locally
Set up cron to run locally every five minutes:
- Go to admin/config/system/cron and copy the URL to run cron from outside the site.
- From the terminal run:
crontab -e - Add as the last line:
*/5 * * * * curl -s -o /dev/null "[paste the URL copied previously]". See crontab every 5 minutes. - Save.
- Go back to admin/config/system/cron and refresh the page regularly to see if cron runs every five minutes (might not be exact).
- Remember that Ultimate Cron extends Drupal standard cron, allowing fine-grained control over the exact interval of each task. Go to admin/config/system/cron/jobs to check.
The settings.local.php file
Use a settings.local.php file to override or add configuration settings on your development environment.
A Drupal 7 example:
<?php
$conf['stage_file_proxy_hotlink'] = TRUE; // To use please enable the stage_file_proxy module to hotlink broken images to the live site.
$conf['stage_file_proxy_origin'] = 'https://www.example.com'; // The live site to hotlink from.
$conf['stage_file_proxy_origin_dir'] = 'sites/default/public_files'; // The path to hotlink from.
$conf['preprocess_css'] = 0; // Switch off CSS aggregation.
$conf['preprocess_js'] = 0; // Switch off JS aggregation.
$conf['theme_debug'] = TRUE; // See template suggestions and the locations of template files in the HTML markup.
$conf['error_level'] = 2; // Error messages to display.
ini_set('max_execution_time', 60); // To adjust PHP execution time.
ini_set('memory_limit', 64M); // To adjust PHP memory limit
$databases['default']['default']['init_commands'] = array(
'isolation' => "SET SESSION tx_isolation='READ-COMMITTED'"
); // avoid db deadlocks. Ref: https://www.drupal.org/node/1952972
// Override of a path that doesn't exist on local.
$conf['file_private_path'] = '';For Drupal 8 (settings.local.php) you would use:
<?php
$config['system.performance']['css']['preprocess'] = 0; // Switch off CSS aggregation.See Configuration override system | Drupal.org.
The best starting point is to copy sites/example.settings.local.php to sites/default/settings.local.php and then uncomment the last part of sites/default/settings.php to load the local development override configuration and then disable caching during development.
Multisite setup
See Multi-site - Sharing the same code base | Drupal 7 guide on Drupal.org
Note:
- This document is based upon Drupal 7, but it's also valid for Drupal 8. There are some specifics for Drupal 8, when you read the full document you will come across them.
- Drush commando for multisite e.g. to clear the cache of a specific domain:
drush -l someotherdomain.localhost cr
Caching mechanism
Additional steps might be needed to make the cache work as on your production server like Memcache.
Example settings.local.php:
// Memcache settings.
$conf['cache_backends'][] = 'sites/all/modules/contrib/memcache/memcache.inc';
$conf['cache_class_cache_form'] = 'DrupalDatabaseCache';
$conf['cache_default_class'] = 'MemCacheDrupal';
$conf['memcache_key_prefix'] = 'default';
$conf['lock_inc'] = 'sites/all/modules/contrib/memcache/memcache-lock.inc';
$conf['memcache_stampede_protection'] = TRUE;
$conf['memcache_servers'] = array(
'127.0.0.1:11211' => 'default',
);If you have a server cluster handled via load balancer then the server version of local.settings.php might look like this in each server
// Memcache settings.
$conf['cache_backends'][] = 'sites/all/modules/contrib/memcache/memcache.inc';
$conf['cache_class_cache_form'] = 'DrupalDatabaseCache';
$conf['cache_default_class'] = 'MemCacheDrupal';
$conf['memcache_key_prefix'] = 'default';
$conf['lock_inc'] = 'sites/all/modules/contrib/memcache/memcache-lock.inc';
$conf['memcache_stampede_protection'] = TRUE;
$conf['memcache_servers'] = array(
'server1:11211' => 'default',
'server2:11211' => 'default',
'server3:11211' => 'default',
'server4:11211' => 'default',
);Search
Additional steps might be needed to make the search mechanism work as on your production server like Solr.
Alternatively: Install Solr 7 for Drupal 8 Search API on Ubuntu 16.04 (seems still valid for 18.04, open for discussion)
Example settings.local.php:
<?php
// Local Solr configuration.
$conf['search_api_override_mode'] = 'load';
$conf['search_api_override_servers'] = array(
'solr_server' => array(
'name' => 'My Solr Server (overriden)',
'options' => array(
'host' => 'localhost',
'port' => '8983',
'scheme' => 'http',
'path' => '/solr',
'http_user' => '',
'http_pass' => '',
'excerpt' => 0,
'retrieve_data' => 0,
'highlight_data' => 0,
'http_method' => 'POST',
),
),
);Re-index search (using Search API):
drush search-api:reset-tracker
drush search-api:index
drush crConsuming external services
You might need to add credentials to the settings.php file to be able to authenticate on external services. Furthermore, you might need additional packages like a SoapClient installation.
Example settings.local.php:
<?php
$conf['service_client_submit'] = array(
'soap_service_endpoint' => 'https://example.com/some_service',
'service_username' => 'some_username',
'service_password' => 'some_password',
);Perform a PHP upgrade
Run the recommended version of PHP for your version of Drupal. That is unlikely to be possible if you run a mix of Drupal versions on the same server, for example, Drupal 7 and Drupal 8. It is wise to keep separate servers for the web applications that you intend to upgrade quickly in the future and those that can wait for a while. This decision is likely based on:
- complexity: Many or particular contrib modules and custom code make a Drupal version upgrade more time-consuming.
- security: the amount and type of user interaction. Less user input from unknown users usually makes a web application less likely to be hacked. You can alleviate this by allowing admin operations only on a technical (sub)domain (admin.example.com) that is different from the URL of the publically available site (example.com). This mitigates XSS and cross-site request forgery vulnerabilities, the most commonly needed protection.
- security: the type of data and uploaded files that are stored. If high sensitive user data is present, the consequence of a security breach is bigger. Data/file encryption and setting up the Private File System correctly can alleviate this.
- security: the severity of a data loss. Having a frequent backup and restore system for both data and files can alleviate this.
In preparation for a Drupal version upgrade, it is likely it has to be preceded by a PHP upgrade. Do that locally first and test. Document the followed steps to be able to replicate this on the remote servers.
An example of an upgrade from PHP 7.2 to 7.4
Based on Ubuntu with Apache and MySQL.
Used terminal commands
Check your current PHP version:
php -vCheck your current PHP extensions:
php -mInstall PHP 7.4 core:
sudo add-apt-repository ppa:ondrej/php # Press enter to confirm.
sudo add-apt-repository ppa:ondrej/apache2 # Press enter to confirm.
sudo apt-get update
sudo apt install php7.4 php7.4-common php7.4-cliInstall the required extensions:
sudo apt install php7.4-curl php7.4-json php7.4-gd php7.4-mbstring php7.4-intl php7.4-mysql php7.4-dom php7.4-bcmath php7.4-bz2 php7.4-readline php7.4-zip
Deactivate the old PHP version and activate the new one:
sudo a2dismod php7.2 && sudo a2enmod php7.4Optional: Allow for PHP short tag (<?) besides a regular PHP tag (<?php):
sudo nano /etc/php/7.4/apache2/php.ini
short_open_tag = On # Change the following line from Off to On.Check if the MySQL Improved Extension is enabled:
php -m | grep mysqliRestart Apache:
sudo service apache2 restart-
If you get any errors on Apache restart, you can debug with:
systemctl status apache2.service
Check your new PHP version:
php -vCheck your new PHP extensions:
php -mRun the website on the new PHP version to test
Clear the cache of the websites running on this server and visit them in the web browser to see if they run without hick-ups. Log in as a super admin and check the status report at admin/reports/status.
Access recent log messages (watchdog)
The log messages list can normally be accessed at admin/reports/dblog if the core dblog module is enabled. You can use drush watchdog:show in case you do not have admin access OR you get:
The website encountered an unexpected error. Please try again later.
Additional sources
- Upgrading to PHP 7.4 - DEV Community
- Set up a local development environment | Set up a local development Drupal site on the latest Ubuntu LTS version and more | Drupal Wiki guide on Drupal.org
- Troubleshooting and other resources | Set up a local development Drupal site on the latest Ubuntu LTS version and more | Drupal Wiki guide on Drupal.org
Next: Know your tools >>
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