Over the past few months, I’ve been slowly streamlining my day-to-day routine. One of the first things I do when I start my work day is try to catch up on current events in my research area. For awhile now, my process has been to use my phone to check for new articles or posts on a set of websites. I realized that I could reduce both the amount of time I spent doing this by using an RSS feed reader. I ended up choosing Tiny Tiny RSS1 because it’s lightweight and can be self-hosted.

Self-Hosting Tiny Tiny RSS (tt-rss)

I haven’t done much self-hosting in the past, so I figured this would be a great place to start. My home network lacks a static IP, so I decided to host tt-rss via a VPS provider. I ended up choosing Vultr2, primarily based on the reviews provided by joshtronic3. Creating a Linux instance was quick and easy and took less than five minutes after the initial signup.

Once the Linux instance was configured, the installation process for tt-rss was relatively straightforward. For the sake of convenience, I deployed using the provided, static docker images4. The tt-rss docker install FAQ provides additional details on how to install with TLS enabled5. TLS support requires an externally reachable domain name. I decided to put in the extra effort to set up TLS since I already owned a domain name. I was able to link the IP of my server to the domain name via Vultr by following these steps:

1. Log into your domain name registrar
2. Change your domain’s name servers to Vultrs’ (you may need to wait up to a day for the name server changes to propagate)


3. Log into the Vultr management portal
4. Select your server (make a copy of its IP address) and use the “…” side menu to open the “Server Details” page
5. Click the plus sign and “Add Domain”
6. Enter your domain name and the IP of the server

Once your domain is configured, you can continue following the TLS steps. When you are ready to run docker compose, I suggest doing so in a tmux or screen window. You can check to see if your install succeeded by visiting the tt-rss frontend via your domain (e.g. https://mydomainname/tt-rss/). I made the mistake of not properly setting SELF_URL_PATH in my .env file. Luckily, the resultant error message supplied the expected value. Changing that required terminating the running docker containers and making the required change to my .env file.

Emacs Integration with elfeed

Following the process in the section above was sufficient for creating a functional, self-hosted tt-rss instance. However, I wanted to take it a step further and integrate tt-rss with my emacs environment. This was made possible by the elfeed package6.

To setup elfeed to receive data from a tt-rss instance requires both the elfeed and elfeed-protocol packages, both of which are available on melpa. Once you install both packages, you’ll need to configure them. Added the following lines to your emacs config file:

;; elfeed
(require 'elfeed)
(require 'elfeed-protocol)
;; debugging
(setq elfeed-use-curl t)
(setq elfeed-log-level 'debug)
(setq elfeed-protocol-log-trace t)
;; feeds
(setq elfeed-feeds
      :password "<password>")))

The debugging lines are included in case something goes wrong during the setup. Once you have everything working, feel free to remove them. To incorporate your tt-rss feed, replace <username> and <domain_name> with the user name used to log into tt-rss at the specified domain. Similarly, replace <password> with the password for the specified user name.

Once your emacs environment is configured, you’ll need to log into your tt-rss web management page, and enabled API usage:

1. Log into tt-rss as the user specified in <username>
2. Select “Preferences”
3. Under “General,” check the “Enable API” box
4. Save your changes

Now, test your setup:

1. Start emacs
2. M-x elfeed
3. M-x elfeed-update
4. Wait for a minute or two

If everything worked, you should see your feed updates in your emacs window. If not, now is the time to use those extra debugging flags. Navigate to the *elfeed-log* buffer (space – b – B in doom emacs) and check for error messages.


I’ve only been using the setup for a few days, but I have already noticed a difference in my productivity. Since all of my information sources are now concentrated in a single location, I spend less time mindlessly perusing the internet. Additionally, this setup has helped me spend less time on my phone. Before, I found myself constantly getting distracted by checking sites on my phone. By forcing myself to go through my desktop, it has been easier to resist this temptation, especially if I’m not working at my computer.

1 Tiny Tiny RSS


3 VPS Showdown

4 Install tt-rss

5 TLS tt-rss Configuration

6 elfeed




For the past few weeks, I’ve found myself spending a lot of time doing FreeBSD kernel hacking. The biggest issue I had starting out was establishing an efficient development and testing workflow. I wasn’t willing to blow away the OS on my laptop and install FreeBSD on bare metal, so virtualization seemed like the best route to take. Most of the references that I found involved a two virtual machine (VM) setup. In these setups, development occurs on the first VM while testing of the modified kernel occurs in a second, diskless PXE-booted VM1. However, during that initial background reading phase, I also came across an article describing a process for loading custom kernels with bhyve2. After reading that article, I decided to try going a similar route but instead leveraging nested virtualization to create the bhyve VM inside of a FreeBSD VM running under KVM. The rest of this post details the steps I had to take to get the entire setup working.

Environment Structure

The following diagram outlines the target environment structure:

L0 : Baremetal (Ubuntu 16.04 LTS)
— L1 : Guest OS (FreeBSD 12.0)
—— L2 : Nested Guest OS (FreeBSD 12.0)

The terms L0, L1, and L2 will be used throughout this article. For clarification, all of the development work was done in L1 and the testing of the modified kernel was done in L2. Both L1 and L2 ran FreeBSD 12. L0 ran Ubuntu 16.04 LTS. L0 was an Acer Aspire F15 with an Intel i5-7200U4. This is an important detail since your underlying processor needs to support both EPT (or equivalent) and VT-X4.

Setup and Configuration.

The following steps give a general outline of the process I followed to create the nested virtual development environment.

  1. Install the necessary software and ISOs on L0
    • KVM
    • ISOs for whatever FreeBSD versions you want to run in L1 and L2 (I used FreeBSD 12.0)
  2. Configure L0 to enable KVM’s5
  3. Create the L1 guest with QEMU/KVM and install FreeBSD6
    • qemu-img create -f raw image_file 4G
    • qemu-system-x86_64 -name image_name -cdrom iso_image -boot order=d -drive file=__disk_image__,format=raw
  4. Modify the L1 VM config to pass through VT-X
    • run “virsh edit image_name”
      • Change the “cpu” entry to match this:
        <cpu mode= ‘host passthrough’>
        <feature policy=’require’ name=’vmx’/>
  5. Start L1 (restart if the VM was running when the configuration change was made)
    • run “virsh start vm_name
  6. Log into L1 and check to make sure that VT-X is enabled
    • One way to test is to run “sudo dmesg | grep vmx”
      • If you see something similar to vmx_init: processor does not support VMX operation, then VMX is not enabled
  7. Configure L1 to your desired development environment. Make sure to download the ISO for the version of FreeBSD to which you will be deploying your modified kernel.
  8. Ensure that bhyve is installed.
    • Try to add it with “pkg install bhyve”
  9. Build your modified kernel.
    1. This post assumes that you already know what to do doing this step. If you don’t the FreeBSD documentation7 is a good place to start.
  10. From here, follow the steps outlined in one of the previously mentioned articles2. I suggest reading the entire article, but following the directions in the “Configuring Guests,” and “Using a bhyve Guest as a Target” sections should suffice. At a high level, the idea is to create a bhyve VM (L2) with a base FreeBSD ISO, but override the version of the kernel in the ISO with the modified kernel residing on L1.
  11. If everything worked, L2 should run a base version of FreeBSD with your modified kernel. Depending on your kernel build process, you may be able to verify this by checking the output of the “uname -a” command.


Once everything is working, your development process should look something like this:
  1. Checkout your kernel source code in L1
  2. Build your modified kernel in L1
  3. Deploy a new VM (L2) from within L1 that runs your modified kernel using bhyve -H
  4. Boot L2 and perform your kernel testing
  5. Rinse and repeat as necessary


1 FreeBSD diskless on VirtualBox

2 Using bhyve for FreeBSD Development

3 Intel i5-7200U

4 FreeBSD as a Host with bhyve

5 Nested Guests


7 Chapter 9. Building and Installing a FreeBSD Kernel

Categories FreeBSD, Virtualization