Goal
To demonstrate how a “compile to static” tool, such as the Drupal Tome module, can be used on Platform.sh using multi-application configurations.
Assumptions
- Your default/production git branch is named
main
Preparation
This tutorial will start from a basic Drupal 8 Composer site. However, it will be easier to start from an empty Git repository. It can be done from a Drupal 8 template site but that requires moving a number of hidden files and is therefore more prone to error.
You will need:
- A newly created empty site on Platform.sh.
- Git and SSH installed locally.
Problems
How can you serve two closely related sites off of the same project?
How can static site generation work in production, rather than compiling locally or during build?
Steps
1. Create an empty working directory
On your local system, create an empty directory for your project and initialize it for Git. Eg:
mkdir project
cd project
git init
2. Download Drupal 8
Clone the Drupal 8 Platform.sh template into your project, then remove the git repository from it.
git clone https://github.com/platformsh-templates/drupal8.git drupal --depth=1
rm -rf drupal/.git
That Git repository is what the Drupal 8 template in the new project wizard populates from. The above commands are essentially what the new project wizard does, although it does not use a subdirectory.
2. Move the .platform
definition files to the repo root
The .platform
directory must be in the repository root, so move it there:
mv drupal/.platform .
The .platform.app.yaml
file stays in the drupal
directory so that the drupal
directory becomes an application container itself. That will let you create another directory for the static site.
3. Add a network-storage
service
Open .platform/services.yaml
in your favorite text editor and add the following:
files:
type: network-storage:1.0
disk: 512
That creates a new network-storage
service named files
. Files there can be shared between the two application containers.
4. Update Drupal mounts
Open drupal/.platform.app.yaml
in your favorite text editor and update the mounts
section to be as follows:
mounts:
'/web/sites/default/files':
source: local
source_path: files
'/tmp':
source: local
source_path: tmp
'/private':
source: local
source_path: private
'/.drush':
source: local
source_path: drush
'/drush-backups':
source: local
source_path: drush-backups
'/.console':
source: local
source_path: console
'/content':
source: local
source_path: content
'/config':
source: local
source_path: config
'/static':
source: service
service: files
source_path: static
Most of those are simply converting the normal Drupal mounts to the new-style mount syntax. The most important are the final three paths. Tome will automatically run a config-export every time configuration is exported, so the /config
directory must be writeable. It will also write out a JSON version of all content as it is created and edited to /content
. The /static
directory is where you’ll instruct Tome to write out the static version of the site.
Of particular note, the /static
mount uses the network storage service, not the local file system. That will make it available to other application containers.
Note: Because these directories are writeable, they will not be tracked in Git. That includes configuration exports, which will not be deployable via Git in this setup.
5. Install Drupal Tome module
Run:
cd drupal
composer require drupal/tome
to add the Tome module. (It’s actually a suite of modules). You’ll enable it later once the code is deployed. Once that’s done return to the repository root directory:
cd ..
6. Set Tome export location
Modify the drupal/web/sites/default/settings.php
file. Add the following line at the location of your choice:
$settings['tome_static_directory'] = '../static/html';
That will set the Tome export directory to the /static/html
directory, which is inside the writeable mount you created above. Because Tome completely removes the output directory before each rebuild it needs to be in a subdirectory of the mount.
7. Disable allowed-host checking
In the drupal/web/sites/default/settings.platformsh.php
file, look for a comment line that reads // Set trusted hosts based on Platform.sh routes
. The code block below that configures the hosts that Drupal is allowed to requests for. Normally it is a security feature, however, on Platform.sh Professional the domain is already mangled by the router and will always be a “safe” domain. That makes this code block unnecessary. (It is included in the template only for Platform.sh Enterprise.)
The Tome module’s export functionality, however, is incompatible with this code block as it will need to use the un-prefixed domain for the export. It is safe to simply remove/comment out this entire block. Alternatively, just comment out the last line that sets $settings['trusted_host_patterns']
.
8. Add a static site application to serve files
Create a new directory called static
, and inside it create a .platform.app.yaml
file. Give it the following contents:
# Note that this is different than what the Drupal site is called.
name: 'static'
# The type here doesn't really matter since it's just a static site.
type: 'php:7.3'
# This must be set, but can be set at the minimum value.
disk: 16
mounts:
'static':
source: service
service: files
source_path: static
web:
locations:
'/':
root: 'static/html'
index: ['index.html']
scripts: false
allow: true
That file is all that is needed to create a second application container. This container will be called static
, and will mount the same network storage directory as the app
container that holds the Drupal site. It will be empty aside from that mount, which is fine as the mount is where the files will be served from. Note that the web root is the static/html
directory, not static
itself, as Tome was configured above to write files to static/html
.
9. Update routes
Open .platform/routes.yaml
in your editor. Update the route definitions to be as follows:
"https://drupal.{default}/":
type: upstream
upstream: "app:http"
cache:
enabled: true
# Base the cache on the session cookie and custom Drupal cookies. Ignore all other cookies.
cookies: ['/^SS?ESS/', '/^Drupal.visitor/']
"https://{default}/":
type: upstream
upstream: "static:http"
(You can also include a www
redirect route if you want, but that is unnecessary.) This configuration creates two routes: The drupal.
subdomain will be where the Drupal site lives, and it will run as any other Drupal site. The main domain (and/or www.
subdomain if desired) will be served by the static
application.
Once the configuration is complete and you are happy with the result, you will most likely want to come back and add HTTP caching to the static
route, including a default_ttl
.
10. Commit and push
Commit all of the files you just created to Git:
git add .
git commit -m "Setting up Tome"
Now add a remote for your empty Platform.sh project. The Git URL can be found in your Management Console in the browser. The command will be something along the lines of:
git remote add platform bzh2mp6iabike@git.eu-3.platform.sh:bzh2mp6iabike.git
And then push all of the code to the platform
remote:
git push -u platform main
If everything is setup correctly it will push and deploy a two-application cluster, containing the Drupal container, static container, and the MariaDB and Redis services used by Drupal itself.
11. Install Drupal and Tome
Once deployment is finished it will show you the domain names that are served. Go to the drupal.
domain in your browser. Complete the Drupal installation process as normal.
Once Drupal is installed, select “Extend” in the menu and enable the “Tome” module. That will also enable several sub-modules. You don’t need to create any content at this point, but if you do it will make the demonstration of Tome’s functionality more interesting.
12. Export the site
Go to /admin/config/tome/static/generate
in your Drupal site. The generation form will ask you for the domain to generate for; give it the unprefixed domain (which could be a dev domain or your production domain, depending on whether or not you’ve gone live yet). Click “Submit”.
Tome will generate a static version of your site as it is seen by an anonymous user. (Which means you must allow anonymous user to see the site.) The process takes anywhere from a few seconds to a few minutes depending on how much content you have. As the site was only just created it should be quite fast.
Now go to the unprefixed version of your site (the domain without drupal.
) in your favorite browser. You should see the anonymous version of your site, now served entirely as static files.
Conclusion
In this tutorial, you have seen how to:
- Create a multi-application project on Platform.sh.
- Use
network-storage
to share content between sites. - Configure an application to serve static files.
All of which can be applied to other configurations if needed. Note that in the case of Tome the generation process does delete files first, so it is recommended to configure caching at the router level for the static container to minimize any disruption to the site as it is being regenerated.