In this blog post we describe the procedure to configure nginx on a FreeBSD VM to use PHP, SSI (Server Side Includes), SSL, and redirects.
We will configure the following server blocks:
- nono.com
- nono.com (SSL)
- www.nono.com (301 permanent redirect to nono.com)
What we want our website to look like

Our final website should look like this: notice the valid SSL cert, the PHP-supplied image and IP address, and the Server Side Includes (the black boxes)
What our website actually looks like
Server Side Includes
We edit nginx.conf (see final version here):
sudo -E vim /usr/local/etc/nginx/nginx.conf
We add the following line to the http stanza:
ssi on;
We save the file and restart nginx:
sudo /usr/local/etc/rc.d/nginx restart
We view the website in our browser to make sure that the SSIs have been honored (in this case, a navbar at the top with home and about links).
Make sure we have flushed our browser’s cache (otherwise we may end up looking at a cached version of the website and falsely assume that our changes failed). The Firefox keyboard shortcut to override the cache and refresh a page on OS X is ⇧⌘R (Shift-Command-R)
Our website now properly inlines the included files; however, the PHP portions are still broken (no picture in the middle from on top, no IP Address listed on the top left next to “Your IP”)

nginx with SSI configured. Although the black boxes appear, the PHP-supplied content is still missing (e.g. image, IP address)
PHP
Installing PHP under nginx is a bit of a slog compared to installing it under Apache (uncomment the appropriate loadmodule, add the .php extension, and restart):
Install PHP-FPM
First, we need to install FreeBSD’s ports collection, which is FreeBSD’s counterpart to OS X’s homebrew. We only need to do this step if ports isn’t installed (i.e. if the directory /usr/ports doesn’t exist).
sudo portsnap fetch
sudo portsnap extract
Next, we install PHP via the ports collection:
cd /usr/ports/lang/php5
sudo make install
When prompted, go with the defaults (the important option is FPM). There will be a chain of dependencies, some of which (e.g. m4, gmake) will prompt you to select options. Again, go with the defaults.
Let’s configure PHP FPM to start on boot and then start it up:
echo 'php_fpm_enable="YES"' | sudo tee -a /etc/rc.conf
sudo /usr/local/etc/rc.d/php-fpm start
Let’s make sure it’s running:
netstat -an | grep 9000
You should see a line similar to this:
tcp4 0 0 127.0.0.1.9000 *.* LISTEN
Configure nginx to use PHP-FPM
Let’s edit nginx.conf:
sudo -E /usr/local/etc/nginx/nginx.conf
We add the following line to the server stanza:
location ~ .php$ {
fastcgi_pass 127.0.0.1:9000;
}
We save the file and restart nginx:
sudo /usr/local/etc/rc.d/nginx restart
We create a test PHP file to make sure that PHP is running properly:
echo "<?php phpinfo(); ?>" > /www/nono.com/phpinfo.php
We browse to our test URI http://shay.nono.com/phpinfo.php. We notice that instead of seeing the PHP configuration information, we see a blank page. PHP is broken. We check the nginx log files in /var/www, but don’t see anything useful. We need to discover where PHP-FPM is logging. To do that, we install and run lsof
(a utility which prints out the open filehandles of the processes on a system, a useful technique to discover where a process’s output is going):
sudo pkg_add -r lsof
lsof | grep php-fpm
In the output, we discover the location of the log files (/var/log/php-fpm.log), which, in retrospect, is an obvious location to look for a log file:
php-fpm 81062 root 2w VREG 0,73 116 1205900 /var/log/php-fpm.log
php-fpm 81062 root 3w VREG 0,73 116 1205900 /var/log/php-fpm.log
We look at the log file (sudo less /var/log/php-fpm.log
). We see nothing but the usual startup messages.
Let’s make sure PHP is configured correctly by running a snippet of PHP code: php -r "phpinfo();"
. Sure enough, it gives the expected output (i.e. a description of the PHP environment information).
PHP seems to be working properly, so let’s turn our attention to PHP-FPM. First, the basics: man php-fpm
.
We notice it has a configuration file; let’s examine it: less /usr/local/etc/php-fpm.conf
.
After reviewing the configuration file, we see it has two directives that we can use to our advantage to troubleshoot the problem:
sudo vim /usr/local/etc/php-fpm.conf # change log_level and run in foreground
log_level = debug
...
daemonize = no
sudo /usr/local/etc/rc.d/php-fpm restart
We browse to our site (http://shay.nono.com/phpinfo.php), still a blank page. And the output from our terminal session tells us nothing. We revert our changes.
In a fit of desperation, we sniff the traffic on port 9000 to see what’s being passed to the PHP-FPM daemon. We start our tcpdump session:
sudo tcpdump -A -ni lo0 port 9000
Then we browse again to our site (http://shay.nono.com/phpinfo.php). We see from the output of tcpdump that nginx is not passing the name of the .php file it needs to execute.
Let’s modify our nginx.conf, add the line to pass the CGI script, and restart the nginx daemon (our current version of our nginx.conf can be seen here)
sudo -E vim /usr/local/etc/nginx.conf # add the following lines
fastcgi_param SCRIPT_FILENAME /www/nono.com$fastcgi_script_name;
include fastcgi_params;
sudo /usr/local/etc/rc.d/nginx restart
We browse again to our site (http://shay.nono.com/). It works! Our output is beautiful:
Redirects
Adding a redirect is simple—we add the following line to nginx.conf:
rewrite ^ https://nono.com$request_uri?;
We restart the nginx daemon, and again browse to our site (http://shay.nono.com/). And we are redirected, but to our old site, our original site, which works fine.
This is not helpful. Rather than being redirected to our old site (i.e. the ARP Networks site), we would rather be redirected to the new site, in Germany (i.e. the Hetzner site). But how can we accomplish this? We want nono.com to resolve to shay.nono.com’s IP address (i.e. 78.47.249.19), but only for our local machine, only until we have finished the migration and are satisfied with the results.
The /etc/hosts override
We are going to use that much-maligned hack, the /etc/hosts override [1] (“universally used, universally despised” is how we characterize it). We edit our /etc/hosts file on our local machine (in this particular case, a 2012 Mac Mini) and add the following line:
78.47.249.19 nono.com
This line has the effect of saying, “I don’t care what the Internet at large thinks the IP address of nono.com, as far as I’m concerned it’s 78.47.249.19”.
We refresh our browser, and we see this message, “Unable to connect. Firefox can’t establish a connection to the server at nono.com.” Our override is working properly because we have never configured the SSL portion of nginx.
SSL
We edit our nginx.conf file, and add the following lines:
server {
server_name nono.com;
listen 443 ssl;
ssl_certificate nono.com.chained.crt;
ssl_certificate_key nono.com.key;
access_log /var/www/nono.com-access.log;
error_log /var/www/nono.com-error.log;
root /www/nono.com;
index index.shtml index.html index.htm;
ssi on;
location ~ .php$ {
ssi on;
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME /www/nono.com$fastcgi_script_name;
include fastcgi_params;
}
}
We also copy our keys into place:
sudo cp nono.com.key nono.com.chained.crt /usr/local/etc/nginx
sudo chown root:wheel /usr/local/etc/nginx/{nono.com.key,nono.com.chained.crt}
We go to extra lengths to protect our .key file, ensuring that only the owner can read it and protect us from accidentally checking it into our public repo.
sudo chmod 400 /usr/local/etc/nginx/nono.com.key
echo '*.key' | sudo tee -a /usr/local/etc/.gitignore
We restart our server:
sudo /usr/local/etc/rc.d/nginx restart
And see the following error message:
nginx: [emerg] the "ssl" parameter requires ngx_http_ssl_module in /usr/local/etc/nginx/nginx.conf:56
We have made a mistake. We installed the stock version of nginx, but it lacks the ngx_http_ssl module, which “is not built by default“. We need to install a custom version, we need to install via ports.
First we uninstall the stock nginx:
sudo pkg_info | grep nginx # look for the exact nginx package name
sudo pkg_delete nginx-1.4.2,1
Let’s install nginx from the ports collection. When presented with the configuration screen, remember to make sure HTTP_SSL
is checked. It should be; it’s the default.
cd /usr/ports/www/nginx
sudo make install
When it has finished installing, we can attempt to start it up again:
sudo /usr/local/etc/rc.d/nginx restart
And browse again to http://shay.nono.com. Success! Our website looks the way we want it to look:

Our final website should look like this: notice the valid SSL cert, the PHP-supplied image and IP address, and the Server Side Includes (the black boxes)
IPv6
To configure nginx to listen on both IPv4 and IPv6, we need to add a second listen
directive for IPv6 ([::]:80;
). Here’s a snippet from our nginx.conf:
server_name _; # invalid value which will never trigger on a real hostname.
listen 80;
listen [::]:80;
Acknowledgements
Stan and Moe have a good post on configure PHP on nginx under FreeBSD.
The nginx site has the canonical instructions for configuring SSL under nginx.
Footnotes
1 Given a hostname, the typical UNIX (Linux, OS X, *BSD) operating system will use the gethostbyname(3) library call to determine the address, (e.g. gethostbyname(“nono.com”) will return a struct which has the IP address 78.47.249.19) (actually it will probably use the getaddrinfo(3) library call, but that’s a topic for another day). There are many levers/overrides to this library call (e.g. there’s the previously mentioned /etc/hosts override, but there is also an acknowledgement that DNS is not always the source of a host’s IP address; other alternative sources include the now-venerable Sun Microsystems’s NIS (a.k.a. “Yellow Pages”) and LDAP). The levers (often configured in a file named either “/etc/nsswitch.conf” or “/etc/hosts.conf”) can specify precedence of various sources of information, e.g. “Check the /etc/hosts file first for the IP address. If not found, check LDAP next, and if you still don’t find the host, check DNS”.
About the Author