Vagrant: Creating a FreeBSD 11 base box (virtualbox) – pt. 2

The previous post discussed what Vagrant is, explained the installation (on FreeBSD), detailed the process of creating a new VM and briefly described how to install FreeBSD 11. The next step is to prepare the fresh installation for Vagrant and eventually create an actual base box from it. If you’re new to VirtualBox or you don’t know what a provider is when it comes to Vagrant, you might want to read the first part. If you however already have a decent idea of virtualization and making sensible choices when installing FreeBSD, just do a fresh install in a VM and continue reading here.

If you haven’t read the first part: These two posts weren’t written without cause. The idea was to dive into Bacula (a program for doing backups). For testing backups properly you need more than one machine obviously. I don’t have enough spare PCs, so using Virtual Machines seemed like a good way of working around that limitation. Since Vagrant makes working with these VMs really easy, it totally makes sense to use it. I’ve used it quite a bit in the past and while I was at it again, I decided to blog about this great tool so that you maybe consider adding it to your tool set as well.

Preparing the VM for Vagrant: Settings

There are a few things on the side of the guest system that need to be in place so that Vagrant can work with it properly.

The first step is optional but considered good practice if you intend to create a public base box: Disable unneeded resources! To do so, go to the settings of your VM template in the VirtualBox GUI.

Selecting VM settings

A good candidate to disable is audio support which is not generally needed in a Vagrant box.

Disabling audio for the VM

Also deactivate USB support. It’s enabled by default but is most likely unneeded in Vagrant boxes (there are other ways to share data between the VM and the host system).

Disabling USB for the VM

Now fire up your fresh FreeBSD 11 system and log in as root. A little tweak that I suggest is to disable the auto delay of the boot loader. This will make the VM boot up 10 seconds faster because it won’t wait for possible user interaction at the boot loader stage. To do so, you can use the following command:

# echo autoboot_delay="-1" >> /boot/loader.conf

Preparing the VM for Vagrant: Packages

If you’re not using a new version that was just released a few days ago, it’s always a good idea to update the base system first:

# freebsd-update fetch install

Reboot if the kernel was updated:

# shutdown -r now

The FreeBSD package manager (pkg) ist not part of the base system (that way it can evolve faster) so let’s bootstrap it first:

# env ASSUME_ALWAYS_YES=yes pkg install pkg

Vagrant needs sudo to work. And not having bash available works but doesn’t make Vagrant happy. It’s best to just install both:

# pkg install -y sudo bash

Now configure sudo. The configuration file is /usr/local/etc/sudoers on FreeBSD – but you may want to forget that again as you shouldn’t touch that file by hand! Rather issue the command

# visudo

which will call a wrapper script that lets you edit the file and check it for validity before actually saving changes. Why’s that? Because on certain system configurations you can easily lock yourself out of the system with a defunct sudo (and you basically lose sudo when you ruin its configuration file)! Even though the script has vi in its name, that’s just the default. You may want to set the EDITOR environment variable to another editor if you prefer emacs/nano/joe/whatever. Not liking vi is NOT an excuse for not using visudo!

When editing the sudoers file, look for the line %wheel ALL=(ALL) NOPASSWD: ALL. It’s commented out by default. Remove the comment sign and save. That’s actually all that needs to be changed. What that change does: It grants all members of the wheel group unrestricted sudo access without having to enter their password.

Depending on what kind of base box you want to create, you may want to install the VirtualBox guest additions. They enable the hypervisor to directly interact with the guest system enabling some features like a shared clipboard, enhanced graphics options, shared folder support (which are not available on *BSD at the present time however), etc. The downside is that they are quite large (due to their dependencies): ca. 350 MB. If you’re aiming for a small base box, leave them out if you don’t need them. Otherwise consider installing them.

In case you built VirtualBox on your host system from ports you might do the same for the guest additions so that versions match. Building them from ports does complicate things a bit however. You need the system source installed, it will use quite some space and take a long time. Usually it’s not worth the hassle. Unless you require some feature that only works when the versions match (I’ve never run into one), just install the guest additions using packages:

# pkg install virtualbox-ose-additions

Installing the vbox guest additions

If you installed them, enable the guest additions for the next boot:

# sysrc vboxguest_enable="YES"
# sysrc vboxservice_enable="YES"

Preparing the VM for Vagrant: Users

The most important requirement for Vagrant is that a specific user has to be present. In FreeBSD you can create it all by issuing one line:

# echo vagrant | pw adduser -n vagrant -m -s /bin/tcsh -h 0 -L default -c "Vagrant user" -G wheel

This will make pw add a user with the name vagrant to the system, create a home directory for them, set the shell (you can also choose another one here like /usr/local/bin/bash for example) and make it use what is piped into it as the password (that’s a zero following the -h, btw.). It will also set the default login class for the user, use the provided user comment and add it to the wheel group (for which we’ve already configured sudo access).

Now that the vagrant user is present, Vagrant could log you into a VM that it has started from the base box. However it will ask for the password. This is just a small annoyance really, but we can do better. So let’s prepare the vagrant user for automatic login (using SSH keys). To do so, we first change to the new user:

# su -l vagrant

Next we create a .ssh dot directory in user vagrant’s home directory:

% mkdir .ssh

Then we download the public key from the Vagrant insecure keypair (it’s insecure because the private key is public, too – Vagrant uses it to log in via SSH and it’s open source software! But that’s not a problem here) into the new directory e.g. with the following line:

% fetch --no-verify-peer https://raw.githubusercontent.com/mitchellh/vagrant/master/keys/vagrant.pub -o .ssh/authorized_keys

This downloads the vagrant.pub file as authorized_keys (the file that SSH checks against) and skips verifying the SSL certificate of the remote web server (this is necessary because FreeBSD does not ship with a collection of trusted root certificates and we haven’t installed one).

The last thing to do is setting the correct permissions for the new directory and file (SSH is quite picky about that – and rightfully so):

% chmod 0700 .ssh
% chmod 0600 .ssh/authorized_keys

When that’s done, we can log out as vagrant, back to the still logged in root:

% exit

With the key in place we have everything that’s required for a simple FreeBSD 11 base box.

Customizing the base box

Now’s the time to customize your base box. You could install additional software, add more users, do specific configuration, etc. I’m going to prepare the template for testing Bacula with multiple nodes. Since I need to build Bacula with non-standard options, I need to use the ports tree. So let’s put that in /usr/ports first:

# portsnap fetch extract

Then we change into the directory for the Bacula client:

# cd /usr/ports/sysutils/bacula-client

We configure the compile options for the Bacula client as well as for all its dependencies next:

# make config-recursive

I usually deactivate NLS (support for non-English translations), IPv6, DOCS and EXAMPLES for all programs. You may choose different options of course.

Since I need the Bacula client on every machine I can simply build and install it now:

# make install clean

Now let’s change into the Bacula server ports directory:

# cd ../bacula-server

Again we need to set the build options for the port and dependencies:

# make config-recursive

Setting compile options for bacula server

Deselect postgresql and select sqlite instead! When you accept the settings, you will be asked to select the settings for postgresql next. This is because the list of ports to configure was compiled before you changed the dependencies by choosing to build with support for another database. Hit CTRL+C to cancel the operation and then run make config-recursive again.

Just like before, leave out unneeded options to keep the whole system a little lighter. Leave sqlite3 as-is if you don’t know too much about it (it’s a port with A LOT of options and can look rather daunting).

Then we fetch the source archives for Bacula server and its dependencies (this is done because I want to configure the VMs to be restricted to the local network later and thus they won’t be able to connect to the internet then):

# make fetch-recursive

Finalizing the VM

If you’re building a base box that you intend to share with others, it makes sense to try to cut down the size as far as possible. Here are a few suggestions:

  • Clean the pkg cache (removing package files no longer needed after installing them:
    # pkg clean -a
  • Remove the distfiles (/usr/ports/distfiles) if you don’t require them to be available later; if you need some of them, delete the others!
  • If you’ve installed the ports tree to build software and don’t need it in the base box, remove it completely
  • In case you installed the system source (e.g. for building the VirtualBox guest additions) or for customizing the FreeBSD system you probably want to delete /usr/src/* and/or /usr/obj/*
  • Have installed programs from ports and removed the ports tree again? You can also uninstall programs that were installed as build time dependencies only

Just deleting stuff won’t make your VM’s virtual hard drive smaller during packaging, though! If you’re using a traditional filesystem (i.e. UFS) there’s an easy trick to “reclaim” the now unused space: Zero it out! Don’t try to do this if you’re using ZFS – you won’t be able to fill your drive with zeros if the filesystem compresses them away! So for UFS filesystems do the following:

# dd if=/dev/zero of=/ZERO bs=1m

This will create the file ZERO in / which will be filled with all zeros until the filesystem runs out of space. If you delete that file afterwards, the part of the filesystem that is free again is all zeroed out and thus compresses well when packaging the base box:

# rm /ZERO

Zeroing out free space

If you chose to use multiple filesystems, you may want to dd to a ZERO file on each separate filesystem (e.g. /usr/ZERO, /var/ZERO, etc.).

Finally everything is ready, so shutdown the VM now:

# shutdown -p now

Building the base box

Wait for the VM to power off. Now open a terminal emulator on your host system and tell Vagrant to build a base box from the VM:

% vagrant package --base fbsd-template -o fbsd-template.box

The argument after –base is the name of the VM as it appears in VirtualBox. Mind upper and lower case! Choose any name for the output file (the extension is usually .box). This will take a moment but if all goes well you should eventually have the base box file!

% vagrant box list

This lists all Vagrant boxes available on your system. If you’ve just installed Vagrant before it will tell you that it doesn’t have any boxes yet. So let’s import our newly built box:

% vagrant box add --name fbsd-template fbsd-template.box

Give it any name you want the base box to be known as by Vagrant and point the program to the .box file. If you do

% vagrant box list

Base box created and added!

again, you should see that it’s available now. What’s left? Let’s test if it actually works.

Testing the base box

To do so, I suggest creating a directory for your Vagrant boxes:

% mkdir -p ~/vagrant/testvm
% cd ~/vagrant/testvm

In that directory issue the following command:

% vagrant init

This creates a default Vagrantfile. Think of this as the central configuration for a single VM that Vagrant manages. It contains the name of the base box to create it from, allows configuring of the network, synced folders, overriding base box settings (like the amount of RAM for the VM), provisioning, etc.

Edit this file, have a look at the contents (you can also do this at a later time – vagrant init will always create this default Vagrantfile for you if you need it) and delete it. Put the following lines in the Vagrantfile:

Vagrant.configure("2") do |config|
config.vm.box = "fbsd-template"
config.vm.synced_folder ".", "/vagrant", disabled: true
end

Substitute fbsd-template with the name of your base box if you chose a different one. The second configuration directive disables synced folders: They don’t work for *BSD guests at the present time and Vagrant would issue an unnecessary warning if we didn’t disable it. This is all you need for a very basic configuration. Save the file and exit your editor.

Now run:

% vagrant up

This command tells Vagrant to create a new VM from the base box (VM template) selected in the Vagrantfile and fire it up. Vagrant will do so in the background – it runs the VM in so-called headless mode.

VM created from base box has booted up

You don’t need the VirtualBox GUI for Vagrant but right now take a look. You’ll see a new VM that was created by Vagrant and in fact you could also use VirtualBox to control it. But that’s rarely necessary. Vagrant is meant to manage boxes all for you after all!

To enter the VM, you can execute

% vagrant ssh

Now you’re SSH’ed into the VM! It’s as easy as that. Issue an ls or something to see that it’s working. Exit the machine by logging out (type exit or press CTRL-D) and you’re back in your host machine’s VM directory. Try vagrant ssh again and you see that you’re inside the VM again.

SSH’ed into the box using Vagrant

Cleaning up

Shutdown the VM now:

% sudo shutdown -p now

When the VM shuts down the SSH daemon, you’re automatically dropped back to your host system. Let’s quickly do some cleaning up and we’re done for now:

% vagrant destroy

This will purge the VM. If you keep the Vagrantfile, you can just vagrant up afterwards to start over with a clean VM (from the base box) again. This is great for testing things. You can also control the VM from outside using commands like vagrant halt, vagrant suspend, vagrant resume, etc. I suggest you take a look yourself and learn what Vagrant can do for you. It really has some neat and useful features.

Just a

% cd ..
% rm -r testvm

later we’re done with cleaning up after ourselves. The base box works and can be used to quickly spin up VMs based off of it. While this is neat, the real power Vagrant has and the real comfort it provides show when you’re working with several VMs at the same time. Which is what I intend to do in the post after the next one.

What’s next?

The next post will be an introduction to the Bacula backup software, exploring the basic functionality.

Vagrant: Creating a FreeBSD 11 base box (virtualbox) – pt. 1

For a while I’ve been messing with backup stuff (namely a program called Bacula). To test backups properly it of course makes sense to have multiple nodes available. Now I do not have several unused PCs and other hardware available nor would I want to set up multiple nodes just to configure them similarly in the end. The easy solution? Virtualization. It allows to set up a virtual machine once and then clone it as the need arises. Also it means that I can try out things, do away with the VM and start over with a clean one if I want to.

Give it a try even if you’re new to VirtualBox! Working with it is very easy and just as useful. The idea of virtualization can be daunting if you’re just starting. Therefore this post is meant as an introduction (I’ll even detail VM creation with pictures). If you already know how to use VirtualBox and have a good idea of what Vagrant is about you may skip this post and go to the next one where the actual base box is being built (not written yet, will link it back here once it’s available).

What is Vagrant?

So what’s Vagrant? Vagrant is a program written in Ruby that runs on multiple platforms (FreeBSD, Linux, OS X and even Windows). It basically is a wrapper for virtualization software that makes working with VMs extremely easy and convenient. Vagrant supports multiple hypervisors and containers (simply called providers in Vagrant terminology): VirtualBox, VMWare, KVM, LXC and Docker. A GSoC effort exists to also support FreeBSD’s native hypervisor Bhyve – I’ll definitely give this one a shot in the future.

Vagrant uses a configuration file (the Vagrantfile) for each VM to know which template (called base box) to create it from, how to configure it and so on. It also supports a lot advanced functionality like provisioning a newly created VM using configuration management tools like the veterans Puppet and Chef or the newer generation like Salt Stack and Ansible. There are many cases where Vagrant can help you – just think about it for a moment.

There are a LOT of base boxes already made for you to download and use (have a look here or here). If you need to create new base boxes quite often, you even may want to automate this step. This is possible with a tool called Packer that allows you to create base boxes from a configuration file. This post however details the manual creation of a Vagrant box using FreeBSD 11 as the target OS.

Installing Vagrant

You can probably install Vagrant using the package manager of your OS. If you are using a strange system that has no package management, you have to find out how to do it yourself as I have given up on those systems for almost a decade now and have no idea how it works there. I’ll discuss setting it up on FreeBSD here. First issue:

# pkg install vagrant

Keep in mind however, that by default FreeBSD uses the quarterly package repositories now and you should either change that or simply install from ports (sysutils/vagrant) if you want the newest version.

Now think about the provider that you want to use. If you want to follow along with this article, we’re using VirtualBox. So go ahead and install it. On FreeBSD VirtualBox 5.x is finally available (Oracle does not support FreeBSD as a host system and the complicated work of porting it over was done by the community – thanks to everybody involved!) and it totally makes sense to install this new version. At the time of this writing it’s still version 4.x in the quarterly repository. So make sure whether

# pkg install virtualbox-ose

would install the old or the new version. Configure the latest repository instead of quarterly or build from ports (emulators/virtualbox-ose). If you choose to build from ports, consider to do the same thing for Vagrant. Otherwise you may build a version of VirtualBox that is newer than what Vagrant supports. To be able to run VirtualBox, make your user a member of the vboxusers group:

# pw groupmod vboxusers -m username

Remember that you have to log out and log back in for the new group membership to take effect. Ensure that the kernel modules for VirtualBox are loaded during system startup and load them ad hoc without having to restart:

# echo 'vboxdrv_load="YES"' >> /boot/loader.conf
# kldload vboxdrv.ko

Now make sure that VirtualBox’ network daemon gets started by default and make it start in the current session:

sysrc vboxnet_enable="YES"
service vboxnet start

All done. VirtualBox is ready to be used. There’s more configuration suggested if e.g. you want to use USB in your VMs (which in this case I don’t).

Creating a VM

VirtualBox has a headless mode and can be controlled using e.g. using the command line. But most people would probably prefer to use the GUI that it also comes with. So open up that program. (For steps where you can just accept the defaults I haven’t made a screenshot.)

The VirtualBox GUI

Click on New to launch an assistant for creating a new VM.

Choosing Name and type of the new VM

Give the new VM a name and select the type of operating system that it’s meant for. If you use a name that is somewhat like “freebsd”, VirtualBox will automatically suggest the right type and OS. Since this VM is going to be a template rather than a single-purpose one, I chose the name “freebsd-template” to reflect that.

Setting the amount of RAM for the VM

Set the amount of ram for the new VM. Think about the correct value for a moment. It’s no problem if you notice that you need more later – you can always change the amount of RAM allocated for the VM when it is turned off. But setting it right now saves you the time and effort to re-adjust it later. So how much should you select here? It depends on several factors.

I’m planning for a template that I want to spin up as multiple VMs so the host system must have quite a bit more RAM than the three to five VMs (that I want to run in parallel) together. However my host machine has 24GB of RAM and so there’s no need for me to be stingy and I’m allocating 1024 MB because I have plenty available. If you have little free RAM go for less. I intend to use FreeBSD in text-mode with not too many services running. You could probably do with 256 MB or even less if you really have to.

Allocating space for the virtual hard drive

The VM needs a virtual hard disk. Set the maximum size for that. Just as with RAM chose some value that’s sensible for your case. Again: I have enough space so I don’t have to go with ultra-low values of 3 GB or so. Making the virtual hard drive dynamically allocated means that it’s only going to take the actual size of its data of space on your real hard drive. This means that it can “grow” until it reaches its maximum size. Note that it won’t automatically shrink if you delete data.

Starting the VM

That’s all, you have created a VM. Start it now.

Selecting the ISO image

On first start, VirtualBox will ask you to insert some kind of installer media. If it didn’t the same thing would happen that happens on a PC with an empty hard drive: The system would fail to boot. Download an ISO image of FreeBSD 11 and select it as the boot iso in VirtualBox.

Selecting the ISO image

Now let the VM boot! I’m using FreeBSD11-RC2 here because the date for the final release has been delayed (it should have been out now and that’s what I had planned for).

Installing FreeBSD 11

The OS should boot up and offer you to go to the installer. Proceed and install FreeBSD. It’s pretty straight-forward but there are a few things noteworthy about the installation options. I don’t want to repeat myself, so if you’re completely new to installing FreeBSD, you might want to take a look here where I detailed the installation of FreeBSD 10.1 (I explained disklabels and such). Here I’ll only cover what’s new in the 11.0 installer.

De-selecting all optional distribution sets

I use the hostname “fbsd-template.local”. The installation sets are different because the base system structure has been redesigned. Most likely you won’t need any of the optional sets. To keep the template nice and small I suggest to de-select all of them. Go with UFS as the file system unless you have special needs – and can spare a fair amount of RAM (2G+) for each VM. So going with AUTO (UFS) and using the entire disk is probably fine. Choose GPT partitioning – we’re not dealing with legacy hardware here.

Setting the date

Enter a root password; if you intend to share your base box, it’s common to set the password to vagrant so that others might easily access and modify it. Configure your network (most likely an IPV4 network with DHCP and no IPV6). Thanks to DHCP you should not need to configure the resolver but can accept the values that the installer was told. Configure the timezone. The FreeBSD 11 installer will let you set date and time now which is a nice feature.

Setting system time

Deselect all services except for SSH which is how Vagrant will connect to the VMs. The system hardening dialog is also new. In my case it’s not terribly important since I’m creating a simple VM template for testing purposes. But for production servers it is actually a pretty good idea to tweak some options. I’ve grown a habit of cutting down services that are remotely accessible to the necessary minimum and thus simply selecting the two last options saves me some hassle of editing rc.conf to do just that.

Tweaking the hardening options

We don’t need to add users right now and can quit the installation without final modifications. So let’s reboot.

Removing installation iso

It’s necessary to remove the installation iso or the machine will boot to the installer again instead of into the new operating system. If you’re not fast enough and the system is already booting the installation iso again, just force the unmount and reset the VM.

Resetting the VM

Now the VM should boot into your new FreeBSD 11 system!

What’s next?

While this part discussed the requirements and detailed the preparations, the second part will describe how to actually build the base box for Vagrant.

How to choose your *BSD OS to begin with?

After publishing my previous post about how FreeBSD’s documentation is way better than that of Linux, I was asked which BSD I’d recommend to somebody who knows Linux but is new to the world of *BSD. This is a good question – and definitely one that cannot be answered in just a comment reply. So here’s a whole article about that topic (and in fact a rather lengthy one).

The question has been asked many times on the net and a lot of people have given different answers. Many of those recommendations are rather old now and the points that they made may no longer apply. Also it’s often BSD veterans who – of course – tend to advocate their BSD of choice. I’m a newcomer myself and so far I have not settled on one particular BSD but still try to explore all of them, their strong points and their shortcomings. If you ask me about Linux, I’m tempted to recommend the distro that I’ve been using for years now. When it comes to the BSDs this is not the case, yet, and while I do not make the claim that I’m perfectly neutral, I think that I can write something that could be of some value to people thinking about giving some BSD a try.

Dear Linux user!

Long-time Linux users will probably remember the famous “Welcome letter to a Windows user” from 2006. It’s a real classic which is outdated in some regards but the main points are still very much valid. The most important one (which applies in our case as well): If you’re interested in another operating system, it is imperative to be open-minded and to give this OS’s way of doing things a chance! It’s not a good idea at all to judge from the perspective of your old OS. Quite some things will be different. And as a matter of fact, you won’t be able to judge if certain decisions were sensible – they may seem totally weird to you but then actually make perfect sense if you know the background (which you don’t until you gain much more knowledge about the design of the system).

All BSDs are direct descendents of the original AT&T UNIX. Compared to Linux they have a much longer history and there are lots and lots of things that can probably only be explained if you go back in time far enough. While all BSDs share a common heritage they have of course been modernized over time. That is why they also have diverged quite a bit over the last two decades (and why it makes sense to write an article like this!).

One of the most important differences between the Linux world and the BSD one is that there are no “BSD distributions”. Sure, you will find some people use that term on the net but it’s most likely wrong. Most likely? Yes, because there arguably are BSD distributions… But that’s a very special case. You definitely know Debian and you probably know Gentoo. These are two Linux distros, right? Sure – but they could also be called “BSD distributions”. Why? Because there’s not only Debian GNU/Linux. The Debian project also offers Debian GNU/Hurd. And there’s Debian GNU/kFreeBSD, too! The latter is a typical Debian distribution (GNU userland) running on top of the FreeBSD kernel. For Gentoo it’s the same story. That’s where there’s something that you may call a “BSD distribution”. But that’s a rather Linuxy point of view!

While Linux is just a kernel and it is the distributions that create a full operating system by combining it with a userland (usually GNU), all BSDs follow a “whole system“ approach. There’s no such thing as “the BSD kernel”. Each BSD has its own. Fedora and Arch Linux may use different versions and configure their kernels differently, but it’s the same Linux kernel from the same sources that they use. The FreeBSD kernel and the OpenBSD kernel for example are entirely different kernels (even though they share common ancestry). It’s due to this “whole system” approach that calling e.g. NetBSD a “distribution” is plain wrong (and for the same reason BSD people will probably call the idea of a “BSD distribution” an absurdity in the first place).

What else should you know? Well, there’s a lot of little things that will be different from what you are used to. Drives and network interfaces have different names (like ada0p1 instead of sda1, em0 instead of eth0 or enp0s3). Some commands have different options and/or switches. Filesystems are different (unless you’re going to try FreeBSD and already used ZFSonLinux). The configuration works differently and you’re going to meet a different init system. You’ll probably come across a lot of things that turn out not to work like you intended. But that’s nothing horrible. You’re familiar with one unix-like system (Linux) and the BSDs are all unix-likes themselves after all!

A potential problem is drivers. If you always use the absolutely newest hardware (or pretty exotic stuff), chances are that Linux may fit you better. All of the BSD projects are much smaller than Linux is and so it is impossible for them to support as much hardware. However they are doing a fantastic job for the manpower that they have. Just try it out and see!

FreeBSD

Why should you try FreeBSD? FreeBSD is the BSD operating system with the largest community. This can be an important point for deciding which BSD to give a try. Thanks to its relatively large community it offers by far the widest range of software available. FreeBSD is the base of a lot of commercial products and appliances and for that reason it receives quite a bit of funding from the industry. That money can then be spent to fund projects that nobody volunteers for.

FreeBSD hat good support for technology like EFI. Nvidia officially supports FreeBSD and provides a closed-source driver that is meant to be on-par with the Windows driver (this can be interesting if you need good graphics performance). If you are into virtualization, FreeBSD is an excellent choice. Virtualbox 5 has been ported to FreeBSD in a community effort (Oracle does not support FreeBSD hosts). Qemu and Xen are available. And with Bhyve, FreeBSD even has its own modern hypervisor which is a really promising piece of tech! A lot of effort has been put into making the ARM platform a first class citizen with FreeBSD 11 (which is just around the corner now).

The project strives to create a general purpose operating system that is free, open source and under a permissive license. FreeBSD has put a lot of effort in getting rid of GPL’ed software in the base system (you can of course always install it as a package, though!): GCC has been replaced with LLVM/Clang (on major platforms) and a lot of the GNU tools for which no alternative implementation existed have been substituted by newly created, BSD licensed replacements. This is still work in progress, but the plan is to be able to offer a full operating system that is all permissive licensed by the time FreeBSD 12 is released.

FreeBSD’s support for technology like ZFS and DTrace has been mature for quite some time now. Other things like jails have been around like forever and are a stable part of the operating systems literally far more than a decade before “containers” became the thing on Linux. On FreeBSD you can choose between three Firewalls: A modified (e.g. multi-core optimized) variant of the mighty PF, IPFW (FreeBSD’s native firewall) and the old IPF. Also FreeBSD’s Linux emulation is a pretty sophisticated system. Don’t expect it to support all Linux syscalls up to the latest 4.7 kernels – but even though it’s limited to emulating older Linux kernels it still enables you to run some closed source software that is only available for Linux if you need that.

In general FreeBSD is often characterized as “extremely stable” and there’s definitely something to it. However this does not just mean that it’s a rock solid system, mind you! Stability is more than that. E.g. the project follows a design principle called the “POLA”: Policy of least astonishment. You won’t reboot your machine after a major upgrade just to find that your init system has been replaced with something else! You also won’t find that your firewall is inactive because the config format changed and the newer one cannot load your previous rules! It’s not too hard to see the benefit of introducing changes gently over time and with loud heads-up messages instead of quietly. When it comes to supported architectures, FreeBSD concentrates on the more popular ones.

While it’s mostly used with servers, FreeBSD makes a great desktop, too. If you want a desktop FreeBSD, you can of course install vanilla FreeBSD and then add a lot of packages for your favorite desktop environment. However there are two projects which provide a FreeBSD based desktop system (with a graphical installer, packages tuned for desktop usage, and so on): PC-BSD / TrueOS and GhostBSD. The former focuses on a modern OS with a lot of nifty tools – at the cost that it’s available for 64-bit PCs only and forces you to use ZFS. It uses the Qt toolkit and (by default) its own desktop called Lumina. If you prefer the GTK+ side of things, GhostBSD offers the MATE or Xfce desktop environments (and also supports 32-bit systems as well as the older UFS filesystem if e.g. your machine has little RAM). Both are excellent choices if you prefer to start with a complete desktop OS and explore things from there.

OpenBSD

If you choose OpenBSD, there’s a lot of really cool and modern features… that you will have to do without! Oh, don’t get me wrong: That can be a great thing!

The OpenBSD project focuses on security and correctness and for that reason take high code quality extremely serious. They reject the phenomena that is sometimes called featuritis and resist the temptation to implement dozens of “neat” or “nice to have” things at the cost of neglecting the essentials. The OpenBSD developers put quite some effort into maintaining a tidy system. Run across some ancient looking code? Time to ask on the mailing list if somebody does even use that at all. If nobody claims to do so, disable it and wait for someone screaming that it is needed after all. And if there’s any doubt in it still being useful after some time: Bye bye, feature!

Just to give you some examples which prove that those guys really mean it: Not too long Linux emulation has been completely removed because it was old and considered to be in a bad state. Just recently tmpfs was disabled due to a lack of maintenance and may very well be removed in the future as well. And of course it’s security first. Believe it or not: OpenBSD is not afraid to throw things away that pretty much every user of a modern OS takes for granted. Loadable kernel modules can always be a security problem. OpenBSD ripped them out. Usermount turned out to have security issues and – due to its nature – not to be really fixable. It’s gone now.

The project also takes a very tough stance on license matters / politics. There’s GPL(v2) code in the base system but GPLv3 is deemed completely unacceptable. As you would expect from hardliners living up to their creed, OpenBSD still ships with GCC 4.2.1 (the last GPLv2 version) in the base system (you can of course install GPLv3 software as packages)! Even though they heavily patch their compiler, it’s pretty old now and probably is a hassle to continue to maintain. Binary blobs are not accepted even if they’d make something work. Since that would not be debugable or auditable, using blobs would mean a half-assed solution. And OpenBSD follows the principle: “Do it right or don’t do it at all”. They also refuse non-disclosure contracts as a matter of principle. If some vendors choose to be pigheads, OpenBSD usually chooses not to support their hardware. Period.

While most people would probably agree that doing things right is a commendable thing, this may sound a bit too harsh for you. But think again: It’s exactly this seemingly “extremist” stance that brought great benefit to all of us, even if we don’t use OpenBSD. How’s that? The OpenBSD developers have discarded a whole lot of tools because they didn’t live up to their high standards and then took the effort to replace them with a new tool done the OpenBSD way. Tools like OpenSSH, OpenNTPD, OpenSMPD, relayd, spamd, tmux and many more originated in OpenBSD. They even created their own secure webserver (simply called httpd) since they felt that Nginx was getting too bloated over time. As the project has a much smaller community compared to FreeBSD, this really is quite an achievement.

They are also not afraid of taking quite radical steps even if that means a lot of software breaks for them. In 2014 they solved the “2038 issue” that all *nix systems have. Previously OpenBSD pioneered system wide stack protection, ASLR, W^X, etc. All these things are major changes that break a lot of applications. OpenBSD ports maintainers who noticed that some application broke due to changes like these always tried to at least notify the upstream projects or upstream patches if they already resolved the issue. This makes it much easier for other systems to also make these changes since the biggest fallout of doing so was already solved (thanks to OpenBSD).

OpenBSD supports quite a lot of architectures and purposely does so. Even the packages for the most exotic platforms are built on these machines instead of cross-compiling them on faster metal. The idea behind this is that doing so will in some cases expose subtle bugs that would have gone unnoticed otherwise.

While it maintains a rather small base system, OpenBSD still comes with a surprisingly complete set of tools for server duty. Some people say that OpenBSD makes the perfect router and thanks to the PF firewall this may very well be the case. Just don’t be too quick dismissing it for desktop usage! OpenBSD developers are known to be devotedly dogfooding their system on their laptops, servers, desktops – on their everything. If you want to use it with a graphical system, there’s a distribution set called Xenocara on the installation cd. Xenocara is a hardened version of Xorg. Should you ever need help, have a look at the manpages. They are of breathtaking quality.

NetBSD

Alright, NetBSD. This BSD does not have a big community and that community is unfortunately not particularly good at communicating the cool things that they are doing. I’ve used it much less that the two “big” BSDs mentioned before, so I might easily miss quite some information deemed relevant by a regular NetBSD user.

First and foremost NetBSD is known for its portability. Their slogan is “Of course it runs NetBSD!” and if you take a look at the quite impressive list of supported hardware, the project lives up to that. If you get into the greater *BSD community a bit, you’ll sooner or later hit the reference that NetBSD runs on just about every computer and on toasters. Don’t you think this is a joke!😉

Perhaps even more impressive is that NetBSD is just so portable that you can actually compile NetBSD on a Linux system if you want to! And things don’t stop there. Probably the best known project that originated from NetBSD is pkgsrc (pronounced “package source”). If you already have an idea what the ports system on FreeBSD or OpenBSD is, think that plus – of course – a lot of effort added to make it highly portable. Pkgsrc can bootstrap itself on all the BSDs, Linux, Solaris, OSX, Minix, commercial UNICES (AIX, HP-UX, etc) and even Windows (using Cygwin)! What does it do? It provides three things: 1) Portable package tools 2) A portable package creation framework 3) Ports (think package “recipes”).

If you use multiple operating systems you may be tired of having to use different versions of your applications (since all operating systems or – in case of Linux – even all distributions package applications at their own pace). Pkgsrc may be the solution for you since you can use it to build and install the same version of your applications on all of your platforms! Truth be told, not every port builds on all supported operating systems. But still even having 60 – 90% (depending on which software you need and which OSes you run) is quite nice!

But there’s more to it than just portability. NetBSD has been experimenting with a few interesting things over the last few years. For example they’ve imported the small embedded programming language LUA into their kernel. In case you do not know it: LUA is used in many places since it’s very light-weight and easy to use. A lot of games embed it as their scripting language for example. Having this in the kernel could allow for a whole lot of interesting things. However I have to admit that I haven’t looked into this. Same thing for the new firewall, npf, that is part of NetBSD. It’s meant to be very high-performance but I haven’t used it and didn’t hear much about it.

The most interesting concept that I associate with NetBSD is that of the rump kernel, NetBSD’s take on the anykernel concept. If you’re not familiar with that please do some reading yourself. This topic alone would easily deserve its own article – and I’d not be the one to write it since I’m not very knowledgeable in this field.

Dragonfly BSD

Who should try out Dragonfly BSD? Well, you should have a heart for underdogs if you want to try out dfly first. It has by far the smallest community of the four main BSDs and so the chance that you’ll ever run into it in the wild is pretty low. If you don’t mind that (or this even sounds great for you) then there’s nothing wrong with giving Dragonfly BSD a try. In fact from the technical side there are very good reasons to do so!

Dragonfly BSD is the youngest of the major BSDs. It was forked from FreeBSD because its lead developer did not agree with the direction that the FreeBSD project took. Since he was interested in clustering and ultra-high performance computing, these are some of the main aspects that drive the development of Dragonfly.

The Dragonfly BSD project seems to be more interested in creating the best performing OS possible then in things like license matters. While they are looking into making LLVM/Clang their system compiler now, they had no problem importing GCC 5 into their system. For quite some time dfly used NetBSD’s pkgsrc as their official packaging tools. After FreeBSD introduced pkg-ng they switched to using that and a customized ports tree called dports.

Dfly has achieved high performance especially in networking and is the leading BSD when it comes to porting graphics drivers over from Linux. It has dropped 32 bit support and now supports 64 bit machines only. This decision was made due to the little manpower that the project has. A tool called DMA (Dragonfly Mail Agent) has originated from Dragonfly; it is a simple replacement for sendmail on servers that only need to send mail on the local machine.

However the most important reason to give Dragonfly BSD a chance is because it offers HAMMER. HAMMER is a BSD licensed next generation filesystem a bit like ZFS in some regards but different in others. While it lacks some of ZFS’s advanced features it works well even with much less memory and it can even do things that ZFS can’t (fine-grained file history)! HAMMER has been considered stable and production quality on Dragonfly for a while now so this is something to take a look at if you are into filesystems.

Well, and then there’s HAMMER2, version 2 of the HAMMER filesystem with even more features. It is not ready yet and the Dragonfly developers openly admit that it won’t be too soon, but it is interesting enough to keep an eye on (especially since version 1 of HAMMER is proof enough that the team can implement a filesystem that rocks!).

Your choice!

So let me welcome you to the rich and fascinating world of *BSD. You now have a first and very basic impression on what the four main projects “work” like. Try out either one. Try out all of them. Virtualize or use real hardware. The source will always be with you. The choice is, too.

(And please give me feedback about this article and/or tell me what your first encounter felt like after you tried out a BSD!)

Documentation: Linux vs. FreeBSD – a real-world example

With every operating system there comes the time when you need help with something (if you’re not the absolute Über-guru, that is). If you are in need of help, there are many ways to get it. You can ask an experienced colleague or friend if available. If not, you can search the web. There is a very high possibility of the information that you need being out there, somewhere. If not, you could ask for help and hope that somebody answers. Well, or you could consult the documentation!

In most cases somebody has been right there before and asked for help on the net and somebody else gave an answer. That answer may or may not be correct, of course. And in fact it might even have been correct at some point in time but is no longer valid. This is a very common thing and we have learned to optimize our searches to more or less quickly find the answers that we need. After getting used to that habit, “google it” (replace with $search_engine if you – like me – try to avoid using Google services when possible) is probably the most common way to deal with it once you hit a problem on unfamiliar ground. So while users of Unix-like systems are usually aware of the existence of manpages, I’d say that especially younger people tend to avoid them. And really: You don’t need them. Except for when you do!

Public WLAN

Last week I had two appointments in another city. So I took one day off from work, got up early in the morning and drove about 1.5 hours to the first one. The second one was a few hours later and so I was left with something extremely precious: Free time! To make it even better, neither my children nor my wife were around. The perfect opportunity to get something done!

One of my hobbies aside from computer stuff is writing. In addition to shorter stuff, I also have a fantasy novel (called “Albsturm”) that I’m writing on as time permits (which it hardly ever did during the last two years). And so I figured that it would be a good idea to take a laptop computer with me and spend some hours writing (hint: Like always, I didn’t write a single sentence!). I have two reasonably new laptops that I could choose from, one running Arch Linux, the other one FreeBSD and OpenBSD. The latter is the smaller one and for that simple reason I took that one with me.

It was a warm day and I decided to sit down at a café, have a drink and do my stuff there. When I found one, I saw a sticker which told me that public WLAN was available there. Hm. Other than writing I also had a more or less urgent email to write. Should be a quicky, just a few lines. So I thought that I should probably start with that.

Offline!

The only problem was that I had no idea whatsoever on how to connect to the WLAN using FreeBSD or OpenBSD! In fact I had no idea how to do it on Linux, either. I’m an “all cable guy”. It feels like about two decades ago that I had my first wireless mouse. I really liked it – until the batteries ran out of charge in a very bad moment and I didn’t have any replacement ready. Wireless stuff may be convenient as long as it works, but I prefer reliability over that. And I also like to set up basic things once (which means that I wouldn’t like to have to change a WLAN channel if my neighbor gets a new access point which occupies the same one that I had used before – stuff like that).

The three or four times that I had used WLAN before was on a Linux box using the graphical Network Manager which does all the magic behind the scenes. Yes, I’m aware that PC-BSD has its own tool which does the same job and GhostBSD has another for people like me who prefer a GTK application over a Qt one. I had neither PC-BSD nor GhostBSD on my laptop however. Just vanilla FreeBSD (with EDE as the desktop) and OpenBSD without any desktop (because I didn’t have time to install one, yet).

So there I was, offline and looking for a way to go online. Obviously “google it!” or some variant of that did not apply here. Sure, the adventure could have ended just there. But I am a weirdo who refuses to take a mobile with him everywhere he goes like most other people seem to do these days. Now if that’s shocking for you or you just cannot believe that someone who deals with tech does not have his mobile in reach all the time: Just imagine that I had one but it ran out of power (I’ve seen this happen to friends often enough to know that it’s quite common)!😉

Ok, what now? Thinking about it for a second, I realized that I had made a mistake when installing my system. You don’t install doc when you’re setting up a new system, right? The (absolutely excellent) FreeBSD handbook is available online after all. So why should you? Yeah. So am I on my own here? No! It’s me and a man’s man(1)! Will that suffice to go online?

Help!

Thanks to my previous exposure to help systems, this was the moment where I could have felt a cold chill (which would actually have felt good due to the warm weather). Remember the Windows 9.x “help” system? I cannot remember a single time when it had actually helped me. It either found nothing even remotely connected to my problem or it gave some generic advice like “ask the network administrator” (I AM the “network administrator”, dammit! I’m the guy who plugged those four cables into the switch and gave static IPs to the PCs!). It was utterly useless – and in a later version they “improved” their help by adding a stupid yellow dog… (When PC people talk about “the good old times” this is what you should remind them of :p)

But let’s not waste any more time on the horrible demons of the past and skip to the friendly daemons of today! I’ve used manpages a few times on Linux systems. This was a much better experience but still a vain effort often enough. The worst thing: For a lot of commands there are both a manpage and an info page – and those two are not identical at all! With a bit of bad luck you skimmed through one help text but the relevant information is only present in the other. Even though I can see the limitations of the older manpage system and understand the intent to create something better… No, sorry. If GNU really wanted to go with info pages instead of manpages they should just have created manpages which point the reader at the info page for each command. Just don’t make me read both because they have different information in them!

FreeBSD has a natural advantage here due to its whole-system approach. If you install third-party packages (say GNU’s coreutils) you will be in for the same mess. But everything that belongs to the base system (and that’s a whole lot of stuff!) is a consistent effort down to the manpages. And from what you hear or read on the net, the BSDs pride themselves in dedicating a fair amount of time to write documentation that’s actually useful! Does the result live up to that claim? We’ll see.

Where to start?

Manpages… Ok, sure. Just what should I start to look for? As I said, I didn’t know too much about the topic. Hm! I couldn’t think of anything quickly, so I actually did a apropos wlan. It wasn’t a serious search and I didn’t really expect anything to show up. Here’s the output of that command from a Linux box:

apropos: nothing appropriate

So was I right there? No! I was in for a first pleasant surprise. Here’s the output on my FreeBSD machine:

snmp_wlan(3) - wireless networking module for bsnmpd 1
wlan(4) - generic 802.11 link-layer support
wlan_acl(4) - MAC-based ACL support for 802.11 devices
wlan_amrr(4) - AMRR rate adaptation algorithm support for 802.11 devices
wlan_ccmp(4) - AES-CCMP crypto support for 802.11 devices
wlan_tkip(4) - TKIP and Michael crypto support for 802.11 devices
wlan_wep(4) - WEP crypto support for 802.11 devices
wlan_xauth(4) - External authenticator support for 802.11 devices
wlandebug(8) - set/query 802.11 wireless debugging messages

Not bad, huh? 9 hits compared to… 0! I had nowhere better to go, so I read wlan. It provided a fair amount insight into things that I was not too interested in at that moment. But it had a rather big SEE ALSO section (which I feel kind of lacking in the Linux manpages that I’ve read so far). This proved extremely useful since a lot of device drivers were mentioned there and I figured that this would actually be a good place to really start.

Dmesg told me that my machine has an “Intel Centrino Advanced-N 6205” and that the corresponding driver was iwn. However ifconfig showed no iwn0 interface. There were only em0 and lo0 there. How’s that? I figured that it probably had to be set up somehow. And had I not just read about the generic wlan driver?

The wlan module is required by all native 802.11 drivers

The same manpage also pointed me to ifconfig(8) which makes sense if you want to do interface related stuff (unless you’re on newer Linux systems which sometimes do not even have ifconfig and you have to use the ip utils).

The ifconfig(8) manpage is a really detailed document that helped me a lot. So it’s only

ifconfig wlan0 create wlandev iwn0

and my wlan interface appears in the list showed by running just ifconfig! That was pretty easy for something which I would have never figured out by myself.

Let’s go on!

The first step of what could have been a painful search turned out to be so surprising easy that I was in a real light mood. So instead of just getting things to work somehow(tm), I decided to do it right instead. It was only one simple command so far but I wouldn’t want to enter it again after each reboot. So it was time to find out how to have the init system taking care of creating my interface during system startup.

Phew. That could be a tough one. What obscure configuration file (or worse: systemd “unit file”) could WLAN configuration stuff go into? Hey, this is FreeBSD! Want init to do something for you? Have a look at /etc/rc.conf!

Hm. Sometimes configuration files have their own manpages, right? But even if there was one, it could hardly cover everything. Would somebody take the time and put what I need in there? Ah, let’s just give it a shot and man 5 rc.conf. Yes, there’s a manpage for it. But not just a manpage. I mean… Wow, just wow. I’m still amazed by the level of detail everything is described with! Should you ever take a look, you’ll be in for a treat of over 2400 lines! Does it cover WLAN interface creation? You bet it does! And it holds more information about that topic than fits on one terminal screen. In my case it boils down to:

wlans_iwn0="wlan0"

Really simple again – which is really encouraging if you’re new to a topic (on an operating system you’re only slowly getting familiar with because you have to spend most of your time with Linux machines).

The manpage also mentions wpa_supplicant(8) and after reading a bit about it and wpa_supplicant.conf(5), I had my system automatically make a WLAN connection during startup: It received and ack’d a DHCP offer and got an IP. Great!

Hold captive by the portal

Time to fire up a browser and surf to some website to see if it works… Oh my. What’s that? A captive portal redirects me to a page with payment information! That’s not quite what I’d call “free WLAN”! What happened? The page says “Telekom” but the sticker said that the hotspot was provided by another company. So I must be connected to the wrong one…

So it’s reading ifconfig(8)’s manpage again. Turns out that ifconfig wlan0 scan returns a list of available networks. So far so good. Of course the manpage also explains how to manually connect to a network of your choice. But this is where things went into the wrong direction for me.

The SSID of the network that I wanted to connect to was too long to fit into the column that ifconfig reserves for the output… Gosh. Now how would I connect to that one? Guess the rest of the name? Probably not a good tactic. What else? I could not connect to the network that I knew was free and I didn’t want to just randomly try connecting to the others.

Autoconnection makes its decision by signal strength. It’s rather unfortunate that the stupid paid Telekom one had a better signal where I was sitting. But by blocking that one network there’d be a good chance that the right one would have the second best signal, right? So I only have to somehow blacklist the Telekom network.

A long story short: This proved to be a dead-end. I still have no idea if it’s even possible to blacklist a network using wpa_supplicant.conf. It probably isn’t and the only way to go is define the desired network with a higher priority than the undesired one. It took me quite some time to give up on this path that seemed to lead nowhere.

What now? It looked like I had to somehow get my hands on the complete SSID of the right network. But how to do that? I could of course always ask a waitress as she probably either knows it or at least could ask somebody who does. However after spending quite some time on the matter, I wanted to figure it out myself. Finally I came across ifconfig(8) again and it mentions the -v flag to show the long SSIDs (and some more info)!

With the full SSID known to me I could adjust my wpa_supplicant.conf – and after a reboot the system picked the right network. My browser was lead to a different captive portal and after I read and accepted the license terms (which were quite reasonable), I was free to surf wherever I wanted.

I quickly wrote and sent the mail that lead me to this adventure in the first place. Then I shutdown -p now my system, put the laptop in my car and drove to my second appointment.

Summary

I’ve had some Linux experience for almost two decades now and used it on a daily basis for about half of that time. In contrast to that I’m really new to the BSDs, seriously using FreeBSD for less than a year. I probably know less than 1% of the common taks on that OS – and even less on the topic of WLAN which I avoided as far as I could.

Getting my laptop to connect to the net via WLAN in a café using just the manpages because I was offline until I reached my goal seemed like a painful adventure full of potential pitfalls. Instead it proved to be an unexpectedly pleasant ride in unfamiliar territory.

There are many sources on the net that say BSD has far superior documentation compared to Linux. And I was impressed enough about that fact to add another one by writing this post. So if you’re a *BSD user and you need help I can only give the advice to take the time to read some manpages instead of looking or even asking on the net. It is much more rewarding to figure out things yourself using the documentation and the chance is quite high that you’ll learn another useful thing or two from it!

Can the same thing (connecting to a WLAN without graphical tools) be done on Linux? Certainly. How would you do that? I have no idea. Is there an easy way to figure things out just using the manpages? I kind of doubt it. With a lot more time on your hands: Probably. But after learning what real documentation tastes like, I don’t feel like trying it right now. I may do it in the future to complete the comparison. Or maybe not.

Version control (pt. 2): Generations and intended use

In the previous post I gave a little introduction to Version control, explaining a few basics that help to understand the topic. This post assumes you know these things that version control systems have in common. So now it’s time to discuss what sets them apart – not individually, yet, but in terms of characteristics some of them share with each other.

Generations

Each version control system (VCS) has its unique advantages and disadvantages. However there are some traits which are common to several of them. And since the programs that share those traits were typically released rather close to each other, it makes sense to speak of generations of version control systems.

So far there are three of them with the first obviously being the oldest and the third generation the newest. What may surprise you is the fact that the earlier versions, even though being much more limited, have not completely disappeared. How come? Well, just keep it in mind while we take a look at those generations. Perhaps you can see where tools of older generations may still make sense!

The previous article discussed manual “version control” and its limitations. In short: It can work for you if your project is rather small, you’re working on it alone and you’ve got the discipline to always do proper file backup before you make bigger changes. In a world of more sophisticated software it’s quite unlikely that many projects meet all of those requirements. Therefore it totally makes sense to develop programs that would assist you in doing proper version control on your projects.

The first generation

The first generation did exactly that: It preserved any changes you made to a single file. Yes, it is one characteristic trait of the first generation that it works on a per-file basis. Version control is entirely separate for each and every file that you choose to record changes for. For each file it manages, the VCS creates a “history file” which contains all the differences from one version to the next plus a comment.

Originally, it was common to use VCS of the first generation on multiuser systems. If multiple users can work on the same project at the same time (via different logins), it’s quite possible that conflicts arise. If two persons make changes to the same file, the one who saves last “wins” – overwriting all changes that somebody else may have made in the meantime. To avoid that, locking was invented. Files can be locked while they are being edited. In case somebody decides to edit a file, causes a lock and then does something else, the file remains locked. An administrator can however break a lock if something like this happens.

Today VCS of the first generation are more or less obsolete. There are niches where they managed to survive and are still being used. One example is management of configuration files on *nix systems without centralized configuration management. These configuration files are only relevant to the system they exist on so that missing networking capabilities (which the second generation introduced) do not mean any disadvantage. And most of the time these configuration files are separate entities not related to other files and for that reason not even the limitation of only managing a single file is a problem here.

The second generation

There are two important aspects that set tools of the second generation apart from those of the first: They offer network capabilities and they can manage multiple files in one project! The later ability solves a whole bunch of problems which made 1st generation tools hard to work with on anything but very small projects. Managing each file separately does not sound too bad at first. But think about it for a minute.

Let’s imagine, we work on a simple project. Nothing too fancy: A few source code files, one header file. Currently the program is broken and we decided to go back to a working version. Good thing that we have version control, right? Right… Sort of. The file main.c is currently at revision 96, foo.c at revision 44, bar.c at 24 and baz.h at revision 7. See the problem? After we found out that revision 89 broke the program and we reverted back to 88, how do we find out which revision number of the other files belongs to revision 88 of main.c? Yes, we have time stamps and we can find out which revisions all of our files had when the program was working when the main file was at revision 88. Maybe it’s not even that bad when we only have four files. But what if we have 20? 100? It’s cumbersome and really a waste of time. Keep things like this in mind and you’ll definitely come to appreciate the ability to manage multiple files together in one project where the revision number increases whatever file was changed and however many files were modified!

Now that larger projects are possible because the whole project is managed together in one repository, it makes sense to use the network as well. This networking capability is achieved by providing one centralized repository which all project members (or even everybody interested in the project) can checkout to create a local working copy of the latest revision (or any older one if needed). Changes can be made locally and after committing them they are checked in back into the centralized repository. Since the tools of the second generation will only allow checking in if nobody else did a check-in in the meantime (if somebody did, you need to update your working copy first and merge your and the remote changes if at least one file was modified by both) locking is also not necessary anymore!

Today tools of the second generation still play an important role. Their attractivity is declining, however. This is due to a few shortcomings which the third generation tries to address.

The third generation

The big innovation that is common to all tools of the third generation is that they work decentralized. Users usually don’t checkout files from a central (probably remote) repository. Instead they clone the full repository and then checkout the files from their local clone. Since the local repository is exactly the same as the original one, there’s no longer one central repository – at least from a technical view. And while cloning requires to transfer a lot more data over the wire (especially for large projects), there are some huge benefits to it.

If you have a local clone, you can work on the project even when you’re not online. You can see the complete history and checkout earlier revisions if you need to – all without having to access a central repository. If you’re online, you can always sync your local clone with the original repo (pull down changes) or even the original one with your local repository (push up changes) if you have write access.

One of the biggest advantages of decentralized tools is that they make forking much easier. While forking a project has been something not well liked in the past, you’ll often see projects asking you to fork and play with their code today (e.g. the well-known “fork me on github”). Experience has shown that quite some people fork a project, add a feature they need and then give their code back to the project (this is done by creating a pull request which invites the administrators of the original project to pull in the changes if they want).

Which one to use?

If you like software history, there’s nothing wrong with trying out tools of the older generations. But if you’re just starting out with version control and you want to learn something now, it makes sense to choose a tool of the third generation. Which one would I recommend? I can only give the usual answer to such a question: It depends. Each one has its strengths and weaknesses. In the next blog posts we’ll take a closer look at some of the open source VCS of all generations. This might help you to choose the right one for your purpose.

Version control (pt. 1): An introduction

This post is the first part of a series on version control. It provides an introduction by explaining what that actually is, why you should probably use it and how it works in general.

Important terms

Version control (also: revision control) is a means of preserving various versions of a file or of multiple files. This can be done in a lot of different ways but over time some best-practices have emerged that are more or less followed in all modern version control systems.

There are lots of cases where version control makes sense. One of the most common ones is software development where using version control is virtually mandatory. That is why there’s even a separate term describing this form of version control: source (code) control or source code management.

We can group various version control systems together in two groups: local as well as network-based systems. The latter can be further differentiated between centralized and distributed ones.

In short: Why you may need it

Depending on the choice of the tool there can be various situation where you can benefit from version control:

  • Version control enables you to quickly return to an older, known-good state in case something broke
  • Version control gives you the possibility to precisely document any changes you made and thus provides both tractability and a quick overview of changes
  • Version control solves a lot of the problems that occur if multiple people work on the same files at the same time
  • Version control makes it simple to clearly find out the author of any change

Or as a former colleague of mine put it (in a very vivid way):
Why to use version control!

Manual version control

The simplest form of version control is working with a backup copy. You make a copy of e.g. a configuration file before making a change to the live file. Afterwards you test your changes and if they seem to work you either delete the backup or keep it for reference. If the changes had undesired effects, the original is overwritten with the backup (and the latter usually deleted again). This is actually a (rather primitive but sometimes sufficient) form of version control: Thanks to the backup copy you have two versions of the file at your hands!

Backup copy – we’ve all done it

Another variant is to make a copy after a fixed amount of time (or at random). Often people prepend the date to the file name. If all you want to accomplish is that e.g. the data as it was at of the first of each month is preserved for one year, that’s also a sufficient method (along with rotating the backup copies so that you don’t keep around more of them than you need).

Those means of manual version control are however pretty limited. And worse: There’s plenty of room for making mistakes!

Manual version control

How a version control system (VCS) works

Let’s think about a simplified versioning process by pretending to do things by hand. For each recorded change of a file you’d make a copy of the file and keep all the old versions of it. A VCS does not forget a single version of a file it monitors! That’s what it is meant to do, after all. Each new version of the file gets a comment that is meant to briefly sum up the changes that were made.

Keeping probably dozens or even hundreds of files around because one file has that many revisions, would really clutter your disk. Also it would not make sense to keep nearly the same file twice if only one line was changed! That’s why local VCS which also version on a per-file base, keep a “history file” around for each versioned file. That file records only the changes between the various versions as well as the comments.

Network-based VCS are able to organize a whole project (multiple files together instead of each one separately). They also record the changes instead of the full files for each revision as well as the comments. All of that data is collected in a so-called repository.

If a new team member wants to start working on the project, he or she first needs to get the files of that project. For centralized VCS this is done by checking out the most current revisions of all the project files from the remote repository. By doing so, a local working copy of the project files is created to be worked on by the user. When using a distributed VCS the remote repository is cloned instead (thus receiving the full repository with all revisions and not just the most current version of each file). The working copy is then checked out from the local repository clone.

At the beginning of a new project there is no repository, yet. In this case either an empty repository is created, checked out and the new working directory is populated with files. In a next step, those files are placed under version control (which means that the VCS is told to watch them and record changes). Then all changes (all of the files since they are all new right now) are placed into the repository by doing a commit.

After every change made to the project you do a commit again, recording the changed state inside the repository. Other project members can now get a current copy from the repository. This way it’s easy to work together on the same project without the risk of (unknowingly) get into the way of somebody else.

OpenBSD/FreeBSD (ZFS) dual-boot & thoughts about GPT/EFI

In the previous post I wrote about how to get a computer up and running with a dual-boot of FreeBSD and OpenBSD while using full disk encryption. This worked quite well but a bit later I decided that it would be a good time to do the FreeBSD installation again – this time going the modern way and using ZFS on root. This has led to a surprisingly large amount of problems. In the end I got a working system that uses ZFS, so that I’ve actually got an alternative howto for FreeBSD (the OpenBSD part remains the same as before and can be looked up in the previous post). But it’s all a bit different from what I first thought it would be.

Doing things today’s way: GPT

GPT (GUID Partition Table) is a more modern partitioning scheme meant to replace the old MBR style partitioning, redeeming us from limitations we had to live with in the past. It can deal with drives up to 8 Zettabyte (10²¹ Bytes) instead of being limited to 2 Terabyte (10¹² Bytes). That limitation used to be no problem and it still isn’t too bad for most home users since drives bigger than 2 TB are not that cheap, yet. But it obviously won’t be too long before this will be a common issue.

OpenBSD bootloader chainloaded by boot0

A more serious limitation is that MBR only supports 4 partitions. Yes, we all used to call these “primary partitions” and made use of “extended partitions” nested inside one of them to get around that limit. BSD users created disklabels instead to embed more partitions inside disk slices (“MBR partitions”). With GPT this is trouble of the past and you are free to create just about as many partitions as you think you need. There’s no need for embedding BSD disklabels or doing any MBR trickery – which is nice.

Also GPT supports naming partitions. So by using them we can do away with the old glabel mechanism that FreeBSD offers and use native GPT labeling instead. That advantage comes with a little disadvantage, though. By default FreeBSD’s gpart shows such partitions multiple times: Once by their label and once by GPT-id. This can be a bit confusing as you first come to the GPT world. Fortunately there’s a simple solution: Setting a sysctl you can simply disable GTP-ids if you opt for labels (which you should since they are much more meaningful).

GPT is a requirement for machines that use EFI booting. The good news is that all recent x86 hardware comes with EFI (and thus GPT) support. The bad news is that while some machines do support GPT when booting from EFI, they don’t if you choose to boot from legacy BIOS emulation. So if you want to stick to BIOS you may want to check if it is capable of booting a system on a GPT partition. My EliteBook 8470p is fine with GPT partitions in BIOS mode. So I was good to give GPT a try.

Problems with GPT

FreeBSD works great with GPT (and has done so for quite some time now) so there’s nothing wrong installing it using GPT partitions. The first obstacle that I encountered was the boot manager. FreeBSD comes with the nice and simple boot0 tool that I used in my previous howto. Too bad that it’s MBR only! So to continue down the path with GPT, it’s using another boot manager. Usually GRUB is used for that purpose. And while I would certainly prefer to go without a boot manager that has “grand” in its name, I think that using it is acceptable.

The FreeBSD bootloader

A bigger problem awaits, however. OpenBSD didn’t support GPT prior to the current version 5.9. Since it does now, everything should be fine, right? Wrong. If I didn’t miss anything, OpenBSD supports GPT only in conjunction with EFI booting! I did not find a way to use GPT partitions with OpenBSD in BIOS mode. Should anybody have more information on this, I’d very much like to know if it either is possible or if support for this is planned for the future.

Choosing EFI?

This means that not too far down the road there’s already a solid blocker. I had next to no knowledge about the EFI complex and I successfully avoided that topic in the past. So my two options to go on were to either give up on GPT and simply stick with MBR or to make the bold move and go for EFI. I would prefer to try out things one after another but meh… I decided to read a bit about the basics of EFI and then give it a try. To be honest, I don’t like what I read too much. Sure, there are quite a few interesting things that EFI can do. But then again I do not believe in unneccessary complexity. And above all: I don’t like the security implications of it. Not a bit. Trust is not something that I give away for free. Trust has to be earned. Unfortunately closed source vendors have done very little in the past that makes me think I want to trust them. Anyway… EFI is the (near?) future and it will not be easy to avoid it altogether in the next few years.

Alright. So I turned off legacy BIOS emulation on my machine and booted FreeBSD (there are separate EFI images for FreeBSD 10.3 – make sure you pick one of those if you want to go with EFI!) into the installer. Everything worked smoothly and after a couple of minutes my new FreeBSD system had booted. It was so simple and dull that there’s not too much I could write about (which is a good thing since everything really just worked).

Next step: Installing OpenBSD. I read that the memstick image supports EFI booting and I can confirm that installing works just as well as with FreeBSD. Again the new system works like a charm – the OpenBSD people have obviously done a good job for 5.9. OpenBSD was able to cope with GPT just like you would expect.

FreeBSD desktop: EDE, pcmanfm, terminator, smplayer

So far everything looked good. Final step: Make the computer offer a means of booting either system! Honestly I did not expect that step to be a show-stopper. It turned out that it is. Most people seem to use the EFI boot manager rEFInd. You can install it from Windows, OS X and Linux. Yes, that’s it. Now, I was not surprised that it was not ported to OpenBSD. But it did surprise me that it’s not available for FreeBSD!

It may be a quite simple thing to toss in a Linux CD and install an EFI bootloader – or maybe not. I have no clue if there are any other obstacles waiting. But this was the point where I stopped. I wanted a dual-boot BSD system and I don’t want to have to use Linux to do that. I’ve got my pride, too, you know. :p No seriously, at that point I decided to give up EFI for now and continue another time. Maybe that will be worth its own blog post. Who knows.

Back to BIOS / MBR… for now

Here we are, back to using BIOS / MBR. I wanted to use a purely ZFS setup for FreeBSD but another problem showed up: The bootcode to load a kernel from ZFS is quite a bit more complicated than its UFS equivalent. For that reason it doesn’t fit into the boot sector of a partition but needs its own small partition instead. However with gpart the type freebsd-boot seems to be only supported for GPT…

To get anything up and running again (for the time being my on-call laptop was broken after all and my next duty was around the corner!) I settled with a UFS boot partition for the unencrypted /boot partition.

Manual install: FreeBSD with ZFS, GELI

The auto_ashift adjustment is needed for ZFS to adhere the 4k alignment. And to be able to set that sysctl, the ZFS kernel module has to be loaded. That’s a little detail but it took me a moment to figure out what’s going on. Everybody advices to set the sysctl but the installer kept on telling me that there was no such sysctl… Which makes sense once you know that ZFS is not loaded into the kernel by default.

For the layout of the datasets I followed the defaults as used by the automated root-on-ZFS installation (zpool history is a very interesting command! If you don’t know it – try it!). I just changed the order so that similar datasets follow each other which avoids a bit of typing by bringing back the previous command and editing it.

It’s more likely than not that this is not the best way to do things. But it does work. Any suggestions or other comments are welcome of course!


In the partitioning shell:
tcsh
dd if=/dev/zero of=/dev/ada0 bs=1m
gpart create -s mbr ada0
gpart add -a 4k -t freebsd -s 98G ada0
gpart add -a 4k -t freebsd ada0
gpart create -s bsd ada0s1
gpart bootcode -b /boot/boot0 ada0
gpart bootcode -b /boot/boot ada0s1
gpart set -a active -i 1 ada0
gpart add -t freebsd-ufs -s 2G ada0s1
gpart add -t freebsd-swap -s 4G ada0s1
gpart add -t freebsd-zfs ada0s1
glabel label clear /dev/ada0s1a
glabel label swap /dev/ada0s1b
glabel label system /dev/ada0s1d
newfs /dev/label/clear
dd if=/dev/random of=/dev/label/system bs=1m
geli init -b -s 4096 -l 256 /dev/label/system
geli attach /dev/label/system
kldload zfs
sysctl vfs.zfs.min_auto_ashift=12
zpool create -o altroot=/mnt -O compress=lz4 -O \
atime=off -m none -f zroot /dev/label/system.eli
zfs create -o mountpoint=none zroot/ROOT
zfs create -o mountpoint=/ zroot/ROOT/default
zfs create -o mountpoint=/usr -o canmount=off zroot/usr
zfs create -o mountpoint=/var -o canmount=off zroot/var
zfs create -o mountpoint=/tmp -o exec=on -o setuid=off \
zroot/tmp
zfs create zroot/usr/home
zfs create zroot/usr/src
zfs create -o setuid=off zroot/usr/ports
zfs create -o setuid=off zroot/var/tmp
zfs create -o exec=off -o setuid=off zroot/var/audit
zfs create -o exec=off -o setuid=off zroot/var/crash
zfs create -o exec=off -o setuid=off zroot/var/log
zfs create -o atime=on zroot/var/mail
zfs set mountpoint=/zroot zroot
exit
exit

In the "final modifications" chroot:
mkdir /realboot
mount /dev/label/clear /realboot
mv /boot /realboot
ln -s /realboot/boot /boot
echo 'geom_eli_load="YES"' >> /boot/loader.conf
echo 'zfs_load="YES"' >> /boot/loader.conf
echo 'vfs.root.mountfrom="zfs:zroot/ROOT/default"' > \
/boot/loader.conf
echo '/dev/label/swap.eli none swap sw 0 0' >> \
/etc/fstab
echo '/dev/label/clear /realboot ufs rw 1 1' >> \
/etc/fstab
sysrc zfs_enable="YES"