2019-12-08 19:42:16 +00:00
---
2020-03-08 14:41:34 +00:00
title: Running Drupal 8.8 with the Symfony Local Server
2020-03-09 19:03:12 +00:00
excerpt: How to use Symfony's local web server to run a Drupal 8.8 website.
2020-03-09 14:09:05 +00:00
date: 2020-03-09
2020-03-08 17:52:59 +00:00
tags:
- drupal
- drupal-8
- symfony
2019-12-08 19:42:16 +00:00
---
2020-03-09 01:58:45 +00:00
![A screenshot of a terminal window running a Drupal project with the Symfony local server ](/images/blog/running-drupal-with-symfony-local-server/terminal.png )
2019-12-08 19:42:16 +00:00
2020-03-09 14:09:05 +00:00
<!--
## Why use the Symfony server?
- performance
- reusable knowledge
-->
2019-12-08 19:42:16 +00:00
## Installation
2020-03-09 14:09:05 +00:00
< https: / / symfony . com / doc / current / setup / symfony_server . html >
2020-03-09 01:58:45 +00:00
2020-03-08 17:52:59 +00:00
The Symfony server is bundled as part of the `symfony` binary that is available
to download from < https: / / symfony . com / download > .
2020-03-08 14:41:34 +00:00
To install it, run this command:
```bash
curl -sS https://get.symfony.com/cli/installer | bash
```
2020-03-09 01:58:45 +00:00
Even though it’ s by Symfony, the local webserver works with any type of
2020-03-09 14:09:05 +00:00
project - including Drupal 8 (and 9) and Drupal 7.
2020-03-09 01:58:45 +00:00
## Getting started
2020-03-09 14:09:05 +00:00
Here are the basic commands to start and stop the server:
2020-03-09 01:58:45 +00:00
```bash
# Alias for server:start, starts the server
symfony serve
# Run the server in daemon mode (in the background)
symfony serve -d
# Display the status of the server
symfony server:status
# Stop the server
symfony server:stop
```
2020-03-09 14:09:05 +00:00
If your Drupal files are within a `web` or `docroot` directory, it will
automatically be used as the document root for the server, so files are served
from there if you run the serve command.
If you use a different subdirectory name - one that isn't loaded automatically -
you can use the `--document-root` option:
```bash
symfony serve --document-root www
```
2019-12-08 19:42:16 +00:00
2020-03-08 14:41:34 +00:00
## Different PHP Versions
2019-12-08 19:42:16 +00:00
2020-03-08 17:52:59 +00:00
One of the most useful features of the Symfony server is that it
[supports multiple versions of PHP ](https://symfony.com/doc/current/setup/symfony_server.html#different-php-settings-per-project )
2020-03-09 01:58:45 +00:00
if you have them installed, and a different version can be selected per
directory.
2019-12-08 19:42:16 +00:00
2020-03-09 01:58:45 +00:00
This is done by adding a `.php-version` file to the root of the project that
contains the PHP version to use. For example:
```bash
echo "7.3" > .php-version
```
2019-12-08 19:42:16 +00:00
2020-03-08 17:52:59 +00:00
Next time the server is started, this file will be read and the correct version
of PHP will be used.
2020-03-08 14:41:34 +00:00
2020-03-09 01:58:45 +00:00
If you’ re using macOS and want to install another version of PHP, you can do it
using Homebrew:
```bash
# Install PHP 7.3
brew install php@7.3
```
2020-03-08 17:52:59 +00:00
[Further PHP customisations can be made per project ](https://symfony.com/doc/current/setup/symfony_server.html#overriding-php-config-options-per-project )
by adding a `php.ini` file.
2019-12-08 19:42:16 +00:00
2020-03-08 14:41:34 +00:00
## Securing Sites Locally
2019-12-08 19:42:16 +00:00
2020-03-09 14:09:05 +00:00
The Symfony server allows for serving sites via HTTPS locally by installing its
own local certificate authority.
2019-12-08 19:42:16 +00:00
2020-03-09 01:58:45 +00:00
If it’ s not installed automatically, run this command to install it:
2019-12-08 19:42:16 +00:00
2020-03-08 14:41:34 +00:00
```
symfony server:ca:install
```
2019-12-08 19:42:16 +00:00
2020-03-09 01:58:45 +00:00
Now any site will be served via HTTPS by default, and any HTTP requests will be
2020-03-09 14:09:05 +00:00
automatically redirected.
2019-12-08 19:42:16 +00:00
2020-03-09 01:58:45 +00:00
If you need to run a site with just HTTP, add the `--no-tls` option to the
`serve` command.
2019-12-08 19:42:16 +00:00
2020-03-09 14:09:05 +00:00
## Adding Databases (and other services) with Docker
2019-12-08 19:42:16 +00:00
2020-03-08 17:52:59 +00:00
The Symfony server has an integration with Docker for providing extra services -
2020-03-09 14:09:05 +00:00
such as databases that we’ ll need to install Drupal.
2019-12-08 19:42:16 +00:00
2020-03-08 17:52:59 +00:00
This is my `docker-compose.yaml` file which defines a `database` service for
MySQL:
2019-12-08 19:42:16 +00:00
```yaml
version: '2.1'
2020-03-08 14:41:34 +00:00
2019-12-08 19:42:16 +00:00
services:
database:
image: mysql:5.7
ports: [3306]
environment:
MYSQL_ROOT_PASSWORD: secret
volumes:
- mysql-data:/var/lib/mysql
2020-03-08 14:41:34 +00:00
2019-12-08 19:42:16 +00:00
volumes:
mysql-data:
```
2020-03-08 17:52:59 +00:00
Because port 3306 is exposed, the server recognises it as a database service and
automatically creates environment variables prefixed with `DATABASE_` .
A list of all the environment variables can be seen by running
`symfony var:export` (add `| tr " " "\n"` if you want to view each one on a new
2020-03-09 01:58:45 +00:00
line, and `| sort` if you want to list them alphabetically):
2019-12-08 19:42:16 +00:00
```dotenv
DATABASE_DATABASE=main
DATABASE_DRIVER=mysql
DATABASE_HOST=127.0.0.1
DATABASE_NAME=main
DATABASE_PASSWORD=secret
DATABASE_PORT=32776
DATABASE_SERVER=mysql://127.0.0.1:32776
DATABASE_URL=mysql://root:secret@127.0.0.1:32776/main?sslmode=disable& charset=utf8mb4
DATABASE_USER=root
DATABASE_USERNAME=root
SYMFONY_DOCKER_ENV=1
SYMFONY_TUNNEL=
SYMFONY_TUNNEL_ENV=
```
2020-03-09 14:09:05 +00:00
Now these environment variables can be used within `settings.php` file to allow
configure Drupal’ s database connection settings:
2019-12-08 19:42:16 +00:00
```php
// web/sites/default/settings.php
2020-03-09 14:09:05 +00:00
if ($_SERVER['SYMFONY_DEFAULT_ROUTE_URL']) {
2019-12-08 19:42:16 +00:00
$databases['default']['default'] = [
'driver' => $_SERVER['DATABASE_DRIVER'],
'host' => $_SERVER['DATABASE_HOST'],
'database' => $_SERVER['DATABASE_NAME'],
'username' => $_SERVER['DATABASE_USER'],
'password' => $_SERVER['DATABASE_PASSWORD'],
'port' => $_SERVER['DATABASE_PORT'],
'prefix' => '',
'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
'collation' => 'utf8mb4_general_ci',
];
}
```
2020-03-09 14:09:05 +00:00
To keep things organised, I usually like to split these settings into their own
file and include it:
```php
if ($_SERVER['SYMFONY_DEFAULT_ROUTE_URL'] & & file_exists(__DIR__ . '/settings.symfony.php')) {
require_once __DIR__ . '/settings.symfony.php';
}
```
2019-12-08 19:42:16 +00:00
## Installing Drupal
2020-03-09 14:09:05 +00:00
Now that Drupal can connect to the (empty) database, we can install the site. I
usually do this using Drush, which is added as a dependency via Composer.
The command that I’ d usually run is:
2020-03-09 01:58:45 +00:00
```bash
2020-03-09 14:09:05 +00:00
cd web
2020-03-09 01:58:45 +00:00
../vendor/bin/drush site-install
```
However, this will cause an error like this because Drupal cannot connect to the
2020-03-09 14:09:05 +00:00
database when Drush is run in this way.
2019-12-08 19:42:16 +00:00
> Error: Class 'Drush\Sql\Sql' not found in Drush\Sql\SqlBase::getInstance()
2020-03-09 01:58:45 +00:00
To fix this, ensure that the command is prefixed with `symfony php` . This will
ensure that the correct PHP version and configuration is used, and that the
appropriate environment variables are available.
2020-03-08 14:41:34 +00:00
2020-03-09 01:58:45 +00:00
```bash
symfony php ../vendor/bin/drush site-install
```
This also applies to all other Drush commands.
2020-03-08 15:29:47 +00:00
2020-03-08 14:41:34 +00:00
## Custom Domain Names
2020-03-09 14:09:05 +00:00
Currently we can only access the site via the localhost URL with a specific
port. The port is determined automatically when the server is started so it can
change if you have multiple projects running.
2020-03-08 15:29:47 +00:00
2020-03-09 14:09:05 +00:00
Symfony server also allows for
[adding local domain names through a proxy ](https://symfony.com/doc/current/setup/symfony_server.html#local-domain-names ).
This is useful if you always want to access the site from the same URL, or if
the site relies on using a specific URL such as a multisite setup (multiple
domains served from the same codebase).
2020-03-08 14:41:34 +00:00
2020-03-09 14:09:05 +00:00
{% include 'figure' with {
image: {
src: '/images/blog/running-drupal-with-symfony-local-server/proxy.png',
alt: 'A screenshot of the proxy overview screen, showing three local projects with their local domains, ports and directories.',
},
caption: 'The proxy overview screen'
} only %}
2020-03-09 01:58:45 +00:00
2020-03-09 14:09:05 +00:00
### Setting up a multisite
2020-03-08 15:29:47 +00:00
2020-03-09 14:09:05 +00:00
Here’ s an example of how I would use local domains to configure a multisite
Drupal installation (taken from
< https: / / github . com / opdavies / symfony-server-drupal-test > ).
2020-03-08 15:29:47 +00:00
2020-03-09 14:09:05 +00:00
The first thing is to add the subdomain to the proxy. In this example, I’ m going
to set up a version of the Umami demo installation profile at
`https://umami.wip` .
```bash
# Add umami.wip to the proxy and attach it to this directory
symfony proxy:domain:attach umami
```
Now we can add it to Drupal’ s `sites.php` file to route requests to the correct
site directory:
2020-03-08 15:29:47 +00:00
```php
// web/sites/sites.php
2020-03-09 14:09:05 +00:00
// This maps https://umami.wip to the sites/umami directory
2020-03-08 15:29:47 +00:00
$sites['umami.wip'] = 'umami';
```
2020-03-09 14:09:05 +00:00
To create the directory, we can duplicate the `default` site directory and its
contents.
2020-03-08 15:29:47 +00:00
2020-03-09 14:09:05 +00:00
```
cp -R web/sites/default web/sites/umami
```
To create a separate database, we add a new service to the `docker-compose.yaml`
file and a new MySQL volume to store the data. We can use labels to generate
site specific environment variables.
```diff
version: '2.1'
services:
database:
image: mysql:5.7
ports: [3306]
environment:
MYSQL_ROOT_PASSWORD: secret
volumes:
- mysql-data:/var/lib/mysql
+ database_umami:
+ image: mysql:5.7
+ ports: [3306]
+ environment:
+ MYSQL_ROOT_PASSWORD: secret
+ volumes:
+ - mysql-data-umami:/var/lib/mysql
+ labels:
+ com.symfony.server.service-prefix: 'UMAMI_DATABASE'
volumes:
mysql-data:
+ mysql-data-umami:
```
These can then be added to `sites/umami/settings.php` :
```php
$databases['default']['default'] = [
'driver' => $_SERVER['UMAMI_DATABASE_DRIVER'],
'host' => $_SERVER['UMAMI_DATABASE_HOST'],
'database' => $_SERVER['UMAMI_DATABASE_NAME'],
'username' => $_SERVER['UMAMI_DATABASE_USER'],
'password' => $_SERVER['UMAMI_DATABASE_PASSWORD'],
'port' => $_SERVER['UMAMI_DATABASE_PORT'],
'prefix' => '',
'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
'collation' => 'utf8mb4_general_ci',
];
2020-03-08 15:29:47 +00:00
```
2020-03-09 14:09:05 +00:00
Now that the Umami site is able to connect to its own database, we can install
Drupal - specifying the installation profile to use and also the site directory
to target.
2020-03-08 15:29:47 +00:00
```bash
2020-03-09 14:09:05 +00:00
symfony php ../vendor/bin/drush site-install \
demo_umami \
2020-03-08 15:29:47 +00:00
-l umami \
--no-interaction
```