Skip to content

Instantly share code, notes, and snippets.

@rnelson
Last active December 30, 2015 17:39
Show Gist options
  • Save rnelson/7862723 to your computer and use it in GitHub Desktop.
Save rnelson/7862723 to your computer and use it in GitHub Desktop.
PC-BSD PHP Jail

About

This gist is my instructions for setting up a jail on PC-BSD/TrueOS to do PHP web development, specifically WordPress. As long as I keep using jails to do project development, I'll keep this document updated.

Initial Setup

Setup for these jails is pretty simple. The first time this is done (or when there's a new release you want to use), first you need to create a Warden template:

[username@pc-bsd ~]$ sudo warden template create -fbsd 10.1-RELEASE -nick fbsd10.1 -arch amd64

The nick is the name you will use to refer to this template when you use warden create and make an actual jail.

Note that I chose to do FreeBSD 10.1-RELEASE/amd64. You can chose nearly any version of FreeBSD, PC-BSD, or TrueOS and any architecture supported by the host OS (likely amd64 and i386). For these one-off development servers, I prefer to stick with a mostly bare bones install of FreeBSD.

Once that's finished, you'll create a new jail for your project, start the jail, and launch a shell into it. Be sure to set an IP in the range your network actually uses if you plan to use it on the network. You can do IPv4 and/or IPv6.

The following creates a jail with an IPv4 address of 10.0.0.3, starts it up, and chroots into it.

[username@pc-bsd ~]$ sudo warden create PROJECT --ipv4=10.0.0.3 --template fbsd10.1
[username@pc-bsd ~]$ sudo warden start PROJECT
[username@pc-bsd ~]$ sudo warden chroot PROJECT

Jail Configuration

pkgng

Before installing packages, you have to install the package tools. Simply run the pkg command; answer y:

# pkg

Now you are able to install packages.

# pkg install bash mutt vim-lite sudo nginx mysql56-server

User

We'll continue setting everything up as root, but once you start development it's obviously best to not work as root. Before we go any further, let's go ahead and set up the user that you'll use later:

# adduser

When it asks for additional groups, specify wheel www

Now, let's give the new user (since it's in the wheel group) full access to sudo:

# visudo

Locate and uncomment %wheel ALL=(ALL) NOPASSWD: ALL.

PHP

Because we want PHP to be set up with FPM support for nginx, we will build that from ports. Update ports, configure PHP, build and install it, then do the same with some PHP extensions:

# portsnap fetch update
# cd /usr/ports/lang/php56
# make config-recursive

In the PHP configuration, turn on the FPM option. Leave the defaults or customize the configurations for anything else as you see fit.

# make install
# cd /usr/ports/lang/php56-extensions
# make config

Turn on the following options: GD, MYSQL, PDO_MYSQL.

As with the php56 port, customize any of options for subsequently built ports as you see fit.

When that finishes, open /etc/rc.conf in an editor and set the PHP FPM server and nginx to start at boot:

php_fpm_enable="YES"
nginx_enable="YES"

Next, we'll create and edit a php.ini file:

# cp /usr/local/etc/php.ini-production /usr/local/etc/php.ini
# vim /usr/local/etc/php.ini

Set the following options:

error_reporting = E_ALL | E_STRICT
cgi.fix_pathinfo = 1
expose_php = Off
upload_max_filesize = 200M
post_max_size = 200M
max_execution_time = 600
max_input_time = 600
memory_limit = 256M
mysql.allow_persistent = Off
register_argc_argv = On
date.timezone = America/Chicago
register_globals = Off
allow_url_fopen = Off
magic_quotes_gpc = Off
magic_quotes_runtime = Off

Obviously, set date.timezone to the timezone you prefer.

nginx

We'll follow a tutorial from bin63 to configure nginx. First, let's create a blank nginx.conf file and create some folders that we'll need:

# mkdir /var/log/nginx
# mkdir -p /usr/local/etc/nginx/conf.d
# rm /usr/local/etc/nginx/nginx.conf
# touch /usr/local/etc/nginx/nginx.conf
# chmod 0444 /usr/local/etc/nginx/nginx.conf
# chown root:wheel /usr/local/etc/nginx/nginx.conf

Now, edit /usr/local/etc/nginx/nginx.conf and put the following in it:

user www www;
worker_processes 4;
error_log /var/log/nginx/error.log crit;
pid /var/run/nginx.pid;
events {
	worker_connections 1024;
}
http {
	include /usr/local/etc/nginx/mime.types;
	default_type application/octet-stream;
	access_log off;
	server_tokens off;
	sendfile on;
	client_max_body_size 200m;
	client_body_buffer_size 1m;
	keepalive_timeout 1;
	port_in_redirect off;
	gzip on;
	gzip_http_version 1.1;
	gzip_vary on;
	gzip_comp_level 6;
	gzip_proxied any;
	gzip_types text/plain text/css application/json application/x-javascript application/xml application/xml+rss text/javascript;
	gzip_buffers 16 8k;
	gzip_disable "MSIE [1-6].(?!.*SV1)";
	include /usr/local/etc/nginx/conf.d/*.conf;
}

Now, create a configuration file, /usr/local/etc/nginx/conf.d/PROJECT_dev.conf, for your specific project. Replace PROJECT with a short name for your project (you'll access the server at http://PROJECT.dev).

server {
        listen 80;
        server_name www.PROJECT.dev;
        rewrite ^ http://PROJECT.dev$request_uri?;
}
server {
        listen 80;
        server_name PROJECT.dev
        server_name_in_redirect off;
        root /var/www/PROJECT.dev;
        location / {
                index index.php;
        }
        location ~ \.php$ {
                fastcgi_pass 127.0.0.1:9000;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME /var/www/PROJECT.dev$fastcgi_script_name;
                include fastcgi_params;
        }
        location ~ /\.ht {
                deny all;
        }
}

Next, create the folder for your project and put a simple phpinfo() file in it to ensure that everything works. Make the user you created earlier own the folder so you can work on it:

# mkdir -p /var/www/PROJECT.dev
# echo "<?php phpinfo();" > /var/www/PROJECT.dev/index.php
# chown -R USERNAME:www /var/www/PROJECT.dev

Now, start the PHP FPM server, nginx, and leave your chroot:

# /usr/local/etc/rc.d/php-fpm start
# /usr/local/etc/rc.d/nginx start

MySQL

While I use PostgreSQL for a lot of things, the projects using these one-off jails generally run on a LAMP stack and I prefer run the same database in development as production. I've found that I can usually get away with swapping the OS and web server, but trying to substitute something for MySQL rarely ends well.

In the initial jail configuration, the mysql56-server package was installed. At present, the FreeBSD ports and packages systems both have MariaDB. Our production servers still run MySQL, so I'm sticking to that for development for now.

First, we need to modify /etc/rc.conf again to set MySQL to start on boot:

mysql_enable="YES"

Next, start the and configure the server. I use all of the defaults in the installation program:

# /usr/local/etc/rc.d/mysql-server start
# mysql_secure_installation

Leave the chroot

Now that the basic configuration is done, let's leave the chroot and start using ssh to work in the new jail:

# exit
[username@pc-bsd ~]$ 

Hosts

You'll want to edit /etc/hosts (C:\WINDOWS\System32\drivers\etc\hosts on Windows) on your workstation and add an entry for your new jail. Be sure to set the IP to whatever v4/v6 address you specified when you created the jail.

10.0.0.3 PROJECT.dev www.PROJECT.dev

WordPress

A lot of the projects I use jails and VMs for are WordPress sites. Assuming you followed all of the above, ssh to your jail (ssh PROJECT.dev) and run the following:

project$ cd /var/www/PROJECT.dev
project$ rm index.php
project$ fetch -o /tmp/wordpress.tar.gz http://wordpress.org/latest.tar.gz
project$ tar zxf /tmp/wordpress.tar.gz
project$ mv wordpress/* .
project$ rm -rf wordpress/
project$ touch wp-config.php
project$ chmod 660 wp-config.php

Next, we need a database:

# mysql -u root -p
mysql> create database PROJECT;
mysql> create user 'PROJECT'@'localhost' identified by 'PASSWORD';
mysql> grant all privileges on PROJECT.* to 'PROJECT'@'localhost' with grant option;
mysql> flush privileges;
mysql> exit

Now that you have a database, you can visit your site at http://PROJECT.dev and run through the WordPress installation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment