First time I heard about Plex was perhaps 2-3 years ago. A friend of mine was traveling from the US to EU was telling how he’s watching (streaming) movies from his home server on his tablet and how perfectly it all works.

Until now I’ve always had some sort of home media server, some storage box that keeps my media.
For the last couple of years it has been an HP MicroServer running FreeBSD with ZFS.

At home I use a RaspberryPi connected to my TV that runs KODI and mounts media share from the FreeBSD box. This works ok. Scripts run periodically to pull subtitles and shares can be mounted wherever.

But there’s a new challenge. I now spend more and more time between two cities and my media being at home sort of sucks as there’s no simple way of accessing it. Yes I do have a VPN but still.
Also accessing media from mobile seems like a great thing to have when on the go.

So I heard about Plex being good at supporting FreeBSD a week ago and I’m giving it a try.
First impression – poorly documented configuration (in case you have several subnets at home it does not work at all by default) but other than that seems quite capable. Will have to try out the premium features.


As much as I enjoy hardcore command line stuff, it is nice to have some eye candy there as well.

Like htop, for example.
However I have recently discovered vtop.
Not sure about the practicality of it but it sure looks nice (albeit at the expense of some additional cpu cycles):

If you have node installed then installing vtop is just a matter of running:

sudo npm install -g vtop  

And as if that’s not enough, it supports themes 🙂

Running Windows on FreeBSD using Bhyve

Yes, it’s possible since beginning of October if you run FreeBSD 11-CURRENT.

I have waited for quite a while for this. This means no more need for KVM or XEN or what have you.
Bhyve does it all.

It’s a bit rough around the edges. Biggest issue (at least for me) is the lack of video support but serial console is there and that is enough to get going. The documentation on windows installation is a bit lacking, but this will probably change quickly as it only just got pushed to CURRENT.

I have had it running for a day now and it seems stable to me.

Currently all the docs regarding Windows on Bhyve that are available (that I’m aware off) are here:

And really that is enough to get you going and if you have had some experience with bhyve before then you’re probably going to be ok.

These are my notes on getting Windows 2012 R2 running on Bhyve.

First, make sure bhyve is usable on your machine. Try booting some linux vm as a test.

Get an installation ISO.
I happen to have an MSDN subscription so this is where I got mine.

I used en_windows_server_2012_r2_with_update_x64_dvd_4065220.iso

You will have to modify the ISO, so make sure you have the tools for that:

pkg install cdrtools-devel p7zip  

Since there is no video output, the installation has to happen automatically. Luckily windows does support this. What you need is a Autounattend.xml file to be present in the root of your installation ISO file.

There are excellent examples available on github. So let’s clone that:

git clone  

I used win2012r2_AutoUnattend.xml file and the only modification I did was adding the product key:
Find the line

<ProductKey />  

And replace it with actual key:


Then rename the file to AutoUnattend.xml and keep it as you’ll need it in a moment. I kept mine in ~/

Next step, get the virtio drivers:


Extract the windows installation ISO. I extract mine into destination directory win2k12r2 like so:

7z -owin2k12r2 x en_windows_server_2012_r2_with_update_x64_dvd_4065220.iso  

change into this directory and copy over the prepared AutoUnattend.xml file so that it would now be in the root of the unpacked ISO:

cd win2k12r2  
cp ~/AutoUnattend.xml .  

now, you need to add the virtio drivers.
Again, while being in the root of the unpacked ISO, create a directory virtio and unpack the virtio drivers there:

mkdir virtio  
tar xfv ~/virtio-win-0.1.96.iso  

These are all the modifications needed, so you can go ahead and re-pack the ISO:

mkisofs \  
    -b boot/ -no-emul-boot -c BOOT.CAT \
    -iso-level 4 -J -l -D \
    -N -joliet-long \
    -relaxed-filenames -v \
    -V "Custom" -udf \
    -boot-info-table -eltorito-alt-boot -eltorito-platform 0xEF \
    -eltorito-boot efi/microsoft/boot/efisys_noprompt.bin \
    -no-emul-boot \
    -o ~/win_repack.iso .

Now, one last dependency before you boot it, you need the UEFI binary as modern Windows versions require UEFI:


Create a file that will serve as the disk for your Windows VM

truncate -s 30G win.img  

Make sure that nmdm module is loaded as we’ll use serial console:

kldload nmdm  

You can now start the installation:

bhyve \  
      -c 2 \
      -s 0,hostbridge \
      -s 3,ahci-hd,win.img \
      -s 4,ahci-cd,win_repack.iso \
      -s 10,virtio-net,tap0 \
      -s 31,lpc \
      -l com1,/dev/nmdm0A \
      -l com2,/dev/nmdm1A \
      -l bootrom,BHYVE_UEFI_20151002.fd \
      -m 2G -H -w \

Once the bhyve process is running, you can connect to the serial port from another console:

cu -l /dev/nmdm0B -s 9600  

Once connected, you’ll find yourself in Special Administration Console. Type ch to get a list of channels and once the installation has started you can follow the progress by connecting to channel #1 by typing:

ch -si 1  

The first stage of installation will copy over the files and eventually the machine will reboot. At this point the bhyve process will exit and you’ll have to restart it. This time, do it without attaching the ISO:

bhyve \  
      -c 2 \
      -s 0,hostbridge \
      -s 3,ahci-hd,win.img \
      -s 10,virtio-net,tap0 \
      -s 31,lpc \
      -l com1,/dev/nmdm0A \
      -l com2,/dev/nmdm1A \
      -l bootrom,BHYVE_UEFI_20151002.fd \
      -m 2G -H -w \

This stage again takes a bit of time but eventually you are done.

I ran vmstat to see when it settles down.

Once it has, you can type i in the SAC console to find out the IP address that your new Windows VM got from the DHCP and then you can connect over RDP.

The default username is Administrator and the default password is Test123 but you can change that in the AutoUnattend.xml

That’s it. Can’t say that it’s straightforward, but it’s certainly doable and if you’ve done it once then it all makes sense.

The iOS 9 podcasts app is terrible

I love listening to podcasts while commuting since I get to learn something on the way. This is especially great on longer trips.

I have been using the iOS podcasts app so that I add select podcast episodes to “On the go” playlist and then whenever I’m driving somewhere I know that I have a list of podcasts to listen to.

To my big surprise Apple has ruined the Podcasts app by removing the “on the go” playlist. There is in fact no way to create a playlist anymore. You can queue up podcast episodes but that’s about it.

This is a huge fail IMO. Yet again Apple has decided on what should be the best way to do things and I don’t like their way at all. They want you to listen to all recent episodes, but this is not at all how I like to do it.

And I’m not the only one with such opinion

Azure + Packer

Yes, it works. How cool is that?
The hardest part is to set up your environment and even that is easy. Kudos to MS.

What you’ll need: a linux machine, golang, packer, Azure plugin for packer, nodejs, Azure cli tools and an Azure subscription.

I’ll start with a clean Ubuntu 14.04 machine.
Let’s start by installing node, npm, git and mercurial (which you’ll need to install the Azure packer plugin).

sudo apt-get install node npm git mercurial  

In Ubuntu node binary is called nodejs because there’s another package called node. One quick fix is to symlink nodejs to node.

sudo ln -s /usr/bin/nodejs /usr/bin/node  

Then we need to install Azure CLI tools. For this we use npm:

sudo npm -g install azure-cli  

And packer. But in order to use Packer and the Azure plugin for Packer you first have to have a recent version of Go (>=1.4).


Unpack it somewhere. I use ~/opt/go
Now we set it up

export PATH=$HOME/opt/go/bin:$PATH  
export GOROOT=$HOME/opt/go  
export GOPATH=$HOME/go  

You might want to add these to your shell settings (like .bashrc).
Test by running go version. You should see something like:

fx@azure-playground:~$ go version  
go version go1.5.1 linux/amd64  

Download packer from and unpack it:

unzip -d packer  

Now, install the Azure plugin for Packer

cd packer  
# the built plugin will be placed in current directory
export GOBIN=$PWD  
go get  

Now, set up Azure CLI if you haven’t done so already.
This is as easy as

azure account download  

This will give you a link to download your settings file. This will have to be done using a real browser. Once you have it, set it up:

azure account import ~/azuresubscription.publishsettings  

In order to use packer, you need a storage account:

azure storage account create packer -l "North Europe" -d "My Packer images" --type GRS  

Now is the moment of truth, if everything went well up to now then you should be able to create a packer image.
Let’s create a very minimal packer json file:

  "variables": {
    "sn": "Windows Azure MSDN - Visual Studio Ultimate",
    "ps": "/home/fx/azuresubscription.publishsettings",
    "sa": "packer"
  "builders": [
      "type": "azure",
      "publish_settings_path": "{{user `ps`}}",
      "subscription_name": "{{user `sn`}}",
      "storage_account": "{{user `sa`}}",
      "storage_account_container": "images",
      "os_type": "Linux",
      "os_image_label": "Ubuntu Server 14.04 LTS",
      "location": "North Europe",
      "instance_size": "Small",
      "user_image_label": "Ubuntu1404LTS"
  "provisioners": [
      "execute_command": "chmod +x {{ .Path }}; {{ .Vars }} sudo -E sh '{{ .Path }}'",
      "inline": [
        "sudo apt-get update",
        "sudo apt-get -y upgrade"
      "inline_shebang": "/bin/sh -x",
      "type": "shell"

You can see more examples on github.
Save it as ubuntu.json and check for errors:

./packer validate ubuntu.json

If no errors were reported, go ahead and build it:

./packer build ubuntu.json

Once the build is done you’ll see something like

==> Builds finished. The artifacts of successful builds are:
--> azure: {imageLabel: 'Ubuntu1404LTS',imageName: 'Ubuntu1404LTS_2015-09-27_13-55',mediaLocation: ''}

Confirm by running:

azure vm image show Ubuntu1404LTS_2015-09-27_13-55  

Congrats, you have your first Packer image on Azure

Battlefield 4 campaign sucks and games in general

Yes, this is probably common knowledge in the gamer community, but it was a bit surprising to me since I’m no gamer.
Imagine, you are shooting your way through the mission and you have couple of good guys with you, yet they can’t seem to shoot anyone and they also never die. They are worse than worthless as they create the illusion of you having some assistance which is not true.
Next example, you need to fetch a missile launcher but one of your guys is standing in front of stairs that you need to take in order to get that said launcher. And the only solution is to shoot your own guy. It’s even on reddit.

Guess I should have read the reviews. But i’s ok as I only spent 10 euros on the game as it is quite old and the multiplayer is quite OK.

Why am I writing all this? Well, I have an old (by todays standard) PS3 console. It usually just sits and collects dust but from time to time I do get the urge to play something, so I buy some older game, play for a week or two and move on. This is actually quite interesting, new games cost 40 – 60 euros. In a year they cost only 20-30 and in 2 years you can get them for a price of a movie ticket. It’s not that I’m cheap, but somehow I can’t bring myself to pay 60 euros for a game that I might get bored with in a week.


For I while now I wanted to complete the Linux Foundation Certified Sysadmin exam and this week I did it. Yay!

If you’re a linux admin then this will not present too much difficulty to pass it. The LF certification page explains what domains and competencies will be tested and this can be used to prep for exam if needed.

The exam format is really cool, you get a console access to a linux vm (several choices of distros) and you are asked to do various sysadmin tasks. Nothing too complicated but might be something you don’t get to do too often.

I truly enjoyed the tasks and I learned a couple of new arguments to commands while doing them (you are free to use the man pages during the exam).

You get 2 hours to complete the tasks and that still allows you some time for readig man pages if needed.

For my preparation I spent two evenings reviewing the required domains and competencies and I passed the exam with a score of 92%.

Try it, it’s fun and interesting and at the end you get to add something to your resume.

Surface 3

So I recently bought a Surface 3. Yes, I know. My home network has been a mix of OSX, iOS, Linux and FreeBSD devices but now it will also have one Windows machine.

Surface 3
This is also my first time buying a computer that runs Windows.
The device itself is quite awesome, I really do like it and especially at that price point where it competes with an iPad. It’s a very capable device if you can live with Windows running on it.
In fact I’m writing this post on it. I also owned the first Surface RT and that was garbage. But with Surface 3 things have changed.

The form factor is good, the screen is great and battery life is decent. It has no trouble playing videos, browsing web, editing office docs and of course, you can run putty and manage your unix boxes. It can do anything, it’s just not super fast when it does it.

This Surface uses an Intel Atom quad core SoC. It has 4 GB of RAM and a 128 GB storage (not and SSD though but some other, slower kind of flash). You can expand the storage using a microSD card (yes it will be a bit slow) and you can plug in any USB device you want.

But most importantly for me – you can charge it using micro USB. Yes, you need a capable charger, with a 1A charger it does take quite a while but if you have a 2A charger then it is much better.
And of course micro usb means – charge it from your battery pack, which means use it on the long flights/trips which is great.

Overall quite happy with it.

NFS exports with ZFS

If you have a ZFS based storage server and other machines in the network, it would be a shame not to share the awesome storage with them.

I have 2 servers at home.
frisbie is the ZFS storage machine and yotta is just a powerful machine but with only one disk, so I’d like to run VMs on it but I’d also like to avoid crying whenever the disk on it dies 🙂

First, enable and start up all the required daemons for NFS server to function.

sysrc -f /etc/rc.conf nfs_server_enable="YES"  
sysrc -f /etc/rc.conf rpc_lockd_enable="YES"  
sysrc -f /etc/rc.conf rpc_statd_enable="YES"  
for service in {nfsd,statd,lockd}; do service $service start; done  

So I create a new zfs filesystem on Frisbie

zfs create data/yotta_bhyve  

And then set it to be shared via NFS:

zfs set sharenfs="-maproot=root yotta,rw" data/yotta_bhyve  

The maproot option on FreeBSD is the same as nosquashroot on linux. Since I will be using it as root on my client I need it to work. Might not be elegant, but hey…

On the client:

sysrc -f /etc/rc.conf nfs_client_enable="YES"  
service nfsclient start  
mkdir /bhyve  
mount frisbie:/data/yotta_bhyve /bhyve  

And afterwards it makes sense to add something like this to /etc/fstab

frisbie:/data/yotta_bhyve /bhyve        nfs     rw      0       0  

Docker on FreeBSD

Docker is now available of FreeBSD.
How cool is that?
And setup is so simple that it would be a shame not to try it out:

sudo pkg install docker-freebsd ca_root_nss  

As seems to be the case quite often with FreeBSD packages, after installing the package you get quite nice instructions on what to do next:

[fx@yotta /usr/home/fx]$ sudo pkg install docker-freebsd
Updating yotta.tln repository catalogue...  
Fetching meta.txz: 100%    264 B   0.3kB/s    00:01  
Fetching packagesite.txz: 100%   56 KiB  57.3kB/s    00:01  
Processing entries: 100%  
yotta.tln repository update completed. 209 packages processed.  
The following 2 package(s) will be affected (of 0 checked):

New packages to be INSTALLED:  
        docker-freebsd: 06252015
        go: 1.4.2,1

The process will require 142 MiB more space.  
23 MiB to be downloaded.

Proceed with this action? [y/N]: y  
Fetching docker-freebsd-06252015.txz: 100%    3 MiB   2.8MB/s    00:01  
Fetching go-1.4.2,1.txz: 100%   21 MiB  21.6MB/s    00:01  
Checking integrity... done (0 conflicting)  
[1/2] Installing go-1.4.2,1...
[1/2] Extracting go-1.4.2,1: 100%
[2/2] Installing docker-freebsd-06252015...
[2/2] Extracting docker-freebsd-06252015: 100%
Message for docker-freebsd-06252015:  
Docker requires a bit of setup before usage.

You will need to create a ZFS dataset on /usr/docker

# zfs create -o mountpoint=/usr/docker <zroot>/docker

And lastly enable the docker daemon  
# sysrc -f /etc/rc.conf docker_enable="YES"
# service docker start


Starting the docker service will also add the following PF rule:

nat on ${iface} from to any -> (${iface})

Where $iface is the default NIC on the system, or the value  
of $docker_nat_iface. This is for network connectivity to docker  
containers in this early port. This should not be needed in future  
versions of docker.  

So I did what the nice instruction said to do:

sudo zfs create -o mountpoint=/usr/docker zroot/docker  
sudo sysrc -f /etc/rc.conf docker_enable="YES"  
sudo service docker start  

It really is that simple.

So now, to run a Debian container, simply download and run it by doing:

sudo docker pull debian  

and then run a bash shell inside of Debian container

sudo docker run -t -i debian /bin/bash  


[fx@yotta /usr/home/fx]$ sudo docker run -t -i debian /bin/bash
root@:/# uname -a  
Linux  2.6.32 FreeBSD 11.0-CURRENT #0 r285684: Sun Jul 19 10:19:35 UTC 2015 x86_64 GNU/Linux  

One slight issue is that it is still experimental and some stuff does not seem to work.
For example in a Debian Wheezy container mostly everything segfaults:

[fx@yotta ~]$ docker run -t -t debian:wheezy /bin/bash
jail: /bin/bash: exited on signal 11  

stracing does not help because it does not work:

strace: test_ptrace_setoptions_for_all: PTRACE_TRACEME doesn't work: Function not implemented  

But other than that stuff works and it does not get much more simpler than that.
You get Docker + ZFS.
One reason less to run linux as your host os.