Installing phpMyAdmin on Nginx using a PPA and SSL

October 2, 2015

This article explains how to install phpMyAdmin on your Nginx server using a Ubuntu PPA (Personal Package Archives), and self-signing an SSL certificate for added security. It assumes you are running Nginx and PHP-FPM.

The motivations for using this setup:

  • No need to manually update phpMyAdmin
  • Take advantage of SSL

Install phpMyAdmin

The PPA ppa:vincent-c/ppa holds stable upstream versions of phpMyAdmin and seems to be updated fairly often.

Install the PPA and the phpMyAdmin package:

1
2
3
sudo add-apt-repository ppa:vincent-c/ppa
sudo apt-get update
sudo apt-get install phpmyadmin

Say yes when it asks whether to use dbconfig-common.

Create a PHP-FPM Pool

PHP-FPM creates a master process that that forwards HTTP requests to one or more child processes. A PHP-FPM pool is a collection of related PHP child processes, and it’s not uncommon to have one such pool for each PHP application.

We’ll create a dedicated PHP-FPM pool and socket for phpMyAdmin. This pool will run as the user pma.

First, create the user:

1
adduser pma

Then create a new PHP-FPM pool config file file based on the default www.conf:

1
2
cd /etc/php5/fpm/pool.d/
sudo cp www.conf pma.conf

Edit pma.conf (I’m only showing the directives I’ve changed):

1
2
3
4
5
6
7
8
9
10
[pma]
user = pma
group = pma
listen = /var/run/php5-fpm-pma.sock
pm = ondemand
pm.max_children = 4
pm.process_idle_timeout = 15s;
security.limit_extensions = .php
php_admin_value[error_log] = /var/log/fpm-php.pma.log

Notice the first line: Each pool configuration begins with [pool-name], hence pma is the name of our new pool.

These settings are probably not recommended for your typical PHP website or app; the phpMyAdmin installation will not generate a lot of traffic, so it has been deliberately allocated a small amount of resources (see pm, pm.max_children, pm.process_idle_timeout).

Restart PHP-FPM:

1
sudo service php-fpm restart

Create and install an SSL certificate

Because the only one accessing phpMyAdmin is myself, and because my only concern is that the traffic is encrypted, I’ll use a self-signed certificate.

Create a self-signed SSL certificate:

1
2
3
4
sudo mkdir /etc/ssl/pma
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /etc/ssl/pma/pma.key \
-out /etc/ssl/pma/pma.crt

The question that you must answer correctly is the “Common Name”. Use your domain name or Server IP Address for this field. I will use pma.myserver.example.com.

Create a Server Block

The next step is to create an Nginx server block (“Virtual Host”) for phpMyAdmin that responds to pma.myserver.example.com.

Create /etc/nginx/sites-available/phpmyadmin.conf:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# Redirect non-SSL to SSL
server {
listen 80;
listen [::]:80;
server_name pma.myserver.example.com;
return 301 https://pma.myserver.example.com$request_uri;
}
server {
listen 443 ssl;
ssl_certificate /etc/ssl/pma/pma.crt;
ssl_certificate_key /etc/ssl/pma/pma.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK;
ssl_prefer_server_ciphers on;
server_name pma.myserver.example.com;
# The phpMyAdmin installation
root /usr/share/phpmyadmin;
index index.php;
client_max_body_size 2m;
charset utf-8;
access_log /var/log/nginx/pma-access.log;
error_log /var/log/nginx/pma-error.log warn;
# Deny access to "hidden" files, including Apache's .htaccess files.
location ~* (?:^|/)\. {
deny all;
access_log off;
log_not_found off;
}
location / {
try_files $uri $uri/ =404;
}
location ~ /(libraries|setup) {
deny all;
return 404;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_index index.php;
include fastcgi.conf;
fastcgi_pass unix:/var/run/php5-fpm-pma.sock;
}
}

Notes:

  • This file actually creates two server blocks: the first is for redirecting non-HTTPS traffic to HTTPS.
  • The cipher list (ssl_ciphers) is taken from the Mozilla Wiki’s Security/Server Side TLS article. Their recommendation is subject to change.
  • There are many more SSL options that are worth looking into.

Then you must then enable the server block:

1
sudo ln -s /etc/nginx/sites-available/phpmyadmin.conf /etc/nginx/sites-enabled/phpmyadmin.conf

And reload Nginx’s configuration files:

1
sudo service nginx reload

Configure phpMyAdmin

phpMyAdmin’s configuration file is located at /etc/phpmyadmin/config.inc.php (this path is set in /usr/share/phpmyadmin/libraries/vendor_config.php).

However, some of the configuration files that are included by /etc/phpmyadmin/config.inc.php will not be readable if your PHP-FPM pool runs as a user other than www-data. This is because they’re owned by root:www-data. Fix this:

1
2
3
sudo chown root:pma /var/lib/phpmyadmin/config.inc.php
sudo chown root:pma /var/lib/phpmyadmin/blowfish_secret.inc.php
sudo chown root:pma /etc/phpmyadmin/config-db.php

Force using HTTPS while accessing phpMyAdmin by adding the following to /var/lib/phpmyadmin/config.inc.php:

1
$cfg['ForceSSL'] = true;

Notes

  • When configuring your Nginx server, you should take a look at HTML5 Boilerplate’s Nginx Server Configs documentation. It provides some great tips and best practices.
  • For SSL/TLS servers, you should test your configuration with SSL Lab’s SSL Server Test. Note that this test will fail if you use a self-signed certificate.
  • Your phpMyAdmin installation should be protected with strong passwords. Ideally, you won’t need to expose it to the web.