Drupal stack containers¶
Apache¶
New Apache image
Since Drupal stacks 5.2.0+ Apache image wodby/php-apache
has been replaced with wodby/apache
with $APACHE_VHOST_PRESET=php
- Apache can be configured with the following environment variables
- Installed apache modules
Restarting apache as default user:
sudo httpd -k restart
See details about virtual host preset.
AthenaPDF¶
See AthenaPDF stack documentation.
Crond¶
Resources limitation
By default we limit crond container memory to 512M (request 8Mb) for all environments and limit CPU to 1 core (request 0.1 core) on production environments.
A duplicate of the main PHP container runs with crond (instead of FPM). You can customize crontab from [Instance] > Stack > Settings
page.
Drupal Node.js¶
Drupal node is a container with a server app for the Node.js Integration Drupal module. You can configure Node.js via environment variables that listed at https://github.com/wodby/drupal-node
Usage:
- Install Node.js Integration Drupal module on your site
- Visit the Node.js configuration page under the Configuration menu, and enter the connection information for your Node.js server application. Set port to
8080
, host tonode
(ordrupal-node
for local environment) and the service key with the value that can be found on[App] > Stack > Node.js
(for local environment specified in$NODE_SERVICE_KEY
of yourcompose.yml
)
Mailhog¶
If Mailhog service enabled and chosen as Mail delivery service at [Instance] > Stack > Settings
all outbound email will be caught by the Mailhog. You can view and release these emails from Mailhog UI, the URL can be found from Domains tab. When release specify opensmtpd
in SMTP server
field if you want to release emails to the default Mail transfer agent (OpenSMTPD).
MariaDB¶
See MariaDB stack documentation.
Memcached¶
You can check the status of memcached and its hits by running the following command.
watch "echo stats | nc 127.0.0.1 11211"
Nginx¶
Nginx can be configured with the following environment variables
Restarting nginx as default user:
sudo nginx -s reload
Do not gzip pages in your application
We already gzip content on Nginx side and it works faster. Having double gzip may cause issues.
Modules¶
Installed nginx modules.
PageSpeed¶
Nginx comes with mod_pagespeed which is disabled by default. To enable it add NGINX_PAGESPEED_ENABLED=1
environment variable to Nginx service. For more details see https://github.com/wodby/pagespeed.
ModSecurity + OWASP¶
Nginx comes with ModSecurity which is disabled by default. To enable it add NGINX_MODSECURITY_ENABLED=1
environment variable to Nginx service. For more details see https://github.com/wodby/modsecurity.
Custom config¶
If a config preset and available environment variables are not enough for your customizations you can use your own virtual host config:
- Copy
/etc/nginx/conf.d/vhost.conf
to your codebase, adjust to your needs - Deploy code with your config file
- Add new environment variable
NGINX_CONF_INCLUDE
for nginx service, the value should the path to your*.conf
file (e.g./var/www/html/vhost.conf
). The specified file will be included in/etc/nginx/nginx.conf
See details about virtual host preset.
PHP endpoints¶
For security reasons, default nginx config allows executing limited php endpoints. This is how you can add additional php endpoints:
- Add
locations.conf
file to your codebase with locations definition, example:location = /custom-php-endpoint.php { fastcgi_pass php; }
- In nginx service configuration set new environment variable
NGINX_SERVER_EXTRA_CONF_FILEPATH=/var/www/html/locations.conf
. It will be included at the end of/etc/nginx/defaults.conf
- Restart the service
Alternatively, you can replace your HTTP server to Apache (not recommended) that has less strict rules.
XML endpoints¶
By default nginx config requests Drupal backend when rss.xml
or sitemap.xml
requested. If you want to add another XML endpoint generated by Drupal just set environment variable NGINX_DRUPAL_ALLOW_XML_ENDPOINTS
to any value and restart the service.
Files proxy¶
When using stage_file_proxy set $NGINX_STATIC_404_TRY_INDEX=1
to redirect 404 static files requests to Drupal.
Alternatively, you can proxy all requests to files without bootstrapping Drupal to another URL (e.g. another Drupal instance with files) by adding the environment variable NGINX_DRUPAL_FILE_PROXY_URL=http://example.com
.
Node.js¶
Light-weight node.js container to help you build your application's frontend. The containers comes without any global pre-installed packages, you can add them by running yarn global add PACKAGE
or by running yarn
in a directory with your package.json
file.
OpenSMTPD¶
See OpenSMTPD stack documentation.
PHP¶
- PHP can be configured with the following environment variables
- Available php extensions
Environment variables¶
Variables availability
Environment variables (except ones provided by Wodby) won't be available in PHP-FPM because we set PHP_FPM_CLEAR_ENV=yes
by default for security reasons. You can set it to yes
to make all environment variables available in your code.
In addition to global environment variables, we provide the following variables in PHP container that you can use in your post-deployment scripts or settings files:
Variable | Description |
---|---|
$APP_ROOT |
/var/www/html by default |
$HTTP_ROOT |
e.g. /var/www/html/web |
$CONF_DIR |
/var/www/conf by default |
$WODBY_APP_NAME |
My app |
$WODBY_HOST_PRIMARY |
example.com |
$WODBY_URL_PRIMARY |
http://example.com |
$WODBY_HOSTS |
[ "example.com", "dev.example.org.wodby.cloud" ] |
Deprecated variables:
Variable | Instead use |
---|---|
$WODBY_APP_ROOT |
$APP_ROOT |
$WODBY_APP_DOCROOT |
$HTTP_ROOT |
$WODBY_CONF |
$CONF_DIR |
$WODBY_DIR_CONF |
$CONF_DIR |
Files directory permissions¶
Public files directory (symlink to /mnt/files/public
) that used for uploads owned by www-data
user (PHP-FPM user) by default and the default container user (wodby
) has no writing permissions. So if you run a command that creates files in a public directory you will get insufficient permissions error. You can fix this problem by giving writing permissions for files directory to the owner's group (user wodby
is a member of www-data
group) by using one of the helper scripts:
sudo files_chmod /mnt/files/public
When you manually import files under wodby
user you should change files ownership to www-data
user to let PHP-FPM create new files in directories, run the following command to change the ownership:
sudo files_chown /mnt/files/public
Helper scripts scope
files_chmod
and files_chown
are the only sudo
commands available to wodby
user and can be applied only to directories under /mnt/files
.
For mode details about users and permissions in PHP container see https://github.com/wodby/php#users-and-permissions
Codebase directory permissions¶
The codebase owned by the default wodby
(uid/gid 1000
) user. If you need to give writing permissions to PHP-FPM (www-data
user with uid/gid 82
) to a directory outside on public files directory you can either access a container as root user or change it from the host server (single-server infrastructure):
chown -R 1000:82 /srv/wodby/instances/[INSTANCE_UUID]/app/path-to-directory
chmod -R 775 /srv/wodby/instances/[INSTANCE_UUID]/app/path-to-directory
SSH and Cron containers
For Wodby environments we additionally spin up copies of PHP services with overridden commands to run cron and ssh daemons. All environment variables added to PHP-FPM service will be automatically passed to SSHd and Crond services.
Drupal-specific¶
Additionally, variable $DRUPAL_SITE
(previous deprecated name $WODBY_APP_SUBSITE
) contains Drupal site directory, e.g. default
.
WARNING
Some environment variables used by PHP may be overridden in wodby.settings.php
file
NewRelic¶
You can add NewRelic APM monitoring for PHP by adding environment variables PHP_NEWRELIC_ENABLED=1
and PHP_NEWRELIC_LICENSE
with your license number to PHP-FPM container. Application name will be automatically set to [Wodby Application Name] - [Wodby Instance Name]
, if you want to change it, use PHP_NEWRELIC_APPNAME
.
Profiling¶
Must know before using profiler
- Both XHProf and Xdebug profiling decreases performance and increases resources usage, especially xdebug. Try to avoid using in production
- Traces files take a lot of disk space and may cause out of disk space very quickly
XHProf¶
Enable XHProf extension by overriding the environment variable PHP_EXTENSIONS_DISABLE=""
to your PHP container (by default, it's set to xdebug,xhprof
).
Use the following example snippet to profile your code:
// Start profiling.
if (extension_loaded('xhprof')) {
xhprof_enable(XHPROF_FLAGS_MEMORY | XHPROF_FLAGS_CPU);
}
// Code which should be profiled.
// ...
// Store profile.
if (extension_loaded('xhprof')) {
$xhprof_out = '/mnt/files/private/xhprof';
if (!file_exists($xhprof_out)) {
mkdir($xhprof_out);
}
file_put_contents(sprintf('%s/%s.%s.xhprof', $xhprof_out, uniqid(), 'web'), serialize(xhprof_disable()));
}
Once traces files generated you can view and analyze your traces via XHProf viewer
Xdebug profiler¶
Enable XDebug profiling by adding the following environment variables to your PHP container (! xdebug env vars have changed since version 3.x):
PHP_XDEBUG: 1
PHP_XDEBUG_MODE: profile
PHP_XDEBUG_START_WITH_REQUEST: trigger
PHP_XDEBUG_TRIGGER_VALUE: 1
Add XDEBUG_PROFILE=1
param to GET or POST request (or set a cookie) you want to profile. Xdebug will generate profile files in /mnt/files/xdebug
. Click Update in Webgrind to access the new information. See https://xdebug.org/docs/profiler to learn more about xdebug profiling.
Once traces files generated you can view and analyze your traces via Webgrind
Xdebug¶
Debugging locally
For using xdebug locally see documentation for local environment
Follow these steps to debug your application instance remotely with xdebug:
- Enable xdebug for your instance from
[Instance] > Stack > Settings
- Set up forwarding for xdebug: copy Xdebug SSH tunnel command from
[Instance] > Stack > SSH server (PHP)
and run on your local machine - Make sure you have your IDE xdebug listener running on port 9000
- Start debugging in IDE
- Start your browser debug helper plugin (Chrome or Firefox) and open the page you want to debug
For xdebug troubleshooting enable logs by adding $PHP_XDEBUG_REMOTE_LOG=/tmp/php-xdebug.log
environment variable to PHP container.
Xdebug troubleshooting
Enable xdebug logs to get more information by adding $PHP_XDEBUG_REMOTE_LOG=/tmp/php-xdebug.log
environment variable to PHP container.
PHPUnit¶
- Inside your drupal/core directory, copy the file
phpunit.xml.dist
and rename it tophpunit.xml
- Open that file and make sure that you update
SIMPLETEST_BASE_URL
tohttp://nginx
- In order to make sure that your DB connection is working as well, update
SIMPLETEST_DB
tomysql://drupal:drupal@mariadb/drupal
Drush¶
PHP container comes with pre-installed drush and drush launcher. Drush launcher will help you use drush that comes with your project without specifying the full path to it. See how to use drush aliases.
Drupal Console¶
PHP container comes with installed drupal console launcher (not the same as drupal console), the launcher used to be able run drupal console without specified the full path to it. Please note that starting Drupal Console ~1.0 you have to install it manually (via composer) per project.
PostgreSQL¶
See PostgreSQL stack documentation.
Redis¶
You can use Redis as a cache storage for your Drupal application. Redis in-memory storage works much faster compared to the default Drupal's cache storage – database.
Wodby environment¶
- Download and install redis module
- Make sure redis service enabled in your stack
- Additionally, for Drupal 8: enable redis integration under
[Instance] > Cache > Settings
page - That's it, all required configuration already provided in
wodby.settings.php
file
Local environment¶
- Download and install redis module
- Add the following lines to your
settings.php
file (make sure the path to redis module is correct):
For Drupal 8+:
$settings['redis.connection']['host'] = 'redis';
$settings['redis.connection']['port'] = '6379';
//$settings['redis.connection']['password'] = '';
$settings['redis.connection']['base'] = 0;
$settings['redis.connection']['interface'] = 'PhpRedis';
$settings['cache']['default'] = 'cache.backend.redis';
$settings['cache']['bins']['bootstrap'] = 'cache.backend.chainedfast';
$settings['cache']['bins']['discovery'] = 'cache.backend.chainedfast';
$settings['cache']['bins']['config'] = 'cache.backend.chainedfast';
$settings['container_yamls'][] = "modules/contrib/redis/example.services.yml";
For Drupal 7:
$conf['redis_client_host'] = 'redis';
$conf['redis_client_port'] = '6379';
//$conf['redis_client_password'] = ';
$conf['redis_client_base'] = 0;
$conf['redis_client_interface'] = 'PhpRedis';
$conf['cache_backends'][] = "sites/all/modules/contrib/redis/redis.autoload.inc";
$conf['cache_default_class'] = 'Redis_Cache';
$conf['cache_class_cache_form'] = 'DrupalDatabaseCache';
$conf['lock_inc'] = "sites/all/modules/contrib/redis/redis.lock.inc";
$conf['path_inc'] = "sites/all/modules/contrib/redis/redis.path.inc";
For more information see Redis stack documentation.
Wodby environment¶
- Download and install redis module
- Make sure redis service enabled in your stack
- Additionally, for Drupal 8: enable redis integration under
[Instance] > Cache > Settings
page - That's it, all required configuration already provided in
wodby.settings.php
file
Local environment¶
- Download and install redis module
- Add the following lines to your
settings.php
file (make sure the path to redis module is correct):
For Drupal 8+:
$settings['redis.connection']['host'] = 'redis';
$settings['redis.connection']['port'] = '6379';
//$settings['redis.connection']['password'] = '';
$settings['redis.connection']['base'] = 0;
$settings['redis.connection']['interface'] = 'PhpRedis';
$settings['cache']['default'] = 'cache.backend.redis';
$settings['cache']['bins']['bootstrap'] = 'cache.backend.chainedfast';
$settings['cache']['bins']['discovery'] = 'cache.backend.chainedfast';
$settings['cache']['bins']['config'] = 'cache.backend.chainedfast';
$settings['container_yamls'][] = "modules/contrib/redis/example.services.yml";
For Drupal 7:
$conf['redis_client_host'] = 'redis';
$conf['redis_client_port'] = '6379';
//$conf['redis_client_password'] = ';
$conf['redis_client_base'] = 0;
$conf['redis_client_interface'] = 'PhpRedis';
$conf['cache_backends'][] = "sites/all/modules/contrib/redis/redis.autoload.inc";
$conf['cache_default_class'] = 'Redis_Cache';
$conf['cache_class_cache_form'] = 'DrupalDatabaseCache';
$conf['lock_inc'] = "sites/all/modules/contrib/redis/redis.lock.inc";
$conf['path_inc'] = "sites/all/modules/contrib/redis/redis.path.inc";
For more information see Redis stack documentation.
Rsyslog¶
Rsyslog can be used to stream your applications logs (watchdog). It's similar to using syslog, however there's no syslog in PHP container. Rsyslog will stream all incoming logs to a container output.
Here how you can use it with Monolog:
- Install monolog module. Make sure all dependencies being downloaded
- Add new handler at
monolog/monolog.services.yml
:monolog.handler.rsyslog: class: Monolog\Handler\SyslogUdpHandler arguments: ['rsyslog']
- Rebuild cache (
drush cr
) - Use
rsyslog
handler for your channels - Find your logs in rsyslog container output
Read Logging in Drupal 8 to learn more.
Solr¶
New Solr image
Since Drupal stacks 5.2.0+ Varnish image wodby/drupal-solr
has been replaced with wodby/solr
and $SOLR_DEFAULT_CONFIG_SET
, see versions matrix
See Solr for Drupal stack documentation.
SSHd¶
A duplicate of PHP container runs with SSH daemon (instead of FPM). You can find access information on [Instance] > Stack > SSH
Public SSH keys from your Wodby profile will be added automatically for all users that have access to an instance.
Varnish¶
New Varnish image
Since Drupal stacks 5.2.0+ Varnish image wodby/drupal-varnish
has been replaced with wodby/varnish
and $VARNISH_CONFIG_PRESET=drupal
You can use Varnish to cache dynamic pages and show pages to your visitors without any calls to Drupal (cache stored in memory).
Drupal 8/9¶
In Drupal 8/9 we recommend using Cache-Tags to clear caches:
- Download modules purge and varnish purger
- Enable the following modules: Varnish Purger Tags, Core tags queuer, Cron processor
- Go to
/admin/config/development/performance/purge
and create a new purger with typeVarnish Purger
- On a new purger edit page:
- Make sure the selected Type is
Tag
(default) - On Request tab specify hostname
varnish
, port6081
- On Headers tab add a new header with name
Cache-tags
and value[invalidation:expression]
- Make sure the selected Type is
- Save purger. Now with every cron run Varnish Purger will flush cache of pages with updated Cache Tags
- You can additionally enable Purge Drush module and add a cron job with a custom period that will flush cache (
drush p-queue-work
)
Drupal 7¶
- Install and enable varnish module (use the dev version). All required configuration for this module already provided in
wodby.settings.php
file - Go to
Home » Administration » Configuration » Development
page of Drupal website and - Check Cache pages for anonymous users
- Check Compress cached pages.
Check Aggregate and compress CSS files.
Check Aggregate JavaScript files.
Also, we recommend to install expire module to configure auto purge of pages when some content has been updated. After installation go to
Home » Administration » Configuration » System
and select External expiration at the "Module status" tab.
For more details see Varnish stack documentation
Webgrind¶
Webgrind allows you view and analyze Xdebug profiler output and generate call graphs for visualisation.
XHProf viewer¶
XHProf viewer allows you view and analyze XHProf traces output and generate call graphs for visualisation.