Balling’s Bits

Setting Up Nginx and PHP-FPM in an OmniOS Zone

Start by configuring a zone and install the Joyent/SmartOS package manager.

Then install Nginx and PHP-FPM (v5.5):

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
pkgin install nginx php55-fpm
calculating dependencies... done.
nothing to upgrade.
7 packages to be installed: xmlcatmgr-2.2nb1 perl-5.20.0nb2 pcre-8.35nb1 php-5.5.16 libxml2-2.9.1nb2 nginx-1.6.0 php55-fpm-5.5.16 (28M to download, 105M to install)
proceed ? [Y/n] y
downloading packages...
[...]
nginx-1.6.0: Creating group ``www''
nginx-1.6.0: Creating user ``www''
[...]
============================================================================
This package has SMF support.  You may use svcadm(1M) to 'enable', 'disable'
or 'restart' services.  To enable the instance(s) for this package, run:

        /usr/sbin/svcadm enable svc:/pkgsrc/nginx:default

Use svcs(1) to check on service status.  See smf(5) for more information.
============================================================================
[...]
installing php55-fpm-5.5.16...
php55-fpm-5.5.16: copying /opt/local/share/examples/php/php-fpm.conf to /opt/local/etc/php-fpm.conf
============================================================================
This package has SMF support.  You may use svcadm(1M) to 'enable', 'disable'
or 'restart' services.  To enable the instance(s) for this package, run:

        /usr/sbin/svcadm enable svc:/pkgsrc/php-fpm:default

Use svcs(1) to check on service status.  See smf(5) for more information.
============================================================================

As seen above a www user and www group is created for Nginx/web content. Start the Nginx web-server:

1
svcadm enable nginx

Browse to http://ip-address, and you should see the Nginx welcome page.

Here is a minimal Nginx configuration file (/opt/local/etc/nginx/nginx.conf) to enable PHP-FPM:

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
user   www  www;
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       /opt/local/etc/nginx/mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    server {
        listen       80;
        server_name  localhost;

        location / {
            root   /www;
            index  index.php index.html index.htm;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   share/examples/nginx/html;
        }

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        location ~ \.php$ {
            root           /www;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include        /opt/local/etc/nginx/fastcgi_params;
        }
    }
}

Create a /www directory to hold html/php files and create an index.php file:

1
2
3
<?php
phpinfo();
?>

Then restart Nginx and start PHP-FPM:

1
svcadm disable nginx && svcadm enable nginx && svcadm enable php-fpm

Browse to http://ip-address to verify that the PHP installation is working and to view PHP information.

Extensions

Search for available PHP extensions:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
pkgin search php55-*
php55-zlib-5.5.16nb1  PHP extension for zlib compression
php55-zip-5.5.16     PHP extension for ZIP archive handling
php55-zendoptimizerplus-7.0.0  Zend opcode cache and optimizer for PHP
php55-yaz-1.1.1nb9   PHP extension for YAZ
php55-xsl-5.5.16nb1  PHP extension for XSLT functions
php55-xmlrpc-5.5.16  PHP extension for XML-RPC support
php55-wddx-5.5.16    PHP extension for WDDX support
php55-uploadprogress-1.0.1  PHP extension to track progress of a file upload
php55-tt-rss-fever-plugin-1.2  Fever emulation plugin for Tiny Tiny RSS
php55-tt-rss-1.12    Tiny Tiny RSS is an open source web-based RSS feed reader
php55-tiki6-6.8nb1   Tiki Wiki CMS Groupware web-based application
php55-tidy-5.5.16    PHP extension for tidy functions
php55-sysvshm-5.5.16  PHP extension for SysV shared memory support
php55-sysvsem-5.5.16  PHP extension for SysV semaphore support
php55-sysvmsg-5.5.16  PHP extension for SysV IPC Message Queues support
php55-ssh2-0.12      PHP bindings to the functions of libssh2
php55-ssdeep-1.0.2   PHP extension for ssdeep
[...]

To install a PHP extension install it, add the extension to /opt/local/etc/php.ini, and then restart PHP-FPM:

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
pkgin -y install php55-gd
calculating dependencies... done.

nothing to upgrade.
4 packages to be installed: png-1.6.12 libjpeg-turbo-1.3.0nb1 freetype2-2.5.3nb1 php55-gd-5.5.16nb1 (2201K to download, 6474K to install)

downloading packages...
[...]
installing packages...
installing png-1.6.12...
installing libjpeg-turbo-1.3.0nb1...
installing freetype2-2.5.3nb1...
installing php55-gd-5.5.16nb1...
===========================================================================
$NetBSD: MESSAGE.module,v 1.2 2004/11/05 21:50:11 jdolecek Exp $

To enable this module, add the following to /opt/local/etc/php.ini:

    extension=gd.so

and make sure extension_dir points to the dir where gd.so is.

Then restart your PHP5.5-enabled HTTP server to load this module.
===========================================================================
pkg_install warnings: 0, errors: 0
reading local summary...
processing local summary...
updating database: 100%
marking php55-gd-5.5.16nb1 as non auto-removable

Restart PHP-FPM

1
svcadm restart php-fpm

Now browse to http://ip-address and check that the extension (gd) is enabled.

Obtaining a Free One-Year StartSSL SSL/TLS Certificate

StartSSL offers free 1-year SSL/TLS certificates. The advantage of having a SSL/TLS certificate signed by a certification authority recognised by most recent browsers (and not your own CA) is that these browsers will not issue all kinds of warnings when they read the certificate; instead the browser will present a nice green padlock next to the https-address.

Before you can issue valid SSL/TLS certificates you must own a domain (e.g. wbnet.dk) and validate that you are the owner of the domain, by being able to receive mails from StartSSL to the postmaster address of the domain. Also, you must validate any mail-addresses (e.g. test@wbnet.dk) you plan to use as the contact person in the certificate(s).

Ars Technica has a nice how-to on obtaining a free StartSSL SSL/TLS certificate. The following notes are more of a personal reminder on key and certificate request generation.

In this post-Snowden and post-Heartbleed era I would recommend a separate 4096-bit private key per certificate. Generate a password protected 4096-bit private key:

1
2
3
4
5
6
7
openssl genrsa -des3 -out test.wbnet.dk.private.key 4096
Generating RSA private key, 4096 bit long modulus
...................................++
...................................++
e is 65537 (0x10001)
Enter pass phrase for test.wbnet.dk.private.key:
Verifying - Enter pass phrase for test.wbnet.dk.private.key:

If you do not want to enter the password every time you start your web-server, create a password-less version of the private key:

1
2
3
openssl rsa -in test.wbnet.dk.private.key -out test.wbnet.dk.key
Enter pass phrase for test.wbnet.dk.private.key:
writing RSA key

Make sure the password-less key is kept in a safe place (only stored on the web-server) and is only readable by root (chown root.root and chmod 400)

Proceed to create a certificate signing request (csr) (in this case for a 4096-bit certificate using the sha256 algorithm, since sha1 is deprecated) without a challenge password (important information is the Common Name, i.e. the hostname, and the Email Address):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
openssl req -new -newkey rsa:4096 -sha256 \
  -key test.wbnet.dk.private.key -out test.wbnet.dk.csr
Enter pass phrase for test.wbnet.dk.private.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:DK
State or Province Name (full name) [Some-State]:Hovedstaden
Locality Name (eg, city) []:Roedovre
Organization Name (eg, company) [Internet Widgits Pty Ltd]:wbnet
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:test.wbnet.dk
Email Address []:postmaster@wbnet.dk

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Copy the certificate request:

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
root@www:~# cat test.wbnet.dk.csr
-----BEGIN CERTIFICATE REQUEST-----
MIIEyDCCArACAQAwgYIxCzAJBgNVBAYTAkRLMRQwEgYDVQQIDAtIb3ZlZHN0YWRl
bjERMA8GA1UEBwwIUm9lZG92cmUxDjAMBgNVBAoMBXdibmV0MRYwFAYDVQQDDA10
ZXN0LndibmV0LmRrMSIwIAYJKoZIhvcNAQkBFhNwb3N0bWFzdGVyQHdibmV0LmRr
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtSoD0QpXSIkOoa6WF4Bj
9Eoewr+BxveSHT0J/fBJTP9jI/XErU1WXLgJUbR444upRV/7RQlmWFKVUcVnHpDo
Giv+tznsgtNh/Wi6Xj81o4OEhuTz9l2XLkbCvOPBrun6gydDvphDLYKLqHMDX3VL
HubG87SrCt+8yJ29C8Zppbo4yawEFxJJ+0dgk3gzhYCE9Pfiw0NwPOiGgQ1nSRz9
Ms0UPzgThQwTpNiAr8xOyjoddmAi8POHexeKnedNk4zXoH6rbJ+P41poEkG0oqsM
lt5gtiyPaJNXmPww66pX73uJtbo3lhbv9SmN8EO+LmQ3VIMuzaZ+auTJABUzLXPw
pV/KQlu21/OVvBuCHoGuT0I+u7aU0ppba5XpEjINw9/vjOsoDoYQzS2lJp9zcBeW
e9aXgZM0YSd88DmDqXWMtePj/yrOSIQ/z7+JRcwjsa8jkE0ssloZqfHxAIALnhNg
dkmCHrg18Pzg8pX0hLA2IJBc9BVXpr3w0iS/D87cnRmuh96XpbxK6Y8bsNeHQiP7
strKCYYNt44glpgKgYvAT9C8pqWo+Kl5TPlYwLEssDzZHmuyMwzDx6uQ1CzdKEH6
KrDzh20hpupon5V+Vk86ar915CWzZ/zcW4yjvZ+pQtkNGJb1nGX874AbT2Ge1lfq
yJXfRp1rh8+4w9/RLkkvEe8CAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4ICAQCoCeYA
sXiA4V8VFy5Z2RLQ7ZPc4pIyDMLPtzyx1LIFUEaIhPhhMIpj0GPKwm9QtTiydQh2
VYkwFB3dAeGwMcTe/UMz6EzvWBIIU2OEwgGid2ZcBUcFUK3pOw0AgVhKPOLNtobC
ZxVQYkxNEMny6sBaQ+REi+cqJU7UYiYkhtpuX/IcUfuYoN3jqDoTdgsolaVbQ9pq
/C/19//vpHdzQBh5aWzoD8w6Shd5Bva2B4MflRINiemfnItsYEkA4VwfIGnBms2X
6LdwTscuC6fQG6CCRu4T35yWiERLCKXowRZkP43tBx70LOP8PG6I6w3jSaMfHgV/
FbAL9S7uQ1A+2nBtnrPybfL8kZ2LaOkq/65B3VZwJAvlPONUnXKr9Xq6kJSNgA5W
k2WUhtFA5pVpedYMMX3ucoFTMIDjzcGpFruGLosmncPaJhGzsPbogwh1f+fLB0sq
Lwr82DqJ3wfPha/pJ35qk9F7pS5CBYArAHtn/F96CytnJCtmOX8vX5D26ODDcVqB
MPQJzq0fKNoNCqm9jwJxnBYRCk1vjOyGsPGvtGkAFt2AIoHx7e6r0W4TSd1w8g9S
HaANvpGW2A9k2jGlJ+BqMwRjcG4QD/yLptFKJFwdepWVXC8Umou5oYhjeUCS9byJ
aX/OTfESaktZ7q27jB9mcpUzqNGgJLG2LwT5fw==
-----END CERTIFICATE REQUEST-----

Then go to the StartSSL control panel. Select Certificates Wizard and select Web Server SSL/TLS Certificate in the drop down and click Continue.

On the next page, skip the generation of a private key (Skip). Then paste your Certificate Signing Request into the text box.

Click Continue and then Continue again on the next page. Select the proper domain in which the host (test.wbnet.dk) resides (wbnet.dk) and click Continue.

On the next page, enter the hostname and click Continue.

On the next page click Continue again.

For some hostnames (including test), a manual verification must be made by StartSSL and you will be shown the message below. Otherwise, you will be taken directly to the certificate.

After a short period of time (max 3 hours) go to Control Panel and click Retrieve Certificate. Select the proper certificate in the drop down menu:

Then click Continue. On the next page your signed certificate is displayed in the text area. Copy this text to a file (test.wbnet.dk.pem) .

Next download the StartSSL CA root certificate and class 1 server certificate and concatenate all three certificates into a new certificate:

1
2
3
4
wget https://www.startssl.com/certs/ca.pem
wget https://www.startssl.com/certs/sub.class1.server.ca.pem
# Note, the order of concatenation IS IMPORTANT
cat test.wbnet.dk.pem sub.class1.server.ca.pem ca.pem > test.wbnet.dk.crt

Now deploy the certificate test.wbnet.dk.crt and the private key test.wbnet.dk.key on your web-server. An example configuration for Nginx is shown below:

1
2
3
4
5
6
7
8
9
[...]
  server {
    listen       443;
    server_name  test.wbnet.dk;
    ssl on;
    ssl_certificate      /opt/local/etc/nginx/ssl/wbnet.dk/test.wbnet.dk.crt;
    ssl_certificate_key  /opt/local/etc/nginx/ssl/wbnet.dk/test.wbnet.dk.key;
    [...]
  }