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

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 9.2-RELEASE -nick fbsd9.2 -arch amd64

Note that I chose to do FreeBSD 9.2-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 wish to set an IPv6 address (you can set either or both), use --ipv6 ADDR.

[username@pc-bsd ~]$ sudo warden create PROJECT --ipv4 10.0.0.IPNUM --ports --template fbsd9.2
[username@pc-bsd ~]$ sudo warden start PROJECT
[username@pc-bsd ~]$ sudo warden chroot PROJECT

Jail Configuration

pkgng

Before setting up any of the servers, we need to switch from the old package format to the new one. FreeBSD 10.0 and PC-BSD 9.2 and later already use this format, so you can skip ahead if you're running those. If you're running FreeBSD 9.x in your jail, however, you need to do the following:

# pkg

When it asks for permisison, answer y

Next, we need to run a few commands to set the package system up:

# /usr/local/sbin/pkg2ng
# mkdir -p /usr/local/etc/pkg/repos
# cp /usr/local/etc/pkg.conf.sample /usr/local/etc/pkg.conf
# vi /usr/local/etc/pkg/repos/FreeBSD.conf

Add the following to FreeBSD.conf:

FreeBSD: {
	url: "pkg+http://pkg.FreeBSD.org/${ABI}/latest",
	mirror_type: "srv",
	enabled: yes
}

Next, install some 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/php55
# 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/php55-extensions
# make config

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

As with the php55 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 VM:

10.0.0.IPNUM	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