In this guide I will:
- Explain Why It Made Sense for Us to Use Drupal 9 on Heroku and Why It Might Not Make Sense for You
- Create a New Drupal 9 Project That is Ready to Patch
- Install Drupal Locally using PostgreSQL on Lando
- Setup a cloud file system module (Flysystem) for system files (in part 2)
- Setup a cloud file system module (Cloudinary) for user contributed files (in part 2)
- Deploy to Heroku (in part 2)
After a decade of using a utility knife of a CMS that was Drupal 5, 6 and 7 to create solutions for hundreds of different use cases, I really thought I had created my last Drupal site after DrupalCon Nashville back in 2018. At the time I managed a development team responsible for more than ~1000 Drupal 7 for the University of Colorado, but I couldn’t get excited about a complete rewrite of the Web Express install profile and all the custom modules and configuration that made offering Drupal as a Service cost effectively. I begged someone to change my views on Drupal 8 in Nashville, but left Nashville disappointed and disillusioned about who Drupal was for.
Instead of continuing to shake my first at the sky, I took an opportunity to transition to a new role at the University of Colorado focusing on CRM/Salesforce solutions. In my new role with my new team, suggest that a logical path forward for this team for the Drupal 7 Commerce solution they had been using to process millions of donors in donations each year was to host smaller applications that integrated tightly with Salesforce on Heroku. Heroku can be expensive, but it provides a nice mix of preconfigured buildpacks and devops build, test and review tools perfect for small development teams without dedicated system admin or devops teams.
Because we were already hosting other applications on Heroku, we thought we’d at least try running the current release of Drupal 9 on Heroku. With a few exceptions, it worked surprising well. Federico Martínez’s posts on getting Drupal 8 running on Heroku really helped, but there are some important changes between versions 8 and 9. I’ve also taken Federico's approach further with a local deployment experience Drupal developers would be more familiar with.
Kristen Pol@kristen_pol#Drupal 9 hosting providers need to step up their game.
@getpantheon doesn't have 9 as an option OOTB.
@acquia look like it was hung when I tried to do the trial.
@platformsh went to white screen after registering.
We need solid tools so people want to choose Drupal!20:06 PM - 17 Sep 2020
DISCLAIMER: If you aren’t running other applications on Heroku, this is unlikely to your best or most cost effective solution for hosting Drupal. While Kristen ran into issues with Platform.sh, I personally think this is best option if you are running Drupal and other modern, PHP applications. If you are only running Drupal, I'd wait to see what Pantheon has to offer with Drupal 9.1.
If you aren’t familiar with using Composer for package management, it’s similar to npm. Assuming you have Composer installed, typing these commands into your terminal will quickly copy these projects and all their dependencies to you local machine.
composer create-project drupal/recommended-project drupal-on-heroku cd drupal-on-heroku composer require drush/drush composer require drupal/core-composer-scaffold composer require cweagans/composer-patches
At this point we’ve told Composer what code we want to include in the project. Including cweagans/composer-patches gives use the ability to patch core and contrib which we will need to get Flysystem and Cloudinary working in Drupal 9.
In Federico’s example, he used
php -S 127.0.0.1:8888 -t web to spin up a local PHP server and install Drupal using the UI. We’re going to install Drupal using Lando and Drush instead.
If you haven't already installed Lando, follow Lando official guide for your platform first.
? From where should we get your app's codebase? current working directory ? What recipe do you want to use? drupal9 ? Where is your webroot relative to the init destination? web ? What do you want to call this app? drupal-on-heroku
Before we start Lando, we need to make a few changes in the .lando.yml and create a defaults.env that we’ll use to mimic Heroku’s Config Vars.
Open .lando.yml with your editor of choice. If you followed the prompts correctly, you should see something like this.
name: d9-test recipe: drupal9 config: webroot: web
Replace that with the following configuration.
name: d9 recipe: drupal9 config: webroot: web php: 7.4 xdebug: true services: postgres: type: postgres:12 portforward: true creds: database: drupal9 events: post-start: # Sleep for a few seconds since Drush load appears to be a race condition. - sleep 5 - drush status # Turn on dev modules excluded from config export. - drush en config dblog devel devel_generate update webprofiler --debug - drush cr excludes: - vendor - web/core - web/private env_file: - defaults.env
Create defaults.env in the project root directory with your editor of choice. Add the following variable.
Create or modify your .gitignore to add defaults.env. That isn't as important for this step, but it will be important that you do not reveal your Cloudinary or S3 configuration in future once those have been added to the defaults.env.
We are finally ready to run
You will likely get this error.
[Symfony\Component\Console\Exception\CommandNotFoundException] Command pm:enable was not found. Drush was unable to query the database. As a result, many commands are unavailable. Re-run your command with --debug to see relevant log messages.
lando info to confirm that the default Postgres port is used on your local configuration.
Run drush si –db-url=pgsql://postgres:@postgres:5432/drupal.
After the install is finished, we need to update the settings.php to parse the database values from the environmental variables. Like many could hosts, Heroku can swap your applications between database instances as needed. We this happens, database credentials in the Config Vars are automatically updated. The database connection credentials are also different in each Review App, staging and production instance. As a result, hard coding these values in a settings.php file (or letting the Drupal install do this) is going to cause problems.
Open web/sites/default/settings.php in your editor of choice and update the database credentials used during the install to this.
// Add database credentials from parsed environmental variable. // This also works for Lando since it uses the same DATABASE_URL variable. $parsed_creds = parse_url(getenv('DATABASE_URL')); // Need to correct scheme based on Drupal naming conventions. $scheme = $parsed_creds['scheme'] == 'postgres' ? 'pgsql' : $parsed_creds['scheme']; $databases['default']['default'] = [ 'database' => explode('/', $parsed_creds['path']), 'username' => $parsed_creds['user'], 'password' => $parsed_creds['pass'], 'prefix' => '', 'host' => $parsed_creds['host'], 'port' => $parsed_creds['port'], 'namespace' => 'Drupal\\Core\\Database\\Driver\\' . $scheme, 'driver' => $scheme, ];
Congratulations! You now have a local copy of Drupal 9 running with a Heroku friendly configuration that can be deployed on Heroku. In the next part, I will walk through how to configure Flysystem and Cloudinary with Heroku's Addons for those services.