Drupal 10.1 On OpenBSD 7.3: Install with Composer
Tags: drupal, symfony, php, openbsd
Published: 2023-09-24 14:55:38

## Summary

[Drupal](https://drupal.org/) is one of the content management systems aka CMS. It has long history and good stability, based on [PHP](https://www.php.net/) and [Symfony](https://symfony.com/).

Symfony is one of the PHP web frameworks. It is clearly classified, functional and robust.

They are often good options to build web services.

- Symfony offers primitive possibility of creating flexible data structure and user interface.
- Drupal offers robust components to build service containing authentication, user roles and functional fields.

Besides, [Drupal Association](https://www.drupal.org/u/drupal-association) wrote about ["Why We Use Symfony"](https://www.drupal.org/association/supporters/blog/why-we-use-symfony).

This post shows how to install Drupal with PHP on [OpenBSD](https://www.openbsd.org/), the solid OS. Here, [Composer](https://getcomposer.org/), the PHP package manager, is used, which possibly makes later update easier.

---

### Environment

- OS: OpenBSD [7.3](https://www.openbsd.org/73.html)
- Database: [MariaDB](https://mariadb.com/) [10.9](https://mariadb.com/kb/en/changes-improvements-in-mariadb-109/)
- App engine: PHP [8.2](https://www.php.net/releases/8.2/)
  - Package Manager: Composer 2.5
- CMS: Drupal [10](https://www.drupal.org/blog/drupal-10-0-0) ([10.1](https://www.drupal.org/blog/drupal-10-1-0), actually)
  - based on: Symfony [6.3](https://symfony.com/blog/symfony-6-3-curated-new-features)
- Web: OpenBSD’s [httpd](https://man.openbsd.org/httpd.8)
  - managed with [`httpd.conf`](https://man.openbsd.org/httpd.conf.5)

Yes, Drupal 10 supports PHP 8 (as well as Drupal [9](https://www.drupal.org/about/9)). Actually it does PHP 8.1 and later. (See: ["PHP versions supported"](https://www.drupal.org/docs/getting-started/system-requirements/php-requirements#versions) in the official docs)

In addition, it's worthy of mention that Composer is given as bound to PHP [8.1](https://www.php.net/releases/8.1/) instead of 8.2. The detail will be written later.

## Tutorial

### 🪄 Overview 💫

1. Create MariaDB database for Drupal.
1. Install PHP, its extensions and Composer. Other packages are optional.
1. Create a Drupal project with Composer.
1. Configure servers: PHP-FPM for app and OpenBSD httpd for web.
1. Install Drupal via the web installer.

The description is below.

---

### Create MariaDB database for Drupal

If you haven't installed MariaDB yet, [this post](https://obsd.solutions/en/blog/2023/09/02/mariadb-109-on-openbsd-73-install/index.html) will help.

Connect to your database server.

```console
$ mysql -u root -p
```

Create a database and the user for it.

```sql
CREATE DATABASE <database> \
    CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, CREATE TEMPORARY TABLES \
    ON <database>.* TO <dbuser> \
    IDENTIFIED BY '<dbpassword>';

FLUSH PRIVILEGES;
```

### Install PHP, its extensions and Composer

#### PHP

We can get both PHP and PHP-FPM with the one-liner below thanks to the great [Ports](https://www.openbsd.org/faq/ports/ports.html) package system.

```console
$ doas pkg_add php
$ # choose php-8.2
```

#### PHP extensions

Get them via Ports, too:

```console
$ doas pkg_add php-curl php-gd php-intl php-zip php-mysqli php-pdo_mysql # + php-[...] if necessary
$ # choose those of php-8.2
```

Be sure to activate them:

```console
$ doas ln -s /etc/php-8.2.sample/* /etc/php-8.2/
```

Creating the symbolic links as above means the extensions are activated. You can confirm them:

```
$ ls -l /etc/php-8.2
total 0
lrwxr-xr-x  1 root  wheel  26 Sep 24 11:36 curl.ini@ -> ../php-8.2.sample/curl.ini
lrwxr-xr-x  1 root  wheel  24 Sep 24 11:36 gd.ini@ -> ../php-8.2.sample/gd.ini
lrwxr-xr-x  1 root  wheel  26 Sep 24 11:36 intl.ini@ -> ../php-8.2.sample/intl.ini
lrwxr-xr-x  1 root  wheel  28 Sep 24 11:36 mysqli.ini@ -> ../php-8.2.sample/mysqli.ini
lrwxr-xr-x  1 root  wheel  29 Sep 24 11:36 opcache.ini@ -> ../php-8.2.sample/opcache.ini
lrwxr-xr-x  1 root  wheel  31 Sep 24 11:36 pdo_mysql.ini@ -> ../php-8.2.sample/pdo_mysql.ini
lrwxr-xr-x  1 root  wheel  25 Sep 24 11:36 zip.ini@ -> ../php-8.2.sample/zip.ini
```

#### Composer

You can get Composer with one-liner, too. Be careful, however, that it's bound to PHP 8.1 (and therefore PHP 8.1 will be installed together here).

```console
$ doas pkg_add composer
```

#### Other packages if necessary (Optional)

```console
$ #doas pkg_add unzip git
```

### Create a Drupal project with Composer

#### Create a project

Let's see which PHP version Composer is behind:

```console
$ composer -vvv about
```

In my case, the result was:

```console
Running 2.5.4 (2023-02-15 13:10:06) with PHP 8.1.23 on OpenBSD / 7.3
Failed to initialize global composer: Composer could not find the config file: /home/(...)/.composer/composer.json
To initialize a project, please create a composer.json file. See https://getcomposer.org/basic-usage
Composer - Dependency Manager for PHP - version 2.5.4
Composer is a dependency manager tracking local dependencies of your projects and libraries.
See https://getcomposer.org/ for more information.
```

It showed "Running 2.5.4 (2023-02-15 13:10:06) with PHP 8.1.23 on OpenBSD / 7.3". When going to build Drupal site with PHP 8.1, there wasn't any problem. However, it was not the case.

Therefore I used a little trick to run `composer` to create a Drupal project.

```console
$ php-8.2 /usr/local/libexec/composer.phar \
      create-project drupal/recommended-project <drupal-dir>
```

Besides, in case that php 8.1 is used, the command line is simpler:

```console
$ #composer \
      create-project drupal/recommended-project <drupal-dir>
```

Well, the output around PHP 8.2 was:

```console
Creating a "drupal/recommended-project" project at "./drupal_on_openbsd"
Installing drupal/recommended-project (10.1.4)
  - Installing drupal/recommended-project (10.1.4): Extracting archive
Created project in /var/www/sites/drupal_on_openbsd
Installing dependencies from lock file (including require-dev)
Verifying lock file contents can be installed on current platform.
Package operations: 59 installs, 0 updates, 0 removals
  - Downloading composer/installers (v2.2.0)
  (...)
  - Downloading drupal/core (10.1.4)
  - Installing composer/installers (v2.2.0): Extracting archive
  - Installing drupal/core (10.1.4): Extracting archive
  - Installing drupal/core-recommended (10.1.4)
Generating autoload files
39 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
Scaffolding files for drupal/core:
  - Copy [project-root]/.editorconfig from assets/scaffold/files/editorconfig
  (...)
  - Copy [web-root]/sites/default/default.services.yml from assets/scaffold/files/default.services.yml
  - Copy [web-root]/sites/default/default.settings.php from assets/scaffold/files/default.settings.php
  - Copy [web-root]/modules/README.txt from assets/scaffold/files/modules.README.txt
  - Copy [web-root]/profiles/README.txt from assets/scaffold/files/profiles.README.txt
  - Copy [web-root]/themes/README.txt from assets/scaffold/files/themes.README.txt
  * Homepage: https://www.drupal.org/project/drupal
  * Support:
    * docs: https://www.drupal.org/docs/user_guide/en/index.html
    * chat: https://www.drupal.org/node/314178
No security vulnerability advisories found
                                                         
  Congratulations, you’ve installed the Drupal codebase  
  from the drupal/recommended-project template!          
                                                         

Next steps:
  * Install the site: https://www.drupal.org/docs/installing-drupal
  * Read the user guide: https://www.drupal.org/docs/user_guide/en/index.html
  * Get support: https://www.drupal.org/support
  * Get involved with the Drupal community:
      https://www.drupal.org/getting-involved
  * Remove the plugin that prints this message:
      composer remove drupal/core-project-message
  * Homepage: https://www.drupal.org/project/drupal
  * Support:
    * docs: https://www.drupal.org/docs/user_guide/en/index.html
    * chat: https://www.drupal.org/node/314178
```

#### Configure directory and permissions

A bit more work is required.

```console
$ cd <drupal-dir>

$ mkdir ./config

$ doas chown -R www: ./config
$ doas chown -R www: ./web/sites/default
```

Done !! Now your project is waiting to be initialized and installed.

### Configure servers

#### PHP-FPM for app

Activate `php82_fpm` daemon and then run it:

```console
$ doas rcctl enable php82_fpm
$ doas rcctl start php82_fpm
```

Besides, the more detail about PHP-FPM 8.2 server is written in [my past post](https://obsd.solutions/en/blog/2023/08/03/php-fpm-82-on-openbsd-73/index.html).

#### OpenBSD httpd for web

Configure web server(s) to enable the flow below:

```
Client --(request)--> Web: httpd --> Gateway: PHP-FPM --> App: Drupal
```

Edit the configuration file of OpenBSD httpd:

```console
$ doas nvim /etc/httpd.conf
```

to add definitions like below:

```apache
server "<fqdn>" {
        listen on egress tls port https
        tls {
                certificate     "/etc/ssl/<fqdn>.pem"
                key             "/etc/ssl/private/<fqdn>.key"
        }
        # alternative to the above:
        #listen on egress port http

        log {
                access  "<fqdn>-access.log"
                error   "<fqdn>-error.log"
        }

        root "/<drupal-dir>/web" # (with chroot)
        directory index index.php

        location "/*.php" { 
                fastcgi socket "/run/php-fpm.sock"
        }
        location "/*.php[/?]*" { 
                fastcgi socket "/run/php-fpm.sock"
        } 
        location "*" {
                fastcgi socket "/run/php-fpm.sock"
                request rewrite "/index.php$REQUEST_URI"
        }
}
```

Both `<fqdn>` (your domain etc.) and `<drupal-dir>` are, of course, up to your environment.

The `root` of the server above must point to:

- not: the Drupal project root (aka `/var/www/<drupal-dir>`)
- but: `/web` in it (aka `/var/www/<drupal-dir>/web`).

Besides, they are affected by [`chroot`](https://man.openbsd.org/chroot.2).

You don't have TLS certificates ? [The notes below](#tls-configuration-files) could help.

Well, when all are done, reload the daemon:

```console
$ doas rcctl restart httpd
```

#### TLS configuration files

It is able to get them via requests to [Let's Encrypt](https://letsencrypt.org/) with [`acme-client`](https://man.openbsd.org/acme-client.1). (See: How to configure OpenBSD [acme-client](https://obsd.solutions/en/blog/2022/03/04/openbsd-acme-client-70-for-letsencrypt-certificates/index.html)).

Alternatively, you can get them as self-signed certificates with command lines such as:

```console
$ cd /etc/ssl

$ # [ consts ]
$ # case ksh:
$ export MY_DOMAIN="..."
$ export MY_COUNTRY_CODE="XX"
$ export MY_STATE="..."
$ export MY_ORGANIZATION="..."
$ # case fish:
$ # set -x MY_DOMAIN "..."; (...)

$ # [ generate ]
$ doas openssl req -newkey rsa:2048 -new -nodes -x509 -days 36500 -keyout private/$MY_DOMAIN.key -out $MY_DOMAIN.crt \
    -subj "/C=$MY_COUNTRY_CODE/ST=$MY_STATE/L=/O=$MY_ORGANIZATION/OU=/CN=$MY_DOMAIN"
$ doas chmod 400 private/$MY_DOMAIN.key

$ # return to your working directory
```

#### Servers with and without TLS connection (Optional)

In addition, you can also redirect all http requests to https as needed:

```apache
# httpd.conf
server "<fqdn>" {
        listen on egress http
        # (...)
        block return 301 "https://$SERVER_NAME$REQUEST_URI"
}
server "<fqdn>" {
        listen on egress tls port https
        # (...)
}
```

### Install Drupal via the web installer

Connect to `https://\<fqdn\>` with your web browser. You will be redirected to `https://\<fqdn\>/core/install.php`.

When the web install is shown, follow their messages. The screenshots are below.

#### Language

![drupal-101-on-openbsd-install-01](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/58zwn8485o7k9kodqjpg.png)

#### Installation profile

![drupal-101-on-openbsd-install-02](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r5mrgoxujkcbxukfy5g8.png)

#### Database configuration

![drupal-101-on-openbsd-install-03](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v1a4qs1npqpzopx3o2fy.png)
![drupal-101-on-openbsd-install-04](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4k2gkzo181afodsiidwj.png)

#### Progress

![drupal-101-on-openbsd-install-05](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mmpukamdxtt62fezupgt.png)

#### Site configuration

![drupal-101-on-openbsd-install-06](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fu7vcejov2nlzlgizrv5.png)

![drupal-101-on-openbsd-install-07](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/27ocjwp6g921wesbh3xp.png)

#### Completed

![drupal-101-on-openbsd-completed-01](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bim22x09zvd874ddbg70.png)

Yay 😁 Here comes Drupal with OpenBSD 🙌

## Conclusion

Symfony is one of my favorite frameworks for web development. It's because:

1. It has clean classes and powerful functionality.
1. It is [designed with security in mind](https://symfony.com/doc/current/security.html). (It's also [true on Drupal](https://www.drupal.org/documentation/is-drupal-secure).)
1. It becomes more powerful with useful helpers such as [MakeBundle](https://symfony.com/doc/current/bundles/SymfonyMakerBundle/index.html).
1. It also provides great official [documentation](https://symfony.com/doc/current/index.html).
1. The [cache](https://symfony.com/doc/current/cache.html) system helps performance and also development.

And, again, Drupal is based on it.

Besides, they may have steeper learning curve for beginners than [WordPress](https://wordpress.com/) and perhaps [Laravel](https://laravel.com/).

![drupal-101-on-openbsd-completed-02](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tk9bkyvv1k1z0sf5l4we.png)

As above, Drupal is running on PHP working with OpenBSD httpd. All of them are hosted on OpenBSD 🐡

🌟 Happy serving 🌟