Using FreeNAS to Host a Blog

Back in 1994 I started studying Computer Science at the Vrije Universiteit Amsterdam. One of the courses I took was the Operating Systems one by prof. Andy S. Tanenbaum. During one of his lectures he recommended trying a BSD Unix such as FreeBSD if we were interested in running a more production level grade Unix on our Personal Computers. I happened to have just bought a Pentium 133Mhz system and decided to follow Tanenbaum’s recommendation, installed FreeBSD 2.0, and was hooked onto FreeBSD for approximately 10 years.

In 2005 I was lured by Apple’s promise of a nice graphical user interface on top of a Unix system that felt somewhat similar to FreeBSD. I made the switch and was relatively happy for another 10 years of computing. However, being delivered to the whims of a company that hasn’t always had the best interest of its professional user at heart has started nagging at me more and more in recent years. Apple used to make great hardware, but on the software side it has always been a hit and miss. Now that their new hardware is under severe criticism from their most active users and their software is at an all time low with regard to quality and stability it is time to dust of my BSD skills in preparation to move back to FreeBSD (or OpenBSD, or DragonFlyBSD) as my daily driver.

FreeNAS

Fortunately I already got a FreeBSD based system running at home: my NAS. It’s an FreeNAS Mini from iXsystems. When shopping for a NAS, I choose it over other NAS systems because of the ZFS filesystem; specifically for its checksumming and snapshot capabilities. But today, I will use it specifically for its jail feature to safely host my blog.

Containers, especially Docker, are all the hype these days, but FreeBSD was there first1 with its jail implementation released as part of FreeBSD 4.0 on March 14th, 2000. Just like Linux containers, FreeBSD jails allow you to cleanly separate one environment from other environments on the same system. And even though my blog is a static one, I’d like to prevent this externally exposed part of my NAS from interfering with the unexposed parts.

FreeNAS, the FreeBSD based operating system running on the my NAS, is in a transition to use a new backend for jail creation: iocage. FreeNAS’ current UI can’t yet create iocage based jails. It’s not-enabled-by-default new UI suppossedly can, but I rather use the command line.

Creating a Jail

The jail I’m about to create needs to have an IP address. My router will forward requests to port 80 on my external IP address to port 80 on my jail’s IP address: 192.162.0.201. I choose that IP adress as it falls outside of my routers DHCP scope. The IP address will become an alias on the physical interface, igb0, of my NAS. I will name the jail blog and will base it on FreeBSD 11.1, which happens to be same release of FreeBSD that FreeNAS is based on. This can all be captured in a single iocage command:

# iocage create -n blog \
     ip4_addr="igb0|192.168.0.201/24" \
     -r 11.1-RELEASE \
     boot=on

To verify that the blog jail has indeed been created and started, I issued the command iocage list. This displays a table with an entry for the blog jail:

+-----+------+-------+--------------+---------------+                                                                               
| JID | NAME | STATE |   RELEASE    |      IP4      |                                                                               
+=====+======+=======+==============+===============+                                                                               
| 1   | blog | up    | 11.1-RELEASE | 192.168.0.201 |                                                                               
+-----+------+-------+--------------+---------------+  

Configuring the Jail

Now I need to log into the jail to further configure it. Iocage provides the console command for that:

 # iocage console blog

For easy uploading of the blog from my laptop to the jail I’ll be creating a separate user account guido by means of the command adduser. Be sure to add the user to the group wheel!

Next I’m installing Nginx and sudo:

# pkg install nginx sudo

It will notify you that the package management tool has not yet been installed and asks you whether it should install it. I answered y.

With the package management tool installed it will resolve the dependencies for Nginx and sudo, display them including the amount of disk storage required and asks whether it should proceed:

New packages to be INSTALLED:                                                                                                       
        nginx: 1.12.2_3,2                                                                                                           
        sudo: 1.8.21p2_1                                                                                                            
        pcre: 8.40_1                                                                                                                
        gettext-runtime: 0.19.8.1_1                                                                                                 
        indexinfo: 0.3.1                                                                                                            
                                                                                                                                    
Number of packages to be installed: 5                                                                                               
                                                                                                                                    
The process will require 12 MiB more space.                                                                                         
3 MiB to be downloaded.                                                                                                             
                                                                                                                                    
Proceed with this action? [y/N]:

I answered y again.

Using visudo I uncommented the line:

# %wheel ALL=(ALL) ALL  

All further configuration can now be done as user guido using sudo:

# sudo -u guido -i

Configure SSH

To allow for uploading my blog by means of scp I need to store my SSH public key in the appropriate location.

% mkdir .ssh
% chmod 700 .ssh
% cd .ssh
% vi authorized_keys
<paste public key>
% chmod 644 authorized_keys

By default sshd is not run for a newly created jail. Hence I need to enable it:

% sudo echo 'sshd_enable="YES"' >> /etc/rc.conf
% sudo service sshd start

Configure Nginx

I want my blog served from ~/www, so that directory needs to exist:

% mkdir www

Next I need to point Nginx to it:

% cd /usr/local/etc/nginx
% sudo vi nginx.conf

The default configuration in nginx.conf doesn’t need a lot of changing for my needs. On my 8 processor core NAS I’ve set the worker_processes to 2. Changed the server_name from localhost to kollerie.com blog.kollerie.com www.kollerie.com as my blog will be served from each of those domains. And finally the root for location / is set to /home/guido/www. Here are the relevant bits from nginx.conf:

worker_processes  2;                                                                                                                
                                                                                                                                    
# ...

http {                                                                                                                              
    
    # ...
    gzip  on;                                                                                                                       
                                                                                                                                    
    server {                                                                                                                        
        listen       80;                                                                                                            
        server_name  koller.com blog.kollerie.com www.kollerie.com;                                                                 
                                                                                                                                    
                                                                                                                                    
        location / {                                                                                                                
            root   /home/guido/www;                                                                                                 
            index  index.html index.htm;                                                                                            
        }                        

        # ...
    }

    # ...
}

All that’s left is to enable nginx on start-up and start it:

% sudo echo 'nginx_enable="YES"' >> /etc/rc.conf
% sudo service nginx start

Copy Blog Content to Jail

On my laptop I change directory to my Hugo blog directory, build the blog and copy it to my blog jail:

% cd devel/blog
% hugo
% scp -r public/* guido@192.168.0.201:www

And that’s what you’re currently reading!


  1. if you discount the earlier IBM 360 operating systems from the late 60’s ↩︎