From ArchWiki
Jump to navigation Jump to search

From Wikipedia:

Grav is a free software, self-hosted content management system (CMS) written in the PHP programming language and based on the Symfony web application framework. It uses a flat file database for both backend and frontend.
Grav is designed to have a shallow learning curve, and to be easy to set up. The focus of Grav is speed and simplicity, rather than an abundance of built-in features that come at the expense of complexity.


Grav comes with surprisingly few prerequisites by itself. Of course as a web application written in PHP it needs PHP. The only required PHP module is php-gd. A few others are also required but already part of the bare PHP installation. The following PHP modules are optional but highly recommended for better performance:

  • php-apcu for increased cache performance
  • php-yamlAUR for native YAML processing dramatically increasing performance

Although Grav can serve the content on its own this article describes a setup with a full blown web server in front. So you need:

The following combinations will be covered:

  • Apache (using mod_proxy_fcgi) → php-fpm
  • Apache (using mod_proxy_uwsgi) → uWSGI (plus uwsgi-plugin-php)
  • nginx → php-fpm,
  • nginx → uWSGI (plus uwsgi-plugin-php)

The installation of Grav complies with Arch Linux' web application package guidelines. This means among other details that Grav must be run with its own system user (grav). So it is not possible anymore to execute the PHP code directly in the Apache process by means of php-apache.


Install the gravAUR package. This automatically takes care of installing the two requires dependencies PHP and php-gd. Also install php-apcu and php-yamlAUR - preferrably as a dependency (--asdeps). Comment the only line in /etc/php/conf.d/yaml.ini. Do not modify /etc/php/conf.d/apcu.ini, i.e. leave the only line commented. Activating these two extensions for Grav will be taken care of in other places (see below).

Application server

There are two prevalent application servers that can be used to process PHP code: uWSGI or php-fpm. php-fpm as the name suggests is specialized on PHP. The protocol used between the web server and php-fpm is fastcgi. The tool is poorly documented. uWSGI on the other hand can serve code written in a handful of languages by means of language specific plugins. The protocol used is uwsgi (lowercase). The tool is extensively documented - albeit the sheer amount of documentation can become confusing and unwieldy.


uWSGI has its own article. A lot of useful information can be found there. Install uwsgi and the plugin uwsgi-plugin-php - preferrably as dependencies, i.e. with --asdeps. Setup of your Grav application requires only copying one file and defining one systemd service.


Copy the Grav specific uWSGI setup file to the appropriate location.

cp /usr/share/webapps/grav/webserver-configs/uwsgi-grav.ini /etc/uwsgi/grav.ini

Make sure grav.ini is owned and only writeable by root, i.e. -rw-r--r-- 1 root root ... grav.ini. This configuration is functional but feel free to adapt it to your liking. E.g. you might like to change php-set = date.timezone= to your preferred timezone.

Enable and start

The package uwsgi provides a template unit file (uwsgi@.service). The instance ID (here grav) is used to pick up the right configuration file. That's what we do.

systemctl enable uwsgi@grav.service
systemctl start uwsgi@grav.service

In case you have more than a few (e.g. 2) services started like this and get the impression this is a waste of resource you might consider using emporer mode.


In case you opt to use php-fpm as your application server install php-fpm - preferrably as a dependent package (--asdeps).

You have to tweak its configuration a little bit.


It's a good practice to run php-fpm with its own version of php.ini. You thus avoid cluttering the standard INI file (/etc/php/php.ini) with stuff only needed by php-fpm. There is a copy of a functional INI file in /usr/share/webapps/grav/webserver-configs. Copy it to /etc/php.

cp /usr/share/webapps/grav/webserver-configs/php-fpm.ini /etc/php

Make sure it is owned and only writeable by root. Something along -rw-r--r-- 1 root root ... php-fpm.ini. Feel free to customize the configuration as you see fit.

php-fpm service

php-fpm is (of course) run as a systemd service. You have to modify the service configuration to be able to run Grav. This is best achieved by means of a drop-in file. The content of the drop-in file can be found in /usr/share/webapps/grav/webserver-configs/php-fpm.service.d/override.conf. Use systemctl edit php-fpm.service to create the file and copy over the content. The drop-in file has three purposes.

  • It replaces the ExecStart line by a start command that uses the php-fpm.ini covered in the previous section.
  • It disables the ProtectSystem option since Grav requires to be able to write to /etc/webapps/grav.
  • It disables the PrivateTmp option. Although a sensible option it has to be turned off so that the gravAUR package can also be used with other application servers.

grav.conf pool file

Finally you have to create a so called pool file for php-fpm. It is responsible for spawning a dedicated php-fpm process for the Grav application. Copy the version provided by the gravAUR package.

cp /usr/share/webapps/grav/webserver-configs/php-fpm.d/grav.conf /etc/php/php-fpm.d

Again make sure this pool file is owned and only writeable by root (i.e. -rw-r--r-- 1 root root ... grav.conf). You may tweak some settings (especially pm... and php_admin_value[date.timezone] to your liking.

Tip: The package php-fpm comes with its own pool file www.conf that is of little use here. A good approach to get rid of it is to rename it to www.conf.package and create a file www.conf with only comment lines (lines starting with a semicolon). This way www.conf becomes a no-op. It is also not overwritten during installation of a new version of php-fpm. Instead a file www.conf.pacnew is created. You can compare this against www.conf.package to see if anything significant has changed in the pool file that you may have to reproduce in grav.conf. Don't forget to rename www.conf.pacnew to www.conf.package at the end of this procedure.

Enable and start

Don't forget to enable and start the php-fpm service.

systemctl enable --now php-fpm

Web server

There is an abundance of web servers you can choose from. Whatever option you finally choose you have to keep in mind that the Grav application needs to be run with its own system user grav. So you probably need to forward your requests to one of the above mentioned application servers.

Warning: Some of the sample files provided in /usr/share/webapps/grav/webserver-configs (except nginx.conf) might be outdated.


Configuration of nginx is way beyond the scope of this article. See the relevant article for further information. The package gravAUR comes with a sample configuration file /usr/share/webapps/grav/webserver-configs/nginx.conf. This file is not functional as is. Use it as a starting point for your own configuration. Most likely you will have to copy it into /etc/nginx/sites-available with an appropriate name and create the corresponding symbolic link in /etc/nginx/sites-enabled.

The sample file assumes you are using SSL/TLS and some ACME client (e.g. Certbot) to get your certificates. OCSP stapling] is not configured.

Things you might have to adapt (not exhaustive):

  • Your server name (server_name clauses 2x), i.e. the server part of the URL your Grav installation will be reachable with.
  • The name of the certificate and key you use for SSL / TLS.
  • If and where you want an access log written to.
  • The location where Certbot (or any other ACME client) will put the domain verification challenges.
  • The path under which your Grav installation will be reachable. (The part right to the server name & port section in the URL.)
  • What application server (uWSGI or php-fpm) you are using, i.e. how and where nginx will pass requests that need to trigger some PHP code.

There is no need to install any additional modules since nginx natively supports both protocols FastCGI and uwsgi.

Grav's documentation also covers setting up Grav with nginx. But be aware that the instructions are Ubuntu / Debian centric and do not mention uWSGI.

Apache HTTP Server

Unfortunately upstream Grav doesn't provide a sample configuration file for Apache HTTP Server. At least there is a section in this wiki about how to integrate Apache with PHP by means of php-fpm and mod_proxy_fcgi. uWSGI's documentation has some information about how to integrate Apache with PHP by means of uWSGI and mod_proxy_uwsgi. Mind that the apache package comes with both modules mod_proxy_fcgi and mod_proxy_uwsgi. They need to be loaded as required.


A lot of Grav's power comes from the large set of plugins that can be installed. Just follow the instructions on Grav's documentation how to install plugins. Currently there are no grav-plugin-... packages that allow installing plugins via pacman (or some AUR wrapper). With the exception of the Admin plugin this will probably not change in the foreseeable future.


See the extensive documentation on Grav's website on how to create content with this CMS.


Chances are the big white board named Grav appears too intimidating to you. In this case you may want to use one of the many skeletons as a starting point. Skeletons are prefabricated bundles of Grav itself, some plugins, a theme and some sample content that give you some bits and pieces to play around with. Skeletons are supposed to be installed instead of a bare Grav installation. Unfortunately this makes it impossible to use a skeleton together with the gravAUR package.

With a bit of fiddling you can import the content of an arbitrary skeleton into your existing Grav installation.

Warning: The following procedure will overwrite your current content. If you want to step back make backups of the directories /var/lib/grav/user and /etc/webapps/grav/config.
  1. Download the desired skeleton.
  2. Extract the user directory:
    bsdtar -xf user
  3. Replace the directories pages, plugins and themes in /var/lib/grav/user with the corresponding directories from the extracted user directory.
  4. Fix ownership and permissions
    chown -R grav:http /var/lib/grav/user/{pages,plugins,themes}
    chmod -R 640 /var/lib/grav/user/{pages,plugins,themes}
    find /var/lib/grav/user/{pages,plugins,themes} -type d -exec chmod 750 {} \;
  5. Replace the config files site.yaml system.yaml in /etc/webapps/grav/config with the corresponding files from the extracted user/config.
  6. Fix ownership and permissions
    chown grav:grav /etc/webapps/grav/config/{site,system}.yaml
    chmod 640 /etc/webapps/grav/config/{site,system}.yaml


Note: Migrating from earlier versions of the package has been poorly tested (due to technical reasons). Please help to improve this section.

Migrating from earlier package versions (< 1.7) will most likely require manual intervention. Errors may happen. So backup your data before trying an upgrade from earlier version! This comprises at least the /usr/share/webapps/grav/user directory.

The upgrade will probably fail right away with lots of error messages complaining about files already existing under /usr/share/webapps/grav/vendor. Just delete this directory.

Since the last package version (v1.6.28, 2020-11-18) PHP was upgraded from version 7 to 8. This my render some of your plugins non-functional.

Grav v1.7 has become stricter in many ways. See Grav's migration guide about details.

Do not try to tweak your setup to use system user http as used to be. For good reasons Arch Linux' web application package guidelines dictates to use a dedicated system user (here grav) to run the application.

Probably the best migration strategy is to backup the /usr/share/webapps/grav/user directory, uninstall Grav and all dependent packages, remove all remnants of the Grav installation (including all Grav specific configurations with your web server and application server), update your system (including PHP) and then install Grav from scratch. When everything is set up and your server successfully presents Grav's default page you can start to restore your previous content.


Upgrading Grav itself must exclusively be done by pacman (or some AUR wrapper)!

Warning: Do not try to upgrade Grav itself with gpm as described in Grav's update documentation or via the admin plugin. At best this will simply not work, at worst it will ruin your installation.

To the contrary upgrading plugins and themes must be done with gpm update or via the admin plugin.

Another option is to download ZIP files and copy around stuff in the filesystem. This is not recommended. Only do so when you know exactly what you are doing.