From Debian to FreeBSD (3/?)

by , on
last update by Peter Ludikovsky, on

As stated previously, I’m building a new home server and switching the OS at the same time. The background and links to all posts can be found here.

Where we’re at?

The new server is set up to take over NTP and DHCP services, and the Jails for both DNS and the common Tor node have been created. And the Jails are my biggest issue at the moment. Or, to be exact, creating many jails in an automated way.

While checking for a way to manage my jails with Ansible I stumbled across this iocage role by Direction des Systèmes d’Information at Centrale Marseille, which ensures that iocage is installed and properly set up. Only, the documentation is crap, and some functionality doesn’t work as advertised. For example, it provides a way to set the resolver settings for a jail, but screws up quoting so it won’t work. The documentation makes it look like one can both create and change settings of a jail when using state: present, but setting changes only happen when explicitly using state: set. But that’s stuff I can work around, especially the resolver stuff, as I can just as easily set these (if needed) through an ansible playbook.

My biggest issue at the moment is avoiding redundancies in the playbook. Aside from the assigned IP, all jails share mostly the same settings. So the obvious solution would be to define a variable with default settings, and add the settings for each IP at runtime. Only, no, as variables in Ansible apparently become imutable during runtime. OK, next idea: create a dictionary (aka hash table) with the settings, and loop through that. Won’t work either, because (and this is the reason why “variables” aren’t all that variable) looping through with the Jinja2 loops provided won’t make Ansible interpolate the values.

So for now I’m stuck with 3 tasks for each jail (creation, parameter change, and restart, with state dependencies to avoid unnecessary runs) that I have to copy/paste for every new jail. So if anyone got an idea on how to avoid this and rework it into a nice looping construct, drop me a line.

Things I’ve heard about but didn’t try yet:

  • Looping over includeded playbooks with variables passed through
  • Using loops to create the playbook from a template, and include that

Data migration

The old machine is using about 2TiB of data right now, which has to be transferred over too. For this I’m really glad that I already had ZFS running. I just have to create a snapshot of the dataset to transfer, and can send this to the new machine via SSH thanks to zfs send/zfs receive. Once I’m ready to move over the service, it’s just another snapshot, which can then be transferred incrementally, only sending the changed blocks (instead of the whole file). But, since the old machine can, for whatever reason, only push about 20MiB/s, this initial sync is going to take a while. All the more time to get Ansible bent to my will…