PHP

Last updated 2nd June 2022

Supported versions

Grid
7.3
7.4
8.0
8.1

Deprecated versions

Grid
5.4
5.5
5.6
7.0
7.1
7.2

Alternate start commands

PHP is most commonly run in a CGI mode, using PHP-FPM. That's the default on Web PaaS. However, you can also start alternative processes if desired, such as if you're running an async PHP daemon, a thread-based worker process, or something similar. To do so, specify an alternative start command in platform.app.yaml, similar to the following:

web:
    commands:
        start: php run.php
    upstream:
            socket_family: tcp
            protocol: http

The above configuration executes the run.php script in the application root when the container starts using the PHP-CLI SAPI, ust before the deploy hook runs but does not launch PHP-FPM.

It also tells the front-controller (Nginx) to connect to your application via a TCP socket, which is specified in the PORT environment variable. Note that the start command must run in the foreground.

If not specified, the effective default start command varies by PHP version:

  • On PHP 5.x, it's /usr/sbin/php5-fpm.
  • On PHP 7.0, it's /usr/sbin/php-fpm7.0.
  • On PHP 7.1, it's /usr/sbin/php-fpm7.1-zts.
  • On PHP 7.2, it's /usr/sbin/php-fpm7.2-zts.
  • On PHP 7.3, it's /usr/sbin/php-fpm7.3-zts.
  • On PHP 7.4, it's /usr/sbin/php-fpm7.4-zts.

While you can call it manually that's generally not necessary. Note that PHP-FPM cannot run simultaneously along with another persistent process (such as ReactPHP or Amp). If you need both, they have to run in separate containers.

Expanded dependencies

In addition to the standard dependencies format, it's also possible to specify alternative repositories for use by Composer. The standard format:

dependencies:
    php:
        "platformsh/client": "2.x-dev"

is equivalent to composer require platform/client 2.x-dev. You can also specify explicit require and repositories blocks:

dependencies:
    php:
        require:
            "platformsh/client": "2.x-dev"
        repositories:
            - type: vcs
              url: "git@github.com:platformsh/platformsh-client-php.git"

That would install platformsh/client from the alternate repository specified, as a global dependency. In other words, it's equivalent to the following composer.json file:

{
    "repositories": [
        {
            "type": "vcs",
            "url":  "git@github.com:platformsh/platformsh-client-php.git"
        }
    ],
    "require": {
        "platformsh/client": "2.x-dev"
    }
}

That allows you to install a forked version of a global dependency from a custom repository.

Build flavor

PHP images use the composer build flavor by default, which runs composer --no-ansi --no-interaction install --no-progress --prefer-dist --optimize-autoloader if a composer.json file is detected.

Note that by default, all PHP containers include the latest Composer 1.x release. If you wish to use Composer 2.x, add it as a dependency:

dependencies:
    php:
        composer/composer: '^2'

OPcache preloading

From PHP 7.4, you can use OPcache preloading, which allows you to load selected files into shared memory when PHP-FPM starts. That means functions and classes in those files are always available and don't need to be autoloaded, at the cost of any changes to those files requiring a PHP-FPM restart.

Since PHP-FPM restarts on each new deploy, this feature is a major win on Web PaaS and we recommend using it aggressively.

To enable preloading, add a php.ini value that specifies a preload script. Any php.ini mechanism ini works, but using a variable in .platform.app.yaml is the recommended approach:

variables:
    php:
        opcache.preload: 'preload.php'

The opcache.preload value is evaluated as a file path relative your app configuration. It may be any PHP script that calls opcache_compile_file().

The following example preloads all .php files anywhere in the vendor directory:

<?php
$directory = new RecursiveDirectoryIterator(getenv('PLATFORM_APP_DIR') . '/vendor');
$iterator = new RecursiveIteratorIterator($directory);
$regex = new RegexIterator($iterator, '/^.+\.php$/i', RecursiveRegexIterator::GET_MATCH);

foreach ($regex as $key => $file) {
    // This is the important part!
    opcache_compile_file($file[0]);
}

Preloading all .php files may not be optimal for your application and may even introduce errors. Your application framework may provide recommendations or a pre-made preload script to use instead. You have to determine the optimal preloading strategy for your situation.

Preloading and dependencies

Your preload script runs each time PHP-FPM restarts, including during your build. This means it runs before your dependencies have been installed (such as with Composer).

If your preload script uses require for dependencies, it fails during the build because the dependencies aren't yet present.

To resolve this, you have two options:

  • Have your script include dependencies instead of require and fail gracefully if the dependencies aren't there.
  • Enable preloading with a variable that isn't available during the build. Then preloading happens only on deploy.

FFI

PHP 7.4 introduced support for Foreign Function Interfaces (FFI), which allows user-space code to bridge to existing C-ABI-compatible libraries. FFI is fully supported on Web PaaS.

Note: FFI is only intended for advanced use cases, and is rarely a net win for routine web requests. Use with caution.

There are a few steps to leveraging FFI:

1. Enable the FFI extension in .platform.app.yaml:

runtime:
    extensions:
        - ffi

2. Specify a preload file in which you can call FFI::load().

Using FFI::load() in preload is considerably faster than loading the linked library on each request or script run.

3. Ensure the library is available locally, but not in a web-accessible directory.

.so files may included in your repository, downloaded in your build hook, or compiled in your build hook. If compiling C code, gcc is available by default. If compiling Rust code, you can download the Rust compiler in the build hook.

4. Running FFI from the command line.

You need to enable the OPcache for command line scripts in addition to the preloader. The standard pattern for the command would be php -d opcache.preload="your-preload-script.php" -d opcache.enable_cli=true your-cli-script.php.

A working FFI example is available online for both C and Rust.

Debug PHP-FPM

If you want to inspect what's going on with PHP-FPM, you can install this small CLI:

dependencies:
    php:
        wizaplace/php-fpm-status-cli: "^1.0"

Then when you are connected to your project over SSH, you can run:

$ php-fpm-status --socket=unix://$SOCKET --path=/-/status --full

Accessing services

To access various services with PHP, see the following examples. The individual service pages have more information on configuring each service.

<?php

declare(strict_types=1);

use Elasticsearch\ClientBuilder;
use Platformsh\ConfigReader\Config;

// Create a new config object to ease reading the Web PaaS environment variables.
// You can alternatively use getenv() yourself.
$config = new Config();

// Get the credentials to connect to the Elasticsearch service.
$credentials = $config->credentials('elasticsearch');

try {
    // The Elasticsearch library lets you connect to multiple hosts.
    // On Web PaaS Standard there is only a single host so just
    // register that.
    $hosts = [
        [
            'scheme' => $credentials['scheme'],
            'host' => $credentials['host'],
            'port' => $credentials['port'],
        ]
    ];

    // Create an Elasticsearch client object.
    $builder = ClientBuilder::create();
    $builder->setHosts($hosts);
    $client = $builder->build();

    $index = 'my_index';
    $type = 'People';

    // Index a few document.
    $params = [
        'index' => $index,
        'type' => $type,
    ];

    $names = ['Ada Lovelace', 'Alonzo Church', 'Barbara Liskov'];

    foreach ($names as $name) {
        $params['body']['name'] = $name;
        $client->index($params);
    }

    // Force just-added items to be indexed.
    $client->indices()->refresh(array('index' => $index));


    // Search for documents.
    $result = $client->search([
        'index' => $index,
        'type' => $type,
        'body' => [
            'query' => [
                'match' => [
                    'name' => 'Barbara Liskov',
                ],
            ],
        ],
    ]);

    if (isset($result['hits']['hits'])) {
        print <<<TABLE
<table>
<thead>
<tr><th>ID</th><th>Name</th></tr>
</thead>
<tbody>
TABLE;
        foreach ($result['hits']['hits'] as $record) {
            printf("<tr><td>%s</td><td>%s</td></tr>\n", $record['_id'], $record['_source']['name']);
        }
        print "</tbody>\n</table>\n";
    }

    // Delete documents.
    $params = [
        'index' => $index,
        'type' => $type,
    ];

    $ids = array_map(function($row) {
        return $row['_id'];
    }, $result['hits']['hits']);

    foreach ($ids as $id) {
        $params['id'] = $id;
        $client->delete($params);
    }

} catch (Exception $e) {
    print $e->getMessage();
}
<?php

declare(strict_types=1);

use Platformsh\ConfigReader\Config;

// Create a new config object to ease reading the Web PaaS environment variables.
// You can alternatively use getenv() yourself.
$config = new Config();

// Get the credentials to connect to the Memcached service.
$credentials = $config->credentials('memcached');

try {
    // Connecting to Memcached server.
    $memcached = new Memcached();
    $memcached->addServer($credentials['host'], $credentials['port']);
    $memcached->setOption(Memcached::OPT_BINARY_PROTOCOL, true);

    $key = "Deploy day";
    $value = "Friday";

    // Set a value.
    $memcached->set($key, $value);

    // Read it back.
    $test = $memcached->get($key);

    printf('Found value <strong>%s</strong> for key <strong>%s</strong>.', $test, $key);

} catch (Exception $e) {
    print $e->getMessage();
}
<?php

declare(strict_types=1);

use Platformsh\ConfigReader\Config;
use MongoDB\Client;

// Create a new config object to ease reading the Web PaaS environment variables.
// You can alternatively use getenv() yourself.
$config = new Config();

// The 'database' relationship is generally the name of primary database of an application.
// It could be anything, though, as in the case here here where it's called "mongodb".
$credentials = $config->credentials('mongodb');

try {

    $server = sprintf('%s://%s:%s@%s:%d/%s',
        $credentials['scheme'],
        $credentials['username'],
        $credentials['password'],
        $credentials['host'],
        $credentials['port'],
        $credentials['path']
    );

    $client = new Client($server);
    $collection = $client->main->starwars;

    $result = $collection->insertOne([
        'name' => 'Rey',
        'occupation' => 'Jedi',
    ]);

    $id = $result->getInsertedId();

    $document = $collection->findOne([
        '_id' => $id,
    ]);

    // Clean up after ourselves.
    $collection->drop();

    printf("Found %s (%s)<br />\n", $document->name, $document->occupation);

} catch (\Exception $e) {
    print $e->getMessage();
}
<?php

declare(strict_types=1);

use Platformsh\ConfigReader\Config;

// Create a new config object to ease reading the Web PaaS environment variables.
// You can alternatively use getenv() yourself.
$config = new Config();

// The 'database' relationship is generally the name of primary SQL database of an application.
// That's not required, but much of our default automation code assumes it.
$credentials = $config->credentials('database');

try {
    // Connect to the database using PDO.  If using some other abstraction layer you would
    // inject the values from $database into whatever your abstraction layer asks for.
    $dsn = sprintf('mysql:host=%s;port=%d;dbname=%s', $credentials['host'], $credentials['port'], $credentials['path']);
    $conn = new \PDO($dsn, $credentials['username'], $credentials['password'], [
        // Always use Exception error mode with PDO, as it's more reliable.
        \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
        // So we don't have to mess around with cursors and unbuffered queries by default.
        \PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => TRUE,
        // Make sure MySQL returns all matched rows on update queries including
        // rows that actually didn't have to be updated because the values didn't
        // change. This matches common behavior among other database systems.
        \PDO::MYSQL_ATTR_FOUND_ROWS => TRUE,
    ]);

    // Creating a table.
    $sql = "CREATE TABLE People (
      id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
      name VARCHAR(30) NOT NULL,
      city VARCHAR(30) NOT NULL
      )";
    $conn->query($sql);

    // Insert data.
    $sql = "INSERT INTO People (name, city) VALUES 
        ('Neil Armstrong', 'Moon'), 
        ('Buzz Aldrin', 'Glen Ridge'), 
        ('Sally Ride', 'La Jolla');";
    $conn->query($sql);

    // Show table.
    $sql = "SELECT * FROM People";
    $result = $conn->query($sql);
    $result->setFetchMode(\PDO::FETCH_OBJ);

    if ($result) {
        print <<<TABLE
<table>
<thead>
<tr><th>Name</th><th>City</th></tr>
</thead>
<tbody>
TABLE;
        foreach ($result as $record) {
            printf("<tr><td>%s</td><td>%s</td></tr>\n", $record->name, $record->city);
        }
        print "</tbody>\n</table>\n";
    }

    // Drop table
    $sql = "DROP TABLE People";
    $conn->query($sql);

} catch (\Exception $e) {
    print $e->getMessage();
}
<?php

declare(strict_types=1);

use Platformsh\ConfigReader\Config;

// Create a new config object to ease reading the Web PaaS environment variables.
// You can alternatively use getenv() yourself.
$config = new Config();

// The 'database' relationship is generally the name of primary SQL database of an application.
// It could be anything, though, as in the case here here where it's called "postgresql".
$credentials = $config->credentials('postgresql');

try {
    // Connect to the database using PDO.  If using some other abstraction layer you would
    // inject the values from $database into whatever your abstraction layer asks for.
    $dsn = sprintf('pgsql:host=%s;port=%d;dbname=%s', $credentials['host'], $credentials['port'], $credentials['path']);
    $conn = new \PDO($dsn, $credentials['username'], $credentials['password'], [
        // Always use Exception error mode with PDO, as it's more reliable.
        \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
        // So we don't have to mess around with cursors and unbuffered queries by default.
    ]);

    $conn->query("DROP TABLE IF EXISTS People");

    // Creating a table.
    $sql = "CREATE TABLE IF NOT EXISTS People (
      id SERIAL PRIMARY KEY,
      name VARCHAR(30) NOT NULL,
      city VARCHAR(30) NOT NULL
      )";
    $conn->query($sql);

    // Insert data.
    $sql = "INSERT INTO People (name, city) VALUES
        ('Neil Armstrong', 'Moon'),
        ('Buzz Aldrin', 'Glen Ridge'),
        ('Sally Ride', 'La Jolla');";
    $conn->query($sql);

    // Show table.
    $sql = "SELECT * FROM People";
    $result = $conn->query($sql);
    $result->setFetchMode(\PDO::FETCH_OBJ);

    if ($result) {
        print <<<TABLE
<table>
<thead>
<tr><th>Name</th><th>City</th></tr>
</thead>
<tbody>
TABLE;
        foreach ($result as $record) {
            printf("<tr><td>%s</td><td>%s</td></tr>\n", $record->name, $record->city);
        }
        print "</tbody>\n</table>\n";
    }

    // Drop table.
    $sql = "DROP TABLE People";
    $conn->query($sql);

} catch (\Exception $e) {
    print $e->getMessage();
}
<?php

declare(strict_types=1);

use Platformsh\ConfigReader\Config;
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;

// Create a new config object to ease reading the Web PaaS environment variables.
// You can alternatively use getenv() yourself.
$config = new Config();

// Get the credentials to connect to the RabbitMQ service.
$credentials = $config->credentials('rabbitmq');

try {

    $queueName = 'deploy_days';

    // Connect to the RabbitMQ server.
    $connection = new AMQPStreamConnection($credentials['host'], $credentials['port'], $credentials['username'], $credentials['password']);
    $channel = $connection->channel();

    $channel->queue_declare($queueName, false, false, false, false);

    $msg = new AMQPMessage('Friday');
    $channel->basic_publish($msg, '', 'hello');

    echo "[x] Sent 'Friday'<br/>\n";

    // In a real application you't put the following in a separate script in a loop.
    $callback = function ($msg) {
        printf("[x] Deploying on %s<br />\n", $msg->body);
    };

    $channel->basic_consume($queueName, '', false, true, false, false, $callback);

    // This blocks on waiting for an item from the queue, so comment it out in this demo script.
    //$channel->wait();

    $channel->close();
    $connection->close();

} catch (Exception $e) {
    print $e->getMessage();
}
<?php

declare(strict_types=1);

use Platformsh\ConfigReader\Config;

// Create a new config object to ease reading the Web PaaS environment variables.
// You can alternatively use getenv() yourself.
$config = new Config();

// Get the credentials to connect to the Redis service.
$credentials = $config->credentials('redis');

try {
    // Connecting to Redis server.
    $redis = new Redis();
    $redis->connect($credentials['host'], $credentials['port']);

    $key = "Deploy day";
    $value = "Friday";

    // Set a value.
    $redis->set($key, $value);

    // Read it back.
    $test = $redis->get($key);

    printf('Found value <strong>%s</strong> for key <strong>%s</strong>.', $test, $key);

} catch (Exception $e) {
    print $e->getMessage();
}
<?php
declare(strict_types=1);

use Platformsh\ConfigReader\Config;
use Solarium\Client;

// Create a new config object to ease reading the Web PaaS environment variables.
// You can alternatively use getenv() yourself.
$config = new Config();

// Get the credentials to connect to the Solr service.
$credentials = $config->credentials('solr');

try {

    $config = [
        'endpoint' => [
            'localhost' => [
                'host' => $credentials['host'],
                'port' => $credentials['port'],
                'path' => "/" . $credentials['path'],
            ]
        ]
    ];

    $client = new Client($config);

    // Add a document
    $update = $client->createUpdate();

    $doc1 = $update->createDocument();
    $doc1->id = 123;
    $doc1->name = 'Valentina Tereshkova';

    $update->addDocuments(array($doc1));
    $update->addCommit();

    $result = $client->update($update);
    print "Adding one document. Status (0 is success): " .$result->getStatus(). "<br />\n";

    // Select one document
    $query = $client->createQuery($client::QUERY_SELECT);
    $resultset = $client->execute($query);
    print  "Selecting documents (1 expected): " .$resultset->getNumFound() . "<br />\n";

    // Delete one document
    $update = $client->createUpdate();

    $update->addDeleteById(123);
    $update->addCommit();
    $result = $client->update($update);
    print "Deleting one document. Status (0 is success): " .$result->getStatus(). "<br />\n";

} catch (Exception $e) {
    print $e->getMessage();
}

Composer library

Runtime configuration

It's possible to change the PHP-FPM runtime configuration via the runtime property in your app configuration. See that reference for details on what can be changed.

Project templates

Gatsby with WordPress

image

This template builds a two application project to deploy the Headless CMS pattern using Gatsby as its frontend and WordPress for its backend. The gatsby-source-wordpress source plugin is used to pull data from WordPress during the post_deploy hook into the Gatsby Data Layer and build the frontend site. Gatsby utilizes the Web PaaS Configuration Reader library for Node.js to define the backend data source in its configuration. It is intended for you to use as a starting point and modify for your own needs.

Note that after you have completed the WordPress installation, the project will require a redeploy to build and deploy Gatsby for the first time. See the included README's post-install section for details.

Gatsby is a free and open source framework based on React that helps developers build statically-generated websites and apps, and WordPress is a blogging and lightweight CMS written in PHP.

Features

  • Node.js 14
  • PHP 7.4
  • MariaDB 10.4
  • Automatic TLS certificates
  • npm-based build for Gatsby
  • Composer-based build for WordPress
  • Multi-app configuration
  • Delayed SSG build (post deploy hook)

View the repository on GitHub.

Drupal 8 Multisite

image

This template builds Drupal 8 in a multisite configuration using the "Drupal Recommended" Composer project. It is pre-configured to use MariaDB and Redis for caching. The Drupal installer will skip asking for database credentials as they are already provided.

It also includes instructions and a script to help with setting up additional multisite instances, although depending on your particular needs it may require some customization.

Drupal is a flexible and extensible PHP-based CMS framework capable of hosting multiple sites on a single code base.

Features

  • PHP 7.4
  • MariaDB 10.4
  • Redis 6
  • Drush and Drupal Console included
  • Pre-configured for multiple sites
  • Automatic TLS certificates
  • Composer-based build

View the repository on GitHub.

Backdrop

image

This template deploys a Backdrop CMS site, with the entire site committed to Git. It comes configured for MariaDB, the most popular database used with Backdrop. It supports a quick web installation to configure the site.

Backdrop is a PHP-based CMS, originally forked from Drupal 7.

Features

  • PHP 7.3
  • MariaDB 10.4
  • Drush included
  • Automatic TLS certificates

View the repository on GitHub.

Nextcloud

image

This template builds Nextcloud on Web PaaS. Nextcloud itself is downloaded on the fly during the build step, and pre-configured for use with MariaDB and Redis. Add-on applications can be provided in a separate directory and will be merged into Nextcloud automatically during build. (Self-update through the web interface is not supported.)

The admin user is created automatically during the first deploy, and its name and password will be available in the deploy log. Be sure to check for it there so you can log in.

Nextcloud is a PHP-based groupware server with installable apps, file synchronization, and federated storage.

Features

  • PHP 7.4
  • MariaDB 10.4
  • Redis 5.0
  • Automatic TLS certificates
  • Nextcloud downloaded on the fly during build

View the repository on GitHub.

Magento 2 Community Edition

image

This template builds Magento 2 CE on Web PaaS. It includes additional scripts to customize Magento to run effectively in a build-and-deploy environment. A MariaDB database and Redis cache server come pre-configured and work out of the box. The installer has been modified to not ask for database information. Background workers are run using a worker container rather than via cron.

Magento is a fully integrated ecommerce system and web store written in PHP. This is the Open Source version.

Features

  • PHP 7.2
  • MariaDB 10.2
  • Redis 3.2
  • Dedicated worker instance for background processing
  • Automatic TLS certificates
  • Composer-based build

View the repository on GitHub.

TYPO3

image

This template builds the TYPO3 CMS for Web PaaS. It comes pre-configured with MariaDB for storage and Redis for caching. A command line installer will automatically initialize the site on first deploy.

TYPO3 is a PHP-based Content Management System

Features

  • PHP 7.4
  • MariaDB 10.4
  • Redis 5.0
  • Automatic TLS certificates
  • Composer-based build

View the repository on GitHub.

Basic PHP

image

This template provides the most basic configuration for running a custom PHP project built with Composer. It includes but doesn't make use of the Web PaaS `config-reader` library. It can be used to build a very rudimentary application but is intended primarily as a documentation reference.

PHP is a high-performance scripting language especially well suited to web development.

Features

  • PHP 7.4
  • Automatic TLS certificates
  • Composer-based build

View the repository on GitHub.

WordPress (Bedrock)

image

This template builds WordPress on Web PaaS using the Bedrock boilerplate by Roots with Composer. Plugins and themes should be managed with Composer exclusively. The only modifications made to the standard Bedrock boilerplate have been providing database credentials and main site url parameters via environment variables. With this configuration, the database is automatically configured such that the installer will not ask you for database credentials. While Bedrock provides support to replicate this configuration in a `.env` file for local development, an example Lando configuration file is included as the recommendated method to do so.

WordPress is a blogging and lightweight CMS written in PHP, and Bedrock is a Composer-based WordPress boilerplate project with a slightly modified project structure and configuration protocol.

Features

  • PHP 7.4
  • MariaDB 10.4
  • Automatic TLS certificates
  • Composer-based build

View the repository on GitHub.

Laravel

image

This template provides a basic Laravel skeleton. It comes pre-configured to use a MariaDB database and Redis for caching and sessions using a Laravel-specific bridge library that runs during Composer autoload. The public files symlink is also replaced with a custom web path definition so it is unnecessary. It is intended for you to use as a starting point and modify for your own needs.

Laravel is an opinionated, integrated rapid-application-development framework for PHP.

Features

  • PHP 7.4
  • MariaDB 10.4
  • Redis 5.0
  • Automatic TLS certificates
  • Composer-based build

View the repository on GitHub.

Sculpin

image

This template provides a basic Sculpin skeleton. All files are generated at build time, so at runtime only static files need to be served.

Sculpin is a static site generator written in PHP and using the Twig templating engine.

Features

  • PHP 7.4
  • Automatic TLS certificates
  • Composer-based build

View the repository on GitHub.

WooCommerce (Bedrock) for Web PaaS

This template builds WordPress on Web PaaS using the Bedrock boilerplate by Roots with Composer. It includes WooCommerce and JetPack as dependencies, which when enabled will quickly allow you to create a store on WordPress.

Plugins and themes should be managed with Composer exclusively. The only modifications made to the standard Bedrock boilerplate have been providing database credentials and main site url parameters via environment variables. With this configuration, the database is automatically configured such that the installer will not ask you for database credentials. While Bedrock provides support to replicate this configuration in a .env file for local development, an example Lando configuration file is included as the recommendated method to do so.

WordPress is a blogging and lightweight CMS written in PHP, and Bedrock is a Composer-based WordPress boilerplate project with a slightly modified project structure and configuration protocol. WooCommerce is an open-source eCommerce platform and plugin for WordPress.

Features

  • PHP 7.4
  • MariaDB 10.4
  • Automatic TLS certificates
  • Composer-based build

View the repository on GitHub.

Drupal 9

image

This template builds Drupal 9 using the "Drupal Recommended" Composer project. It is pre-configured to use MariaDB and Redis for caching. The Drupal installer will skip asking for database credentials as they are already provided.

Drupal is a flexible and extensible PHP-based CMS framework.

Features

  • PHP 7.4
  • MariaDB 10.4
  • Redis 6
  • Drush included
  • Automatic TLS certificates
  • Composer-based build

View the repository on GitHub.

Drupal 8

image

This template builds Drupal 8 using the "Drupal Recommended" Composer project. It is pre-configured to use MariaDB and Redis for caching. The Drupal installer will skip asking for database credentials as they are already provided.

Drupal is a flexible and extensible PHP-based CMS framework.

Features

  • PHP 7.4
  • MariaDB 10.4
  • Redis 6
  • Automatic TLS certificates
  • Composer-based build

View the repository on GitHub.

GovCMS 8

image

This template builds the Australian government's GovCMS Drupal 8 distribution using the Drupal Composer project for better flexibility. It is pre-configured to use MariaDB and Redis for caching. The Drupal installer will skip asking for database credentials as they are already provided.

GovCMS is a Drupal distribution built for the Australian government, and includes configuration optimized for managing government websites.

Features

  • PHP 7.4
  • MariaDB 10.4
  • Redis 6
  • Drush and Drupal Console included
  • Automatic TLS certificates
  • Composer-based build

View the repository on GitHub.

Pimcore

image

This template builds Pimcore 5 on Web PaaS. It comes pre-installed with a MariaDB database connecting through Doctrine and Redis for caching via a custom configuration file. It will self-install on the first deploy.

Pimcore is a Symfony-based Digital Experience Platform.

Features

  • PHP 7.4
  • MariaDB 10.4
  • Redis 5
  • Automatic TLS certificates
  • Composer-based build

View the repository on GitHub.

WordPress (Composer)

image

This template builds WordPress on Web PaaS using the johnbloch/wordpress "Composer Fork" of WordPress. Plugins and themes should be managed with Composer exclusively. A custom configuration file is provided that runs on Web PaaS to automatically configure the database, so the installer will not ask you for database credentials. For local-only configuration you can use a wp-config-local.php file that gets excluded from Git.

WordPress is a blogging and lightweight CMS written in PHP.

Features

  • PHP 7.4
  • MariaDB 10.4
  • Automatic TLS certificates
  • Composer-based build

View the repository on GitHub.

Opigno

image

This template builds the Opigno Drupal 8 distribution using the Drupal Composer project for better flexibility. It also includes configuration to use Redis for caching, although that must be enabled post-install in .platform.app.yaml.

Opigno is a Learning Management system built as a Drupal distribution.

Features

  • PHP 7.3
  • MariaDB 10.4
  • Redis 6
  • Drush and Drupal Console included
  • Automatic TLS certificates
  • Composer-based build

View the repository on GitHub.

Gatsby with Drupal

image

This template builds a two-application project to deploy the Headless CMS pattern using Gatsby as its frontend and Drupal 8 for its backend. The gatsby-source-drupal source plugin is used to pull data from Drupal during the post_deploy hook into the Gatsby Data Layer and build the frontend site. Gatsby utilizes the Web PaaS Configuration Reader library for Node.js to define the backend data source in its configuration. It is intended for you to use as a starting point and modify for your own needs.

Note that after you have completed the Drupal installation and included a few articles, the project will require a redeploy to build and deploy Gatsby for the first time. See the included README's post-install section for details.

Gatsby is a free and open source framework based on React that helps developers build statically-generated websites and apps, and Drupal is a flexible and extensible PHP-based CMS framework.

Features

  • Node.js 12
  • PHP 7.4
  • MariaDB 10.4
  • Redis 5.0
  • Automatic TLS certificates
  • npm-based build for Gatsby
  • Composer-based build for Drupal
  • Multi-app configuration
  • Delayed SSG build (post deploy hook)

View the repository on GitHub.

WordPress (Vanilla) for Web PaaS

image

This template builds WordPress on Web PaaS, installing WordPress to a subdirectory instead of to the project root. It does not use a package management tool like Composer, and updating core, themes, and plugins should be done with care. A custom configuration file is provided that runs on Web PaaS to automatically configure the database, so the installer will not ask you for database credentials.

WordPress is a blogging and lightweight CMS written in PHP.

Features

  • PHP 7.4
  • MariaDB 10.4
  • Automatic TLS certificates

View the repository on GitHub.


Did you find this guide useful?

Please feel free to give any suggestions in order to improve this documentation.

Whether your feedback is about images, content, or structure, please share it, so that we can improve it together.

Your support requests will not be processed via this form. To do this, please use the "Create a ticket" form.

Thank you. Your feedback has been received.


These guides might also interest you...

OVHcloud Community

Access your community space. Ask questions, search for information, post content, and interact with other OVHcloud Community members.

Discuss with the OVHcloud community

In accordance with the 2006/112/CE Directive, modified on 01/01/2015, prices exclude VAT. VAT may vary according to the customer's country of residence.