Passbolt on CentOS 7 with NGINX / PHP7-FPM / MariaDB from scratch

Having some issues when installing passbolt? You can always request some help on the support forum!

You tried installing passbolt on CentOS but things didn’t go as planned ? You are struggling with some parts ? Or you simply want to learn how to have a running instance of passbolt ? Then this step by step tutorial is for you. It covers the installation of passbolt on a freshly installed CentOS 7 environment.

You can get CentOS 7 by downloading it from the official mirrors, by running the corresponding AMI for AWS, or by pulling the CentOS docker container. For this tutorial, all the steps were done on a docker container but were also tested on a AWS machine.

The goal of this tutorial is not to create an hardened installation, but more to create a minimal barebone passbolt instance you can use to test the application locally, before you start building your production environment.

Before we start, I’d like to point out that SvennD had already made a great tutorial about it. However since then, a few installation steps have evolved and we got to know about a few additional pain points faced by the community while installing passbolt on CentOS, hence this updated version was born.

This tutorial was made for passbolt v1.6.4

Base packages

First, we clean the yum cache and the packages accumulated in the /var/cache/yum directory.

yum clean all

1. Nginx

1.1 Add the nginx repository to the list of supported ones.

cat >/etc/yum.repos.d/nginx.repo <<EOL
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/mainline/centos/7/\$basearch/
gpgcheck=0
enabled=1
EOL

1.2. Update dependencies and install nginx package

yum update && yum install nginx -y

2. MariaDB

We will use mariadb here, but you could also use mysql.

2.1. Install MariaDB

yum install mariadb-server -y

2.2. Initialize MariaDB

mysql_install_db --user=mysql -ldata=/var/lib/mysql

2.3. Start MariaDB

/usr/bin/mysqld_safe --datadir='/var/lib/mysql' &

3. PHP7 FPM

3.1. For this demo we will use the PHP7 repositories provided by webtatic. You could also use any other one according to your preferences.

rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm && \
rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm

3.2. Install PHP7 FPM and some other necessary dependencies

yum install php70w-fpm php70w-opcache php70w-gd php70w-mysql php70w-mcrypt php70w-cli php70w-pear php70w-devel gpgme-devel gcc nano -y

3.3. Modify the PHP-FPM configuration so that it uses the nginx user instead of the default (apache). We’ll need to modify the user and group parameters.

nano /etc/php-fpm.d/www.conf

4. PHP GnuPG

We need to install the module PHP GnuPG.

4.1. Install the module through PECL

pecl install gnupg

4.2. Activate the module for PHP

echo "extension=gnupg.so" > /etc/php.d/gnupg.ini

5. Git and rng-tools

5.1 We will need git to be able to download passbolt from its repository.

yum install git -y

5.2. Entropy is required to generate the SSL or GPG keys. Since it can be long to generate entropy (e.g. randomness) on virtual machines we will install rng-tools to ensure that there is enough.

yum install rng-tools git -y

Security note: rng-tools is not magic, as it can only get entropy from the sources available. In other words if your virtual machine has no available sources of entropy then security-wise it will not help. You can check how much entropy is available at any given time, the higher the better. Learn more.

cat /proc/sys/kernel/random/entropy_avail

Configuring the base packages

1. Start Nginx server and PHP-FPM

nginx -g "daemon off;" &
php-fpm

2. Create database for passbolt

You will need to choose a root password and ideally create another database user to control who has access to the database properly. For the sake of simplicity we will just use root in this tutorial.

2.1 Set the password for the database root user. (Don’t forget to replace ‘changeme’ by a password of your choice).

/usr/bin/mysqladmin -u root password 'changeme'

2.2. Create the passbolt database

mysqladmin -u root -pchangeme create passbolt

3. Generate GPG key pair

Passbolt will need its own PGP key to be able to shake hands with the users during the authentication procedure. Use the command below to generate a PGP key pair, and answer the questions.

It’s a good idea to fill in the details properly and not press enter frantically. Make sure you have decent name and email for the key. This will come in handy to identify and verify it down the line.

Important: Currently php-gnupg does not support keys with a passphrase so you will need to leave that field empty.

 gpg --gen-key

Passbolt Installation

1. Download the source code

Download the source code from its git repository and store it in /var/www/passbolt

git clone https://github.com/passbolt/passbolt_api.git /var/www/passbolt

2. Set the correct rights

The web server needs to be able to write in the tmp directory to speed things up during excecution. It also need a place to upload the profile pictures.

chmod +w -R /var/www/passbolt/app/tmp
chmod +w /var/www/passbolt/app/webroot/img/public
chown -R nginx.nginx /var/www/passbolt/

3. Export the GPG keys

We’ll need to export the public and the private key that we created previously. We’ll store the keys in the configuration folder.

Don’t forget to replace email@yourkey.com with the email address you used while generating your key.

gpg --armor --export-secret-keys email@yourkey.com > /var/www/passbolt/app/Config/gpg/server_private_key.key
gpg
--armor --export email@yourkey.com > /var/www/passbolt/app/Config/gpg/server_public_key.key

4. Create the configuration files

4.1. Let’s copy the default configuration files to create our own versions.

cd /var/www/passbolt/app/Config
cp
core.php.default core.php
cp database.php.default database.php
cp app.php.default app.php
cp email.php.default email.php

4.2 Edit the configuration files

We need to edit the security salt, cipherSeed (digit only), and fullBaseUrl (the url where passbolt will be reachable) in core.php. Both values are currently not used, but they may be used in the future, so it is a mandatory step. Choose random values by for example throwing a few dice.

nano core.php

The lines below will have to be modified.

Configure::write('Security.salt', '{salt_of_your_choice}');
Configure::write('Security.cipherSeed', '{cipher_seed_of_your_choice}');

We also want to uncomment and change the App.fullBaseUrl to our selected domain or ip address so that all the links are correctly formatted. This will be used for example to display the avatar images in the notification emails.

Do not forget to uncomment the line. It is commented by default!

Configure::write('App.fullBaseUrl', 'http://{ip_of_your_server}');

4.3. We also need to set the right database name and user credentials in database.php.

nano database.php

You need to fill in the details for your default database server. Here mostly login (e.g. root or whatever user you have created previously), password and database (passbolt).

No need to edit other items, see the diff bellow:

diff database.php.default database.php
73,75c73,75
< 'login' => 'user',
< 'password' => 'password',
< 'database' => 'database_name',
---
> 'login' => 'root',
> 'password' => 'Str0ng#P4ssword',
> 'database' => 'passbolt',

We need to tell the application to use reuse our freshly created gpg keys, as the default ones are insecure. To accomplish this we set the fingerprint and location in app.php (in the GPG Configuration section). Also take a moment to check the other application settings. You may want to allow public registration of users for example.

nano app.php

With the values

// Server private key location and fingerprint
'fingerprint’ => '<your fingerprint>',
'public’ => APP . 'Config' . DS . 'gpg' . DS . 'server_public_key.key',
'private’ => APP . 'Config' . DS . 'gpg' . DS . 'server_private_key.key'

To obtain the fingerprint of your key, you can run the command below.

echo `gpg --fingerprint passboltserver@passbolt.com | sed -n '2p' | rev | awk '{NF=10}1' | rev | sed 's/ //g'`

5. Configure the GPG Keyring for the nginx user

5.1 Retrieve the home directory of the nginx user, this is where the GPG keyring will be stored and used by nginx server. We are in CentOS, so the default location should be /var/cache/nginx

NGINX_HOME=`su -s /bin/bash -c "cd ; pwd;" nginx`
echo $NGINX_HOME

5.2 Create the .gnupg keyring directory and set ownership to nginx user

mkdir $NGINX_HOME/.gnupg
chmod 700 $NGINX_HOME/.gnupg
chown nginx $NGINX_HOME/.gnupg

5.3. Edit the configuration file to use the newly created keyring. The only thing we’ll need to edit is the GPG.env.home entry, and set it with the path of the .gnupg directory (in centos 7: /var/cache/nginx/.gnupg)

nano app.php

Wrapping up

1. Install passbolt

Everything is now ready. We can install passbolt.

cd /var/www/passbolt
su -s /bin/bash -c "app/Console/cake install --no-admin" nginx

You can at that step decide if you want to send anonymous statistics about your passbolt usage. Cool kids do, because it helps the developers to make passbolt better for everyone.

2. Configure Nginx

2.1 Configure pretty urls

Passbolt is installed. We now need to tell nginx how to run it. Among other settings, passbolt needs to be run by a web server configured with url rewriting.

nano /etc/nginx/conf.d/default.conf

Below is an example of configuration you can use in /etc/nginx/conf.d/default.conf

server {
listen 80;
client_body_buffer_size     100K;
client_header_buffer_size 1k;
client_max_body_size 100k;
large_client_header_buffers 2 1k;
client_body_timeout   10;
client_header_timeout 10;
keepalive_timeout 5 5;
send_timeout 10;
root /var/www/passbolt;
# X-Frame-Options is to prevent from clickJacking attack
add_header X-Frame-Options SAMEORIGIN;
#  disable content-type sniffing on some browsers.
add_header X-Content-Type-Options nosniff;
# This header enables the Cross-site scripting (XSS) filter
add_header X-XSS-Protection "1; mode=block";
# This will enforce HTTP browsing into HTTPS and avoid ssl stripping attack
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";
location / {
try_files $uri $uri/ /index.php?$args;
index index.php;
}
location ~ \.php$ {
fastcgi_index index.php;
fastcgi_pass 127.0.0.1:9000;
fastcgi_split_path_info ^(.+\.php)(.+)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SERVER_NAME $http_host;
}
location ~* \.(jpe?g|woff|woff2|ttf|gif|png|bmp|ico|css|js|json|pdf|zip|htm|html|docx?|xlsx?|pptx?|txt|wav|swf|svg|avi|mp\d)$ {
access_log off;
log_not_found off;
try_files $uri /app/webroot/$uri /index.php?$args;
}
}

2.2. Reload nginx configuration

nginx -s reload

3. Deactivate ssl force in passbolt temporarily

We’ll also set App.ssl.force parameter to false in the app.php configuration file, so that we can test that passbolt is already in a working condition. If we keep it to true, passbolt would not let us access it through http and would force https.

nano app/Config/app.php

4. Check that everything is in order

Everything is now in a working condition. We’ll execute the healthcheck command to get a full report about the passbolt installation

app/Console/cake passbolt healthcheck

In our installation, everything seems now in order, except the SSL part which we are going to fix.

We can also see that passbolt is now accessible through a web browser:

If you are impatient to see passbolt in action, continue with the next step: create a first user. Or if you want to complete everything first, then you can jump directly to the emails section.

5. Create the first user

At last, passbolt is up and running! But there is no user yer. So let’s create our first user, the administrator.

app/Console/cake passbolt register_user -u admin@passbolt.dev -f ada -l lovelace -r admin

Follow the link in the terminal to start the setup process, in the browser, for this admin user. Once logged in, we can start creating passwords.

Don’t forget to take a backup of your key during the setup.

Going further

1. Emails

Before inviting other users we need to wrap-up the email configuration in app/Config/email.php. Enter the host, username and password of your SMTP server in the default configuration.

nano app/Config/email.php

We also need a cron job to send periodically the emails from the queue.

yum install crontabs -y
crontab -e

The following will send emails every minutes.

* * * * * /var/www/passbolt/app/Console/cake EmailQueue.sender > /var/www/passbolt/app/tmp/email.log

2. Configure HTTPS

It is recommended to use https with passbolt (and, well, pretty much everything). To setup SSL we need a certificate. Here for the sake of brevity we will create a self-signed certificate. Of course you are free to use a proper free certificate and tidy up the server supported cypher suites.

In the following steps, we’ll generate a self signed certificate and configure nginx and passbolt to use https.

2.1 Generate the self signed certificate

openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 -subj "/C=FR/ST=Denial/L=Springfield/O=Dis/CN=www.passbolt.local" -keyout /etc/ssl/certs/passbolt.key -out /etc/ssl/certs/passbolt.crt

2.2 Make sure the certificate is readable by nginx

chown root:nginx /etc/ssl/certs/passbolt.crt
chown root:nginx /etc/ssl/certs/passbolt.key
chmod 640 /etc/ssl/certs/passbolt.crt
chmod 640 /etc/ssl/certs/passbolt.key

2.3. Configure nginx for https

nano /etc/nginx/conf.d/default.conf

Add the following configuration

server {
listen 443;
  ssl on;
ssl_certificate /etc/ssl/certs/passbolt.crt;
ssl_certificate_key /etc/ssl/certs/passbolt.key;
ssl_protocols TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS;
ssl_session_tickets off;
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
root /var/www/passbolt;
# X-Frame-Options is to prevent from clickJacking attack
add_header X-Frame-Options SAMEORIGIN;
#  disable content-type sniffing on some browsers.
add_header X-Content-Type-Options nosniff;
# This header enables the Cross-site scripting (XSS) filter
add_header X-XSS-Protection "1; mode=block";
# This will enforce HTTP browsing into HTTPS and avoid ssl stripping attack
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";
location / {
try_files $uri $uri/ /index.php?$args;
index index.php;
}
location ~ \.php$ {
fastcgi_index index.php;
fastcgi_pass 127.0.0.1:9000;
fastcgi_split_path_info ^(.+\.php)(.+)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SERVER_NAME $http_host;
}
location ~* \.(jpe?g|woff|woff2|ttf|gif|png|bmp|ico|css|js|json|pdf|zip|htm|html|docx?|xlsx?|pptx?|txt|wav|swf|svg|avi|mp\d)$ {
access_log off;
log_not_found off;
try_files $uri /app/webroot/$uri /index.php?$args;
}
}

2.4. Reload configuration

nginx -s reload

We’ll need to change the passbolt configuration to make him use https instead of http, and force the redirection to https:

nano /var/www/passbolt/app/Config/app.php

2.5. Set App.ssl.force to true

nano /var/www/passbolt/app/Config/core.php

2.5. Set App.fullBaseUrl to https

That’s it! Passbolt is now ready to be used with https.

You will notice that the passbolt plugin tells you that the plugin is not configured to work with this domain. This is normal since it was already configured to work with http, and not https.

That’s not an issue, you can fix this easily by clicking on “recover an existing account”

That’s it!

Do let us know if you run into problems following this tutorial on the support forum. You can also check our help section directly on our website.

Thank you for trying out passbolt!

If you like passbolt you should consider giving some love back. No need to be a developer: every little help count. For example you can write a review on chrome web store or firefox addon marketplace, or give a star on github. Do you want to know more?