User Documentation

Customize TYPO3 for

Sign up for Upsun

Get your free trial by clicking the link below.

Get your Upsun free trial

Now that your code contains all of the configuration to deploy on, it’s time to make your TYPO3 site itself ready to run on a environment. There are a number of additional steps that are either required or recommended, depending on how well you want to optimize your site.

Install the Config Reader Anchor to this heading

You can get all information about a deployed environment, including how to connect to services, through environment variables. Your app can access these variables.

The following examples use it, so install it through Composer if you haven’t already.

composer require platformsh/config-reader

Avoiding deadlock with the Local Page Error Handler Anchor to this heading

A default TYPO3 installation has a risk of deadlocks when run on low-worker PHP-FPM configurations. Specifically, TYPO3 handles 403 and 404 error pages by issuing a full HTTP request back to itself with no timeout, which can lead to process starvation. There are two required steps to avoid this problem.

First, you need to install the Local Page Error Handler extension for TYPO3 with the command:

composer require pixelant/pxa-lpeh

Second, you need to add a timeout that sets an HTTP timeout of at least 3 seconds instead of the default several minutes to a new public/typo3conf/PlatformshConfiguration.php. You can see this line in context of the full file in the configuration section below.

$GLOBALS['TYPO3_CONF_VARS']['HTTP']['timeout'] = 3;

You still need to enable the pixelant/pxa-lpeh extension, which you can do by running the command:

php vendor/bin/typo3 extension:activate pxa_lpeh

TYPO3 CMS’s web-dir Anchor to this heading recommends serving TYPO3 from its default subdirectory public. public can be seen already throughout your file in web.locations.root, mounts and within your build and deploy hooks. You need to assign public to the cms.web-dir attribute in your composer.json file, and it’s a good idea to update dependencies once you have done so:

composer config extra.typo3/cms.web-dir public && composer update --no-scripts

Site Anchor to this heading

You have to locate the site configuration files (config.yaml) in your repository’s config/sites/<SITEID> subdirectories. For the purposes of this guide, you need to set the base attribute to an environment variable called PLATFORM_ROUTES_MAIN. You can also add the definition to your existing baseVariant attribute for production if desired.

# TYPO3 Site Handling configuration YAML.
# See
rootPageId: 1

# The base domain used to run the TYPO3 site. Here, the environment variable `PLATFORM_ROUTES_MAIN` set in 
# `public/typo3/conf/PlatformshConfiguration.php` is used. 

# Site's available languages configuration.
# See
        languageId: '0'
        title: English
        navigationTitle: English
        base: '/'
        locale: en_US.UTF8
        iso-639-1: en
        hreflang: en-US
        direction: ltr
        typo3Language: default
        flag: us
        enabled: true
        languageId: '2'
        title: German
        navigationTitle: Deutsch
        base: '/de/'
        locale: de_DE.UTF8
        iso-639-1: de
        hreflang: de-DE
        direction: ltr
        typo3Language: de
        flag: de
        fallbackType: fallback
        fallbacks: '0'
        enabled: true
        languageId: '1'
        title: Dansk
        navigationTitle: Dansk
        base: '/da/'
        locale: da_DK.UTF-8
        iso-639-1: da
        hreflang: da-DK
        direction: ltr
        typo3Language: default
        flag: dk
        fallbackType: fallback
        fallbacks: '0'
        enabled: true

# Configuration for how to handle error codes for the TYPO3 site.
# See
        errorCode: '404'
        errorHandler: Page
        errorContentSource: 't3://page?uid=5'

# Environment-specific `base` configuration.
# See
baseVariants: {  }

# Adding static routes for the TYPO3 site. 
# See
        route: robots.txt
        type: staticText
        content: "User-agent: *\r\nDisallow: /typo3/"

You define this environment variable in the next section, but its purpose is to retrieve the root domain (since you haven’t yet registered a domain name on the project, this is a hashed placeholder domain generated from the environment) from the environment variable PLATFORM_ROUTES.

Environment Anchor to this heading

Finally, you can start using the Configuration Reader library to starting reading from the environment from within your application. In a public/typo3conf/PlatformshConfiguration.php file, you can use the library to:

  • Verify the deployment is occurring on a project (if (!$platformConfig->isValidPlatform()))
  • Verify that it’s not running during build, when services aren’t yet available (if ($platformConfig->inBuild()))
  • Set the PLATFORM_ROUTES_MAIN environment variable used in config/sites/main/config.yaml)
  • Configure TYPO3’s database (TYPO3_CONF_VARS.DB.Connections.Default) using credentials from the database relationship ($databaseConfig = $platformConfig->credentials('database'))
  • Configure TYPO3’s cacheConfigurations to use Redis via your rediscache relationship
  • Configure the HTTP timeout to 3 seconds to avoid the PHP-FPM-related deadlock described above.

 * configuration for TYPO3.
 * You may edit this file as desired, but connection configuration
 * should be based on environment variables.


use Platformsh\ConfigReader\Config;

// Leverages the Configuration Reader library for PHP.
// See
$platformConfig = new Config();

// Ensures script does not run if not on
if (!$platformConfig->isValidPlatform()) {

// Ensures script does not run during builds, when relationships
// are not available.
if ($platformConfig->inBuild()) {

// Workaround to set the proper env variable for the main route (found in config/sites/main/config.yaml)
// Relies on the `id: "main"` configuration set in `.platform/routes.yaml`.
putenv('PLATFORM_ROUTES_MAIN=' . $platformConfig->getRoute('main')['url']);

// Configure the database for `doctrine-dbal` for TYPO3 based on the relationships. 
// See
// These lines depend on the database relationship being named `database`. If updating the name to 
// something else below, be sure to update `` to match.
if ($platformConfig->hasRelationship('database')) {
    $databaseConfig = $platformConfig->credentials('database');
    $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['driver'] = 'mysqli';
    $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['host'] = $databaseConfig['host'];
    $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['port'] = $databaseConfig['port'];
    $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['dbname'] = $databaseConfig['path'];
    $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['user'] = $databaseConfig['username'];
    $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['password'] = $databaseConfig['password'];

// Configure Redis as the cache backend if available. These lines depend on the Redis relationship
// being named `rediscache`. If updating the name to something else below, be sure to update `` to match.
if ($platformConfig->hasRelationship('rediscache')) {
    $redisConfig = $platformConfig->credentials('rediscache');
    $redisHost = $redisConfig['host'];
    $redisPort = $redisConfig['port'];
    $list = [
        'pages' => 3600 * 24 * 7,
        'pagesection' => 3600 * 24 * 7,
        'rootline' => 3600 * 24 * 7,
        'hash' => 3600 * 24 * 7,
        'extbase' => 3600 * 24 * 7,
    $counter = 1;
    foreach ($list as $key => $lifetime) {
        $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations'][$key]['backend'] = \TYPO3\CMS\Core\Cache\Backend\RedisBackend::class;
        $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations'][$key]['options'] = [
            'database' => $counter++,
            'hostname' => $redisHost,
            'port' => $redisPort,
            'defaultLifetime' => $lifetime

// Ensure that HTTP requests have a timeout set, to avoid sites locking up due to slow
// outgoing HTTP requests.
$GLOBALS['TYPO3_CONF_VARS']['HTTP']['timeout'] = 3;

// Add additional configuration here, such as a search backend.

Then include the require_once() function within your public/typo3conf/AdditionalConfiguration.php file to load the configuration into the site if present.


 * Additional configuration file.
 * Place configuration here you want to be shared by environments and local development.
 * configuration should be added to PlatformshConfiguration.php.
 * Environment-specific configuration should be added to LocalConfiguration.php as normal.

// Include the configuration.
// This file will no-op on its own if not on
$platformshFile = __DIR__ . '/PlatformshConfiguration.php';
if (file_exists($platformshFile)) {

Is this page helpful?