Install CiviCRM 5 with Drupal 8 using Lando

Submitted by christophe on Mon, 15/10/2018 - 22:01
CiviCRM Drupal 8

CiviCRM is an old Drupal 7 friend and its relationships with Drupal 8 are in a pretty good way. Let's make them meet the Composer template for Drupal projects, a widespread setup that stores the vendor directory outside of the docroot.
Lando will host the party by spinning up a local environment, however this method should be generalizable with any other development environment.

Refer to this previous post to setup Lando.


Get Drupal and install it

Create a Drupal project

composer create-project drupal-composer/drupal-project:8.x-dev civi-drupal --stability dev --no-interaction

Initialize Lando

cd civi-drupal
lando init --recipe drupal8 --webroot web

Give your app the CiviDrupal name then start Lando

 lando start

Finally, install Drupal

lando drush site-install standard --account-name=admin --account-pass=admin --db-url='mysql://drupal8:[email protected]/drupal8' --site-name=CiviDrupal

Your site should be available at


Get CiviCRM for Drupal 8

We will use the method provided by David Snopek in this gist with CiviCRM 5.6.0.

Run the following commands at the root of the civi-drupal directory.

# Set CiviCRM  version

# Repositories aren't inherited from requirements, so we have to put this one from civicrm-core/composer.json again
composer config repositories.zetacomponents-mail vcs

# Require civicrm-core at the requested version.
composer require "civicrm/civicrm-core:$CIVICRM_VERSION"

# Run 'bower install'
(cd vendor/civicrm/civicrm-core && bower install)

# Download the latest Drupal package to copy some stuff that's
# generated by the build and included in release tarballs.
wget -O /tmp/civicrm.tar.gz$CIVICRM_VERSION-drupal.tar.gz
tar -xzf /tmp/civicrm.tar.gz -C /tmp
# Copy the 3rd party dependencies. Should be done via Composer at a later stage.
cp -r /tmp/civicrm/packages vendor/civicrm/civicrm-core/
# Setup the civicrm-version.php
cat /tmp/civicrm/civicrm-version.php | sed -e 's/Drupal/Drupal8/' > vendor/civicrm/civicrm-core/civicrm-version.php
# Copy sql
cp -r /tmp/civicrm/sql vendor/civicrm/civicrm-core/
# Copy some misc other things
cp /tmp/civicrm/civicrm.config.php vendor/civicrm/civicrm-core/
cp /tmp/civicrm/CRM/Core/I18n/SchemaStructure.php vendor/civicrm/civicrm-core/CRM/Core/I18n/
cp /tmp/civicrm/install/langs.php vendor/civicrm/civicrm-core/install/
# Clean-up
rm -rf /tmp/civicrm.tar.gz /tmp/civicrm


Get Drupal 8 CiviCRM module

Get the module from GitHub. We will use the 5.7.x-dev that requires CiviCRM Core >=5.4.0

composer config repositories.civicrm-drupal vcs
composer require civicrm/civicrm-drupal-8:5.7.x-dev 

Note that we will not use the repository but this one


Install CiviCRM

Go to /admin/modules and enable the CiviCRM Core module.

CiviCRM Core Drupal module

You will have this error while trying to access /civicrm in the browser.

Sorry, due to an error, we are unable to fulfill your request at the moment.
You may want to contact your administrator or service provider with more details about what action you were performing when this occurred.
DB Constraint Violation - contact_id should possibly be marked as mandatory for DashboardContact,create API.
If so, please raise a bug report.

To get rid of it, go back to Drupal, logout and login again. See CRM-19878.


Allow CiviCRM to be accessed from the docroot

CiviCRM will need to access its Javascript/CSS assets, so we will symlink the civicrm-core directory in the Drupal libraries directory.

mkdir web/libraries
(cd web/libraries/ && ln -s ../../vendor/civicrm/civicrm-core civicrm) 

Configure then the CiviCRM Resource URL at /civicrm/admin/setting/url?reset=1, set the following value:


Thanks to klaas for the cms.root token!


Allow CiviCRM to access the extern directory

The scripts from this directory have to bee accessed directly, they are used for e.g. the CiviMail click through counters (url.php). Direct access to these scripts will be prevented by the default .htaccess directives.

CiviCRM extern directory

Make the scripts available by including this .htaccess override in the /libraries/civicrm/extern/ directory:

<IfModule mod_rewrite.c>
  RewriteEngine Off

Let then know civicrm.config.php where to find the civicrm.settings.php file (/app/web/sites/default/civicrm.settings.php in this example).


Execute scheduled Jobs via the cron

Install CV (the CiviCRM CLI) then execute this command via a system cron, in the docroot.

cv api Job.execute


Happy CiviCRM hacking!


Before the lando drush command you need to do a

- lando composer install
- lando composer drupal:scaffold

otherwise drush and drupal are not available

The composer create-project command will composer install for you. If you clone the Composer template straight from a repository you will have to take care of these extra steps, still unsure about the composer drupal:scaffold. In this case I can usually, just composer install then drush site-install.

Let then know civicrm.config.php where to find the civicrm.settings.php file (/app/web/sites/default/civicrm.settings.php in this example).

There's a lot in that file. Since the topic is civicrm with lando lando the exact change can be done here 'cause all followers use lando as well then.

CiviCRM will not find its settings file when it is accessed via /libraries/civicrm for another purpose than the Javascript / CSS assets (so basically, the files from the extern directory). You will have this error while e.g. clicking on a link enclosed in a mail sent via CiviMail. The following url /libraries/civicrm/extern/url.php?u=1&qid=1 will yeld

Warning: include_once(/app/vendor/civicrm/civicrm-core/../../../../default/civicrm.settings.php): failed to open stream

By default,  CiviCRM will look in the directories described in the comments from civicrm.config.php. On line 116, the $settingsFile = civicrm_conf_init() . '/civicrm.settings.php'; needs to get the civicrm.settings.php file in the right location, in this example /app/web/sites/default/civicrm.settings.php.

To comply to every environment + vendor or libraries access, it will need a patch that can be then included via your composer.json, so it can be applied while preparing a build for the deployment on other environments.


Some more feedback about the /extern directory, this time for the cron.

If we want to execute the CiviCRM cron from the outside, there are a few options

One of them is to call /libraries/civicrm/bin/cron.php

The following call with the described setup returns an error due to the Drupal container.
A workaround could be to iterate through the active Jobs from the API, but there are probably much cleaner options.

#!/usr/bin/env bash


POST_AUTH="-d name=${CIVI_USER} -d pass=${CIVI_PASS} -d key=${SITE_KEY}"
POST_JOBS="-d job=process_mailing"

curl -s civicrm.cronjob.out ${POST_AUTH} ${POST_JOBS} ${CIVI_CRON}


Fatal error: Uncaught Drupal\Core\DependencyInjection\ContainerNotInitializedException: \Drupal::$container is not initialized yet. \Drupal::setContainer() must be called with a real container. in /app/web/core/lib/Drupal.php on line 130

Drupal\Core\DependencyInjection\ContainerNotInitializedException: \Drupal::$container is not initialized yet. \Drupal::setContainer() must be called with a real container. in /app/web/core/lib/Drupal.php on line 130

Call Stack:
    0.0027     363056   1. {main}() /app/vendor/civicrm/civicrm-core/bin/cron.php:0
    3.0671    2288728   2. CRM_Utils_System::authenticateScript() /app/vendor/civicrm/civicrm-core/bin/cron.php:34
    3.0671    2288728   3. CRM_Utils_System::authenticate() /app/vendor/civicrm/civicrm-core/CRM/Utils/System.php:618
    3.0715    2302720   4. CRM_Utils_System_Drupal8->authenticate() /app/vendor/civicrm/civicrm-core/CRM/Utils/System.php:677
    3.0744    2303280   5. Drupal::service() /app/vendor/civicrm/civicrm-core/CRM/Utils/System/Drupal8.php:336
    3.0745    2303280   6. Drupal::getContainer() /app/web/core/lib/Drupal.php:158


Add new comment

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.