Install Neos CMS on Ubuntu 20.04 LTS

Updated on June 4, 2021
Install Neos CMS on Ubuntu 20.04 LTS header image

Introduction

Neos CMS is a free and open-source Content Management System (CMS) available under the GPL v3 license or later. Neos CMS has many valuable features that appeal to both content editors and developers, such as inline editing, full Unicode support, complete internationalization, and built-in SEO. It's easy to combine Neos CMS with other modern front-end technologies using JSON or GraphQL export formats.

This tutorial explains how to install Neos CMS on Ubuntu 20.04 LTS and optionally set up HTTPS using a Let's Encrypt TLS certificate.

Prerequisites

This tutorial assumes you own a domain name such as example.com, and you have pointed it to the server IP address. If not, replace example.com with the server IP address.

Make sure to replace example.com in the code examples with your domain name or IP address.

1. Install PHP 7.4

Log in to the server as a non-root sudo user via SSH.

Install PHP-FPM and other required PHP extensions.

$ sudo apt install unzip php-fpm php-mbstring php-tokenizer php-xml php-mysql php-imagick php-zip -y

To enhance the security of your server, create a dedicated user named neos as the user/group of PHP-FPM processes for Neos CMS. This user also owns the Neos CMS source code files.

$ sudo adduser neos

Every time you want to add, delete, or update the source code files, you need to switch to this user.

Create the configuration file from the default one.

$ sudo cp /etc/php/7.4/fpm/pool.d/www.conf /etc/php/7.4/fpm/pool.d/neos.conf

Rename the default file to disable it and keep it as a backup.

$ sudo mv /etc/php/7.4/fpm/pool.d/www.conf /etc/php/7.4/fpm/pool.d/www.conf.default

Open the /etc/php/7.4/fpm/pool.d/neos.conf file.

$ sudo nano /etc/php/7.4/fpm/pool.d/neos.conf

In the configuration file, any line starting with ; is a comment.

Search for the following settings, then:

  1. Replace [www] with [neos]
  2. Replace user = www-data with user = neos
  3. Replace group = www-data with group = neos (do not touch the listen.group = www-data setting)

Make sure the listen = /run/php/php7.4-fpm.sock setting does not start with ;

Copy and paste the following settings to the end of the file.

php_flag[display_errors] = off
php_admin_value[error_log] = /var/log/fpm-php/neos/error.log
php_admin_flag[log_errors] = on

Those settings make PHP-FPM log error messages to the /var/log/fpm-php/neos.error.log file instead of displaying them to website users.

Save the configuration file and exit. Then create the log folder.

$ sudo mkdir -p /var/log/fpm-php/neos

Make the log folder writable by PHP-FPM processes.

$ sudo chown neos:neos /var/log/fpm-php/neos

Check the new configuration.

$ sudo php-fpm7.4 -t

Reload PHP for the changes to take effect.

$ sudo systemctl reload php7.4-fpm.service

2. Install MySQL 8.0

Install MySQL server.

$ sudo apt install mysql-server -y

Run the mysql_secure_installation script to improve security and set the password for the root user.

$ sudo mysql_secure_installation

To enforce strong passwords, press Y to set up the VALIDATE PASSWORD component. Then press 1 to select the MEDIUM password policy, which is secure enough.

You can use a free password manager like KeePassXC or an online tool such as Random Password Generator to generate strong passwords.

Enter a strong password twice for the MySQL root user. Then press Y to confirm.

For other questions, press Y to confirm.

When finished, connect to the MySQL command line as the root user.

$ sudo mysql -u root -p

Create a MySQL database named neos for Neos CMS.

mysql> CREATE DATABASE neos CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Create a MySQL user named neos for Neos CMS. Replace password with a strong password.

mysql> CREATE USER 'neos'@'localhost' IDENTIFIED BY 'password';
mysql> GRANT ALL PRIVILEGES ON neos.* TO 'neos'@'localhost';
mysql> FLUSH PRIVILEGES;
mysql> exit

3. Install Neos CMS

Install Composer, the PHP dependency manager.

$ cd ~ && curl -sS https://getcomposer.org/installer | php

Make the composer command globally available.

$ sudo mv composer.phar /usr/local/bin/composer

Create a folder to store the Neos CMS source code.

$ sudo mkdir -p /var/www/neos

Set neos as the owner of the source code folder.

$ sudo chown neos:neos /var/www/neos

Switch to the neos user.

$ sudo su neos

Fetch the Neos CMS source code using Composer. Be patient because this process may take a while.

$ cd /var/www/neos && composer create-project --no-dev neos/neos-base-distribution .

If you see the Do you want to remove the existing VCS (.git, .svn..) history? [Y,n]? message, press Enter.

Generate all required libraries such as jQuery, Bootstrap, CKEditor.

$ ./flow resource:publish

Don't worry if you see some error messages because the command still generates the whole set of required libraries.

Switch back to the sudo user to continue with the setup.

$ exit

4. Install Nginx

Install Nginx web server.

$ sudo apt install nginx -y

Disable the default configuration.

$ sudo rm /etc/nginx/sites-enabled/default

Create a new configuration for Neos CMS.

$ sudo nano /etc/nginx/sites-available/neos-http.conf

Paste the following contents:

server {
  listen 80 default_server;
  listen [::]:80 default_server;

  server_name  example.com;

  root   /var/www/neos/Web;
  index index.php;

  location ~ /_Resources/ {
    access_log off;
    log_not_found off;
    expires max;

    if (!-f $request_filename) {
      rewrite "/_Resources/Persistent/([a-z0-9]{40})/.+\.(.+)" /_Resources/Persistent/$1.$2 break;
      rewrite "/_Resources/Persistent(?>/[a-z0-9]{5}){8}/([a-f0-9]{40})/.+\.(.+)" /_Resources/Persistent/$1.$2 break;
    }
  }

  location / {
    try_files $uri $uri/ /index.php?$args;
  }

  # Pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
  location ~ \.php$ {
    include        snippets/fastcgi-php.conf;
    fastcgi_pass   unix:/run/php/php7.4-fpm.sock;
    fastcgi_param  FLOW_REWRITEURLS  1;
    fastcgi_param  FLOW_CONTEXT      Production;
    fastcgi_param  X-Forwarded-For   $proxy_add_x_forwarded_for;
    fastcgi_param  X-Forwarded-Port  $proxy_port;
    fastcgi_param  SERVER_NAME       $http_host;
    fastcgi_split_path_info ^(.+\.php)(.*)$;
    fastcgi_read_timeout         300;
    fastcgi_buffer_size          128k;
    fastcgi_buffers              256 16k;
    fastcgi_busy_buffers_size    256k;
    fastcgi_temp_file_write_size 256k;
  }
}

Save the configuration file and exit. Then enable the new configuration.

$ sudo ln -s /etc/nginx/sites-available/neos-http.conf /etc/nginx/sites-enabled/neos-http.conf

Add the www-data user to the neos group so that Nginx processes can access the Neos CMS source code folder.

$ sudo usermod -aG neos www-data

Check the new configuration.

$ sudo nginx -t

Reload Nginx for the changes to take effect.

$ sudo systemctl reload nginx.service

5. (Optional) Configure HTTPS

If you own a valid domain name, you can set up HTTPS for your Neos CMS at no cost. Using the Certbot program, you can get a free TLS certificate from Let's Encrypt, a certificate authority.

Install Certbot with Snap

Ubuntu has built-in Snap Store support that makes it easy to get the latest version of Certbot with features like automatic certificate renewal.

$ sudo snap install --classic certbot

Make the certbot command globally available.

$ sudo ln -s /snap/bin/certbot /usr/bin/certbot

Get a Let's Encrypt Certificate

Run the following command and press Y when prompted.

$ sudo certbot certonly --webroot -w /var/www/neos/Web -d example.com -m admin@example.com --agree-tos

When finished, certbot tells you the path of your certificate file and key file:

/etc/letsencrypt/live/example.com/fullchain.pem
/etc/letsencrypt/live/example.com/privkey.pem

Another critical file, located in the same folder, also needed for the next step is chain.pem.

Install the Certificate with Nginx

Generate a file with DH parameters for DHE ciphers.

$ sudo openssl dhparam -out /etc/nginx/dhparam.pem 2048

2048 is the size of DH parameters. This process may take a while, so please be patient.

Rename the old configuration file.

$ sudo mv /etc/nginx/sites-available/neos-http.conf /etc/nginx/sites-available/neos-https.conf

Update the new file to support TLS.

$ sudo nano /etc/nginx/sites-available/neos-https.conf

Find the following lines:

  listen 80 default_server;
  listen [::]:80 default_server;

Replace them with:

  listen 443 ssl http2;
  listen [::]:443 ssl http2;

  ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

  ssl_session_timeout 1d;
  ssl_session_cache shared:MozSSL:10m;  # about 40000 sessions

  # DH parameters file
  ssl_dhparam /etc/nginx/dhparam.pem;

  # intermediate configuration
  ssl_protocols TLSv1.2;
  ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
  ssl_prefer_server_ciphers off;

  # HSTS (ngx_http_headers_module is required) (63072000 seconds)
  #
  # Uncomment the following line only if your website fully supports HTTPS
  # and you have no intention of going back to HTTP, otherwise, it will
  # break your site.
  #
  # add_header Strict-Transport-Security "max-age=63072000" always;

  # OCSP stapling
  ssl_stapling on;
  ssl_stapling_verify on;

  # verify chain of trust of OCSP response using Root CA and Intermediate certs
  ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;

  # Use Cloudflare DNS resolver
  resolver 1.1.1.1;

Save the configuration file and exit. Then enable the new configuration.

$ sudo ln -s /etc/nginx/sites-available/neos-https.conf /etc/nginx/sites-enabled/neos-https.conf

Create another configuration file for Neos CMS to redirect HTTP requests.

$ sudo nano /etc/nginx/sites-available/neos-http.conf

Paste the following contents:

server {
  listen 80 default_server;
  listen [::]:80 default_server;

  server_name example.com;

  root /var/www/neos/Web;

  location / {
      return 301 https://$server_name$request_uri;
  }

  location /.well-known/acme-challenge/ {}
}

This configuration makes Nginx redirect all HTTP requests, except those from Let's Encrypt, to corresponding HTTPS requests.

Save the configuration file and exit. Then check the Nginx configuration.

$ sudo nginx -t

Apply the new configuration.

$ sudo systemctl reload nginx.service

Automate Renewal

Let's Encrypt certificates are valid for 90 days, so you must renew your TLS certificate at least once every three months. The Certbot installation automatically created a systemd timer unit to automate this task. Run the following command to verify the timer is active.

$ sudo systemctl list-timers | grep 'certbot\|ACTIVATES'

After renewing the certificate, Certbot will not automatically reload Nginx, so Nginx still uses the old certificate. You must write a script inside the /etc/letsencrypt/renewal-hooks/deploy folder to reload Nginx.

Open your text editor.

$ sudo nano /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh

Paste the following contents into the editor:

#!/bin/bash

/usr/bin/systemctl reload nginx.service

Save and exit. Then make the script executable.

$ sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh

Test the renewal process with a dry run.

$ sudo certbot renew --dry-run

This Vultr article explains all the above steps in more detail. This kind of TLS setup gives you an A on the SSL Labs test.

6. Configure Neos CMS

Restart the server to see if everything is working fine.

$ sudo reboot

Open the http://example.com/setup link in your browser. Wait a while for Neos CMS to initialize the setup tool. Then you will see the login screen.

Login screen

To get the setup password, log in to the server as a non-root sudo user via SSH.

Display the password.

$ sudo cat /var/www/neos/Data/SetupPassword.txt

Copy and paste it into the login screen. Then click the Login button to proceed.

Click the Next button in the Neos requirements check screen.

Neos requirements check

In the Configure database screen:

  • Select the MySQL/MariaDB via PDO option for DB Driver.
  • Enter neos for DB Username.
  • Enter the database password you created in step 2 for DB Password
  • Enter 127.0.0.1 for DB Host.
  • Select the neos option for DB Name.

Neos requirements check

Click Next to go to the Create administrator account screen. Then enter your desired credentials and click Next.

Neos Create administrator account

In the Create a new site screen:

  • Select the Neos.Demo option for Select a site package.
  • Leave other options blank.

Neos Create a new site

Wait for a while for Neos CMS to install its demo data. When finished, it greets you with the Setup complete screen.

Neos Setup complete

For security reasons, you must log in to the Neos CMS dashboard using the created administrator account to remove the Try me page because that page allows anyone to create an account to manage the site. The dashboard link is http://example.com/neos.

After logging in, select the Try me page from the list on the left and then click the Delete button as shown below.

Neos Delete Try me

Click the Publish all button to apply the changes.

Neos Publish all

Your Neos CMS is now ready. You can start posting articles on it.

References