Running Artifactory in a FreeNAS Jail

These notes are with respect to FreeNAS 11.3, Artifactory 5.8, and Apache 2.4.

Let’s begin by adding a jail. Within Jails, click Add Jail. Most of this is default. Here are the settings for a currently working config: DHCP Autoconfigure IPv4 unchecked, NAT unchecked, VNET checked, Berkeley Packet Filter checked, IPv4 statically defined, Autoconfigure IPv6 unchecked, Auto-start checked, mount_devfs checked, mount_fedscfs checked, allow_set_hostname checked, all other jail allow_* properties unchecked, Network interface vnet0:bridge0, within Custom Properties host_time checked).

To install Artifactory, we want to get to a shell on the FreeNAS system (ssh works too).
# shell into the jail
$ sudo iocage console artifactory
# install using ports
# if you do not have /usr/ports, run portsnap fetch && portsnap extract
$ cd /usr/ports/devel/artifactory
$ make install clean

Artifactory runs by default on port 8081. A recommended way to access it over HTTP port 80 is to setup Apache as a proxy. Here is a working /usr/local/etc/apache24/Includes/artifactory.conf file.

LoadModule proxy_module libexec/apache24/mod_proxy.so
LoadModule proxy_http_module libexec/apache24/mod_proxy_http.so

<VirtualHost *:80>
  ProxyPreserveHost On
  ProxyRequests Off
  ProxyPass / http://localhost:8081/
  ProxyPassReverse / http://localhost:8081/
</VirtualHost>
Then test and restart Apache.
$ apachectl configtest && apachectl restart

Artifactory should now be available over HTTP (port 80).

Running Git in a FreeNAS Jail

These notes are with respect to FreeNAS 11.3, Git 2.6, and Apache 2.4.

Let’s begin by adding a jail. Within Jails, click Add Jail. Most of this is default. Here are the settings for a currently working config: DHCP Autoconfigure IPv4 unchecked, NAT unchecked, VNET checked, Berkeley Packet Filter checked, IPv4 statically defined, Autoconfigure IPv6 unchecked, Auto-start checked, mount_devfs checked, mount_fedscfs checked, allow_set_hostname checked, all other jail allow_* properties unchecked, Network interface vnet0:bridge0, within Custom Properties host_time checked).

To install Git, we want to get to a shell on the FreeNAS system (ssh works too).
# shell into the jail
$ sudo iocage console git
# install dependencies
$ pkg install git apache24

The next thing to do is create a Git repo within the jail. There are plenty of online references for this, though creating an initial bare repository is the goal.

To use this repo over HTTP, there are some additional configs to setup. Below is the content for the config file at the root of the repo.

[core]
        repositoryformatversion = 0
        filemode = true
        bare = true
        sharedrepository = 1
[receive]
        denyNonFastforwards = true
[http]
        receivepack = true
Also, configure the file system to be modifiable by the Apache user.
$ chown -R www:www /data/git/repos/brian.git

The last bit of work is to configure Apache. Here is a working /usr/local/etc/apache24/Includes/git.conf file where the path /ro/ is used for read-only access to the repository (helpful for CI builds).

LoadModule rewrite_module libexec/apache24/mod_rewrite.so
<IfModule !mpm_prefork_module>
  LoadModule cgid_module libexec/apache24/mod_cgid.so
</IfModule>
<IfModule mpm_prefork_module>
  LoadModule cgi_module libexec/apache24/mod_cgi.so
</IfModule>

<VirtualHost *:80>
  DocumentRoot /data/git/repos

  # Smart-HTTP needs longer timeouts
  Timeout 600

  # Read-only access
  RewriteEngine On
  RewriteCond %{QUERY_STRING} service=git-receive-pack [NC]
  RewriteRule ^ - [E=AUTHREQUIRED:yes]
  SetEnvIf Request_URI ^/ro/.*/git-upload-pack$ AUTHALLOWED
  RewriteCond %{QUERY_STRING} service=git-upload-pack [NC]
  RewriteRule ^/ro/ - [E=AUTHALLOWED:yes]
  <LocationMatch "^/ro/.*">
    Options +Indexes +MultiViews +ExecCGI
    Order allow,deny
    Allow from env=AUTHALLOWED
    Deny from env=AUTHREQUIRED
    Satisfy Any
  </LocationMatch>

  # Read-write access
  <LocationMatch "^(?!/ro)/[^/]+">
    Options +Indexes +MultiViews +ExecCGI
    Order deny,allow
    AuthType Basic
    AuthName "Git"
    AuthUserFile /usr/local/etc/apache24/basic_auth
    require valid-user
  </LocationMatch>

  SetEnv GIT_PROJECT_ROOT /data/git/repos
  SetEnv GIT_HTTP_EXPORT_ALL
  ScriptAlias /ro /usr/local/libexec/git-core/git-http-backend/
  ScriptAlias / /usr/local/libexec/git-core/git-http-backend/
</VirtualHost>
Then test and restart Apache.
$ apachectl configtest && apachectl restart

The Git repo should now be available over HTTP.
# read-only
$ git clone http://.../ro/brian.git
# read-write
$ git clone http://.../brian.git

Running OpenVPN + Google Authenticator in a FreeNAS Jail

These notes are with respect to FreeNAS 11 and OpenVPN 2.4. This post was a great reference for most of this: https://www.ixsystems.com/community/threads/step-by-step-to-install-openvpn-inside-a-jail-in-freenas-11-1-u1.61681/. Much of the below is based on the post, captured below to have that and the Google Authenticator configuration in one place.

Let’s begin by adding a jail. Within Jails, click Add Jail. Here are the settings for a currently working config: DHCP Autoconfigure IPv4 unchecked, VNET checked, Berkeley Packet Filter checked, IPv4 statically defined, Autoconfigure IPv6 unchecked, Auto-start checked, mount_devfs checked, mount_fedscfs checked, allow_set_hostname checked, allow_raw_sockets checked, all other jail allow_* properties unchecked, Network interface vnet0:bridge0, vnet_default_interface auto, within Custom Properties allow_tun checked. The allow_tun in particular is important for OpenVPN.

To install OpenVPN, we want to get to a shell on the FreeNAS system (ssh works too).
# determine jail ID for the newly created jail
$ jls
# shell into the jail
$ jexec /bin/sh
# install dependencies
$ pkg install libqrencode openvpn libpam-google-authenticator

Before configuring OpenVPN, we will setup the certificate authority (CA) and certificates.
$ mkdir /usr/local/etc/openvpn /usr/local/etc/openvpn/keys
$ cp /usr/local/share/examples/openvpn/sample-config-files/server.conf /usr/local/etc/openvpn/openvpn.conf
$ cp -r /usr/local/share/easy-rsa /usr/local/etc/openvpn/easy-rsa
$ cd /usr/local/etc/openvpn/easy-rsa

Edit /usr/local/etc/openvpn/easy-rsa/vars

set_var EASYRSA_REQ_COUNTRY
set_var EASYRSA_REQ_PROVINCE
set_var EASYRSA_REQ_CITY
set_var EASYRSA_REQ_ORG
set_var EASYRSA_REQ_EMAIL
set_var EASYRSA_REQ_OU
set_var EASYRSA_KEY_SIZE
$ ./easyrsa.real init-pki
$ ./easyrsa.real build-ca
$ ./easyrsa.real build-server-full openvpn-server nopass
$ ./easyrsa.real gen-dh
$ openvpn --genkey --secret ta.key
$ cp pki/dh.pem pki/ca.crt pki/issued/openvpn-server.crt pki/private/openvpn-server.key /usr/local/etc/openvpn/keys/
$ cp ta.key /usr/local/etc/openvpn/keys/

# generate client cert for each username
$ ./easyrsa.real build-client-full username
$ cp pki/issued/username.crt pki/private/username.key /usr/local/etc/openvpn/keys/

Configure PAM for Google Authenticator. Edit /etc/pam.d/openvpn

auth required /usr/local/lib/pam_google_authenticator.so secret=/home/${USER}/.google_authenticator

We need to add and configure user accounts for Google Authenticator.
$ adduser -s /usr/sbin/nologin username
$ chsh -s /bin/sh username
$ su username
$ google-authenticator -t -l "OpenVPN home:$USER" -Q utf8 -r3 -R30 -w5 -f -d
$ chsh -s /usr/sbin/nologin username

Configure OpenVPN with Google Authenticator plugin. Note, we are also configuring it to listen on TCP 443 with port-share to 4443, where we will run a web server. The TCP 443 and port share are necessary to enable connections from remote networks where they may only be allowing TCP 443 outbound and doing packet inspection.

Edit /usr/local/etc/openvpn/openvpn.conf

local the.listen.ip.address
port 443
proto tcp
port-share 127.0.0.1 4443
dev tun
ca /usr/local/etc/openvpn/keys/ca.crt
cert /usr/local/etc/openvpn/keys/openvpn-server.crt
key /usr/local/etc/openvpn/keys/openvpn-server.key
dh /usr/local/etc/openvpn/keys/dh.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "route 192.168.1.0 255.255.255.0"
keepalive 10 120
tls-auth /usr/local/etc/openvpn/keys/ta.key
remote-cert-tls client
cipher AES-256-CBC
user nobody
group nobody
persist-key
persist tun
status openvpn-status.log
verb 3
plugin /usr/local/lib/openvpn/plugins/openvpn-plugin-auth-pam.so openvpn

Edit NAT config in /usr/local/etc/ipfw.rules
#!/bin/sh
EPAIR=$(/sbin/ifconfig -l | tr " " "\n" | /usr/bin/grep epair)
ipfw -q -f flush
ipfw -q nat 1 config if ${EPAIR}
ipfw -q add nat 1 all from 10.8.0.0/24 to any out via ${EPAIR}
ipfw -q add nat 1 all from any to any in via ${EPAIR}
TUN=$(/sbin/ifconfig -l | tr " " "\n" | /usr/bin/grep tun)
ifconfig ${TUN} name tun0

Enable in /etc/rc.conf
openvpn_enable="YES"
openvpn_if="tun"
openvpn_configfile="/usr/local/etc/openvpn/openvpn.conf"
openvpn_dir="/usr/local/etc/openvpn/"
cloned_interfaces="tun"
gateway_enable="YES"
firewall_enable="YES"
firewall_script="/usr/local/etc/ipfw.rules"

I will not go into details here (there is plenty of info available online if you Google it), though in the same jail we want to setup a web server (Apache 2.4 is what I used) listening on TCP 4443 for SSL/HTTPS traffic. This is what the OpenVPN port share will send non-openvpn clients to. You can get a free certificate from Let’s Encrypt and automate it’s renewal. Once configured, add it to startup in /etc/rc.conf

apache24_enable="YES"

Configure OpenVPN client
$ cp /usr/local/share/examples/openvpn/sample-config-files/client.conf /usr/local/etc/openvpn/username.conf

Edit /usr/local/etc/openvpn/username.conf

client
dev tun
proto tcp
remote your.fully.qualified.domain 443
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert username.crt
key username.key
remote-cert-tls server
tls-auth ta.key 1
cipher AES-256-CBC
# Send all client traffic through the VPN
redirect-gateway autolocal
# Google Authenticator
ns-cert-type server
auth-user-pass

Restart the jail and give it a test. You should be able to request the 443 destination in a web browser and see the web site listening on TCP 4443’s content. This confirms connectivity to OpenVPN and port share is working. When testing the OpenVPN client, it will ask for the certificate password and then the password, where the Google Authenticator code value is entered as the password.

Chainloading iPXE from PXELINUX

I prefer PXELINUX’s menu system and config, though the TFTP installs can be slow because of using TFTP vs HTTP. We can get the best of both worlds by chainloading iPXE (which supports HTTP) from PXELINUX.

First, download the iPXE kernel to your tftproot
$ wget http://boot.ipxe.org/ipxe.lkrn

Next, place what will be the iPXE config file (or menu) on a local HTTP server

#!ipxe

# defaults
set boot-url http://192.168.88.82/tftproot
set menu-timeout 60000
set submenu-timeout ${menu-timeout}
isset ${menu-default} || set menu-default exit


:start
menu iPXE ${version} Boot Menu (ip ${net0/ip}, mac ${net0/mac})
item --gap -- ------------------------- Installers -------------------------------------
item centos7              Install CentOS 7 x86-64
item ubuntu1604           Install Ubuntu 16.04 LTS amd64 (Xenial Xerus)
item ubuntu1804           Install Ubuntu 18.04 LTS amd64 (Bionic Beaver)
item --gap -- ------------------------- Advanced Options -------------------------------
item shell                Drop to iPXE shell
item reboot               Reboot computer
choose --timeout ${menu-timeout} --default ${menu-default} selected || goto cancel
set menu-timeout 0
goto ${selected}

:cancel
echo You cancelled the menu, dropping you to a shell

:shell
echo Type 'exit' to get the back to the menu
shell
set menu-timeout 0
set submenu-timeout 0
goto start

:failed
echo Booting failed, dropping to shell
goto shell

:reboot
reboot

:exit
exit


:centos7
echo Starting CentOS 7 installer
set base-url ${boot-url}/pxelinux.cfg/installer/centos-7/repo
kernel ${base-url}/isolinux/vmlinuz ksdevice= inst.repo=${base-url}/
initrd ${base-url}/isolinux/initrd.img
boot || goto failed
goto start

:ubuntu1604
echo Starting Ubuntu 16.04 installer
set base-url ${boot-url}/pxelinux.cfg/installer/ubuntu-16.04/amd64 
kernel ${base-url}/linux vga=768
initrd ${base-url}/initrd.gz
boot || goto failed
goto start

:ubuntu1804
echo Starting Ubuntu 18.04 installer
set base-url ${boot-url}/pxelinux.cfg/installer/ubuntu-18.04/amd64
kernel ${base-url}/linux vga=768
initrd ${base-url}/initrd.gz
boot || goto failed
goto start

Finally, we configure a PXELINUX menu item for chainloading iPXE

LABEL -
MENU LABEL Load iPXE (for faster HTTP installs)
  KERNEL ipxe.lkrn
  APPEND dhcp && chain http://192.168.88.82/tftproot/ipxeboot.pxe

PXE Boot RetroPie

SD cards do fail … and often at inconvenient times. Rather than face the loss of saved games, I recently configured my RetroPie to boot off the network using PXE, TFTP, and a NFS root volume.

To start, read the existing documentation on this topic at https://www.raspberrypi.org/documentation/hardware/raspberrypi/bootmodes/net_tutorial.md. Based on that, I did the “client” work of configuring the Pi for USB boot. As I had existing DHCP (MicroTik), as well as TFTP and NFS (FreeNAS), I only needed the file system from my Pi, so I rsync’d that over ssh to the location I wanted to use on the FreeNAS host. Since I am moving the existing root filesystem from the SD card to NFS, I did not remove the ssh host config. After copying the files, I did edit /etc/fstab on the network copy, removing the /dev/mmcblkp1 and p2 lines (only proc should be left) as covered in the tutorial. Finally, before shutting down the Pi and removing the SD Card, grab the serial number by looking at /proc/cpuinfo because we will use it when configuring the TFTP server.

Next, I configured NFS within Services on FreeNAS (number of servers=4, serve UDP NFS clients=checked, Bind IP Address=checked the one listed, allow non-root mount=unchecked, enabled NFSv4=unchecked, NFSv3 ownership model for NFSv4=unchecked, require kerberos for NFSv4=unchecked, mountd bind port=, rpc.statd bind port=, rpc.lockd bind port=, support >16 groups=unchecked, log mountd requests=unchecked, log rpc.statd and rpc.lockd=unchecked). Then in Services, click Start Now to start NFS, and select Start on boot.

For the NFS Share, within Sharing on FreeNAS, I pointed to the path I wanted to use (/mnt/storage/user/retropie/root), and configured mapall user=root, mapall group=wheel, taking defaults for the rest (delete=unchecked, authorized ips/networks=, all directories=unchecked, read only=unchecked, quiet=unchecked, maproot user=, maproot group=).

Now, I’d like to say that all I had to do was copy some files over to the TFTP server and it worked; however, that is not what happened. After a bit of tcpdump and other troubleshooting, I came to find that the Pi insisted on having the TFTP server address be the same as the DHCP server address. This insistence was true for both the MicroTik router as well as an Ubiquiti EdgeRouter 6P. Regardless, what I did instead to get this working was put the Pi’s TFTP files onto the router and use TFTP on the router (instead of the FreeNAS I already had setup).

I will cover the MicroTik config first, as that is what I originally got this working on, and the EdgeRouter next. Within MicroTik, I setup the special DHCP option for the Pi. In DHCP Server, added a new Option (name=piboot, code=43, value=’Raspberry Pi Boot ‘) – note, there are three extra spaces at the end of the value based on reading https://www.raspberrypi.org/documentation/hardware/raspberrypi/bootmodes/net.md. Then, I edited the DHCP Network to add my piboot DHCP Option. Note, on my MicroTik I have the Boot File Name set to pxelinux.0 and Next Server as 192.168.88.217, which still work (the Pi does not use these).

Then, from the Pi’s /boot directory I added these files to the MicroTik under TFTP (all are allow=checked and read only=checked):

Request Filename                 Real Filename
--------------------------------------------------------------
bootcode.bin                     bootcode.bin
bf7072fe/bcm2710-rpi-3-b.dtb     bcm2710-rpi-3-b.dtb
bf7072fe/cmdline.txt             cmdline.txt
bf7072fe/config.txt              config.txt
bf7072fe/fixup.dat               fixup.dat
bf7072fe/kernel.img              kernel.img
bf7072fe/kernel7.img             kernel7.img
bf7072fe/start.elf               start.elf

A couple notes on the above:

  • bf7072fe is the serial number of my Pi (yours will be different, check /proc/cpuinfo)
  • To figure out which files were needed, I used Tools -> Packet Sniffer on the MicroTik with Filter on ports 67, 68, 69 (click Apply, then Start, then Packets)
  • There were several iterations of start packet sniffer filter, reboot Pi, watch Pi fail to boot, stop packet sniffer, view Packets, tweak, try again
  • There were a couple files it was looking for (based on packet sniffing) that did not exist in the /boot directory to begin with … they are not on the TFTP server and it is booting just fine

To configure the EdgeRouter, I started with the DHCP option 43. There are a couple ways you can do this from CLI to GUI, and I did both. I will cover the GUI here since it may be easier for some folks. In EdgeOS, go to the Config Tree and drill down to service, dhcp-server. We will add a global-parameter (click Add):

option option-43 code 43 = string;

Next, drill down into shared-network-name, the LAN the Pi is on, subnet, the subnet address, and add a subnet-parameter:

option option-43 &quot;Raspberry Pi Boot   &quot;;

Click Preview then Save. If you want another reference, there is a support article on Defining Custom DHCP Options.

You can confirm your changes (and the formatting result of " if you wish) by looking at /opt/vyatta/etc/dhcpd.conf (on the CLI, cat /opt/vyatta/etc/dhcpd.conf):

# ... only showing relative lines here ...

# The following 1 lines were added as global-parameters in the CLI and
# have not been validated
option option-43 code 43 = string;

shared-network LAN_1 {
  not authoritative;
  subnet 192.168.1.0 netmask 255.255.255.0 {
    option domain-name-servers 192.168.88.81, 192.168.88.90;
# The following 1 lines were added as subnet-parameters in the CLI and have not been validated
    option option-43 "Raspberry Pi Boot   ";
    option routers 192.168.1.1;
    option bootfile-name "pxelinux.0";
    filename "pxelinux.0";
    next-server 192.168.88.217;
    default-lease-time 86400;
    max-lease-time 86400;
    range 192.168.1.100 192.168.1.254;
  }
}

You can see I still have the “normal” bootfile-name and bootfile-server configured on this subnet, because the Pi ignores them.

Next, I had to install TFTP on EdgeOS (because it is not one of the “built-in” services). There is a support article that covers Adding Debian Packages to EdgeOS:

configure
set system package repository wheezy components 'main contrib non-free'
set system package repository wheezy distribution wheezy
set system package repository wheezy url http://http.us.debian.org/debian
commit
save
sudo apt-get update
sudo apt-get install tftpd-hpa

To then configure TFTP on EdgeOS, I setup the directory structure:

sudo mkdir -p /config/user-data/tftp/bf7072fe
sudo cp bootcode.bin /config/user-data/tftp/bootcode.bin
sudo cp bcm2710-rpi-3-b.dtb /config/user-data/tftp/bf7072fe/bcm2710-rpi-3-b.dtb
sudo cp cmdline.txt /config/user-data/tftp/bf7072fe/cmdline.txt
sudo cp config.txt /config/user-data/tftp/bf7072fe/config.txt
sudo cp fixup.dat /config/user-data/tftp/bf7072fe/fixup.dat
sudo cp kernel.img /config/user-data/tftp/bf7072fe/kernel.img
sudo cp kernel7.img /config/user-data/tftp/bf7072fe/kernel7.img
sudo cp start.elf /config/user-data/tftp/bf7072fe/start.elf
sudo chown -R root:vyattacfg /config/user-data/tftp

… and update the configuration file /etc/default/tftpd-hpa:

TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/config/user-data/tftp"
TFTP_ADDRESS="192.168.1.1:69"
TFTP_OPTIONS="--secure"

You will see I modified the default address from 0.0.0.0 to a specific internal only address on the LAN where the Pi was because I did not want the TFTP server running on the Internet. Finally, a quick restart was all that was needed to get TFTP running (sudo /etc/init.d/tftpd-hpa stop ; /etc/init.d/tftpd-hpa start).

Once you have all the files the Pi needs on the TFTP server, and the NFS volume working, it should network boot as expected.

PXE Network Boot with MicroTik Router and FreeNAS TFTP

Having done a fair amount of computer building and troubleshooting, I find it is helpful to have bootable media with common tools like Memtest. Even more convenient than finding that boot disk and retrieving it, we can boot off the network. The below walks through how to setup network boot with Memtest as an example, though once you have TFTP running you can add more to it (installers, etc).

I am using PXELINUX from the SysLinux project. There are download links on that site, and this is based on version 6.02.

We can start by building out the tftproot file system on the FreeNAS host (/mnt/storage is the root of my volume). The files below are all found within the Syslinux download.

$ ls -la /mnt/storage/tftproot/
-rw-r--r--  1 root  nobody   24040 May 27 17:26 chain.c32
-rw-r--r--  1 root  nobody  122044 May 27 17:26 ldlinux.c32
-rw-r--r--  1 root  nobody  186444 May 27 18:39 libcom32.c32
-rw-r--r--  1 root  nobody   24156 May 27 18:44 libutil.c32
-rw-r--r--  1 root  nobody    1252 May 27 18:38 localboot.c32
-rw-r--r--  1 root  nobody   10700 May 27 17:26 mboot.c32
-rw-r--r--  1 root  nobody   26568 May 27 17:26 menu.c32
-rw-r--r--  1 root  nobody   46545 Oct 13  2013 pxelinux.0
drwxr-xr-x  3 root  nobody       4 May 28 13:56 pxelinux.cfg
-rw-r--r--  1 root  nobody   27076 May 27 17:26 vesamenu.c32

Within the pxelinux.cfg directory, we have the default configuration file, and files/directories to serve over TFTP.

$ ls -la /mnt/storage/tftproot/pxelinux.cfg/
-rw-r--r--  1 root  nobody  107 May 28 15:33 default
drwxr-xr-x  2 root  nobody    3 May 27 12:52 memtest

$ ls -la /mnt/storage/tftproot/pxelinux.cfg/memtest/
-rw-r--r--  1 root  nobody  150024 Aug 23  2013 memtest

The default configuration file is rather basic:

DEFAULT menu.c32
TIMEOUT 300
ONTIMEOUT localboot.c32

LABEL Memtest
  KERNEL pxelinux.cfg/memtest/memtest

The memtest file came from their download page (be sure to grab the pre-compiled bootable binary). I did rename the .bin file to be simply memtest (based on reading http://wiki.seanmadden.net/networking/pxeboot/memtest_over_pxeboot).

The last bit of FreeNAS work is to configure TFTP within Services (directory=/mnt/storage/tftproot, allow new files=unchecked, port=69, username=nobody, umask=022, extra options=). You can then check the box for Start on boot in Services and click Start Now to start TFTP.

Now, the last thing to setup is DHCP on the MicroTik router for PXE. It did take a bit to get this working, because the MicroTik router has named configurations for Next Server and Boot File Name in its DHCP Network configuration, as well as Options (where one can specify things like code 66 for boot server and code 67 for boot file). I originally setup Options, and then added those (via DHCP Options) to the DHCP Network config, though that did not work. What did finally work was to instead specify the Next Server (192.168.88.217) and Boot File Name (pxelinux.0) on the DHCP Network configuration.

Running BIND in a FreeNAS Jail

These notes are with respect to FreeNAS 11 and Bind 9.

The first thing you will need is storage for jails. If this is already setup, you can reuse it. To create it, go to Storage and select the location you want to use, then click Create Dataset. You can name it as you wish … though jails is a handy one. All the other options are defaults (sync=inherit/standard, compression=inherit/lz4, share-type=unix, enable-atime=inherit/on, zfs-deduplicatoin=inherit/off, quotas=0/unlimited, reserved-space=0/none, read-only=inherit/off, record-size=inherit).

Next, we have to add the jail. Within Jails, click Add Jail. Again, any name will do … I chose bind. All the other options are defaults though check the IP address and netmask are what you wish to use (type=standard, ipv4-dhcp unchecked, IP aliases=, IP bridge config=, sysctls=allow.raw_sockets=true, autostart=checked, vimage=checked, NAT=unchecked). If not started, start the jail.

To install Bind, we want to get to a shell on the FreeNAS system (ssh works too).

# determine jail ID for the newly created jail
$ jls

# shell into the jail
$ jexec /bin/sh

# install dependencies
$ pkg install texinfo libedit

# install bind (for this, just took defaults when prompted)
# if you do not have /usr/ports, run portsnap fetch && portsnap extract
$ cd /usr/ports/dns/bind911
$ make install clean

To configure BIND, we edit /usr/local/etc/namedb/named.conf.

It is a good idea to create an acl for the internal network:

acl goodclients {
        192.168.0.0/16;
        localhost;
        localnets;
};

Within “options {“, there are a couple things to configure:

        recursion yes;
        allow-query { goodclients; };
        allow-recursion { goodclients; };
        allow-transfer { none; };

        listen-on { 192.168.88.81; };
        listen-on-v6 { none; };

Note: The listen configurations are which address(es) BIND listens on (this matches the jail’s IP config).

Now, we can validate the config and start the service:

$ named-checkconf
$ service named start
$ service named status

To have this run on startup in our jail, edit /etc/rc.conf (in the jail):

named_enable="YES"
named_program="/usr/local/sbin/named"

By default, resolvconf will try to update /etc/resolv.conf inside the jail which may not be what you want. You can configure a static config. Edit /etc/resolv.conf:

# resolvconf is disabled, see /etc/resolvconf.conf
nameserver 208.67.222.222
nameserver 208.67.220.220
nameserver 8.8.8.8
nameserver 8.8.4.4

Edit /etc/resolvconf.conf:

# disable resolvconf from running any subscribers:
resolvconf="NO"

That should do it. You can restart your jail and ensure /etc/resolv.conf matches expectations.

The listen-on config setup within named.conf is what you will want to configure the clients on your network to use. For example, this internal network has two BIND DNS servers (running on different FreeNAS machines), and so the DHCP configuration for this network sends down two DNS servers: 192.168.88.81 and 192.168.88.90. Specifying two enables the clients to be resilient to failure of any single BIND instance.

After setting this up, I ran DNS Benchmark. This tool is great for testing DNS configuration (from DHCP settings to DNS server performance, of your local servers as well as public ones). The conclusions it showed after running its benchmark proved the local network had optimal DNS configuration.

OpenStack Heat and Load Balancer as a Service

Continuing the OpenStack journey with Icehouse, got Load Balancer as a Service (LBaaS) running (using haproxy) and also explored the orchestration component, Heat.

All the details are over on GitHub, including a Heat template which boots two Nova compute web servers, provisions a load balancer in front of them, as well as obtains and associates a floating IP onto the load balancer VIP.

https://github.com/BrianBrophy/OpenStack-Installation/blob/master/README.md#working-with-orchestration-heat

Bootstrap OpenStack Icehouse On VirtualBox

I have been kicking the tires on OpenStack again. While the DevStack setup is probably most helpful for unit testing, I find it limiting when it comes to playing with OpenStack.

So, I worked through setting-up on a VirtualBox host a classic three-node architecture (control, network, and compute nodes) using Ubuntu 12.04 as my OpenStack host OS with VirtualBox running on Windows. Additionally, I fully scripted the configuration and installation of the OpenStack components on each node so that once you have the base Ubuntu 12.04 server installed on your VMs, you can be up and running on OpenStack in minutes.

If you would like to see more, checkout https://github.com/BrianBrophy/OpenStack-Installation.