oranki.net

The prettiest blog on the block


Self Hosting My Way - Primer

1st post in a series about self-hosting

I self-host some stuff, using Podman. There are a whole bunch of guides online, and it feels like most of them have consolidated on docker-compose. This is understandable, considering how Docker was the first in the field, and docker compose provides a nice way to do multi-container infrastructure as code-type deployments with just a single file.

When I started experimenting with self-hosting, I transitioned quickly from Docker to Podman. While I didn’t quite understand the implications at the time, the running rootless by default sounded good. The first thing I set up was Nextcloud, running with Docker. Thinking it makes things a whole lot easier, I added my user to the docker group, to allow running Docker commands without sudo as a regular user.

Running the Docker daemon in rootless mode is perfectly possible, but by default the daemon runs as root. This means you can do sudo docker run -v /:/mnt alpine ash and ta-da, you have full access to the entire filesystem. Combine that with the ability to run docker without sudo, you can see where this is going.

So, in comes Podman. There are plenty of technical articles discussing the differences of Podman vs Docker, I’m not going to go there. Suffice to say that using Podman for some years, I’m quite sure most self-hosters would be just fine running everything with rootless Podman. My opinion is if some service requires the extra privileges Docker provides by default, it’s probably a bit dubious anyway.

Podman kube play

The truly powerful feature of Podman is the ability to use Kubernetes-style YAML files to define multi-container deployments. Without going in too much detail, the smallest unit in Kubernetes is a pod, a unit containing one or more containers.

Inside a pod, if there are multiple containers, they can access ports that other containers’ services expose using localhost. This communication is possible without exposing any ports to the host system, in fact without explicitly forwarding ports from the pod, the services are not accessible from the host at all. But the services inside the pod can talk to each other.

This allows for great isolation of different services, and is in my opinion far easier to understand than the docker-compose way of relying on DNS on a dedicated container network.

Podman can read a subset of the Kuberneres YAML spec, and deploy pods using those definitions. The format is slightly more complex than the docker-compose spec, but the upside is that you get your foot between the door for Kubernetes. For most self-hosters Kubernetes is overkill, but learning about it is still a big plus in my opinion.

Quadlet

Quadlet is Red Hat’s component for executing containerized workloads. Using it, systemd acts kind of as an orchestrator like Kubernetes, while Podman is used for the execution of these services.

Quadlet is already quite featureful, and I’ve only scratched the surface. The main reason I use it is it comes bundled with later versions of Podman, at least on the RHELative distros. Keeping extra dependencies to mininum simplifies maintenance.

One thing I don’t like about Quadlet is the need to remember the systemd unit syntax in addition to Podman Kube YAML.

ZFS

If only the licensing complications between Linux and ZFS could be just forgotten. Meanwhile, ZFS is in my non-expert opinion the most robust filesystem for storing data.

In the self-hosted context, I store all persistent data (bind mounts) on ZFS. Podman provides some native integration with ZFS. For rootful stuff I think it could be directly used as the storage driver, but overlayfs is simpler, and the performance is more than enough for the home server scale.

There’s the common misconception of requiring a ton of RAM with ZFS. While extra RAM speeds things up a lot, more so than with other filesystems, it’s not the necessity it was before. What ZFS does provide, is the ability to do backups with minimal downtime while keeping the backups consistent. You can achieve the same with other snapshotting mechanisms, but ZFS’s tooling is really straightforward while having all the bells and whistles. More on backups later on a separate post.

Borg for off-site backups

While ZFS would provide a very effective way to replicate datasets to remote hosts by using zfs send | zfs receive over SSH, I’ve come to the conclusion that having all backups dependent on the filesystem is a bit restrictive. Not to mention I’ve been using Borg from the start, so sticking with it means continuing with the existing setup.

Borg provides deduplicated, incremental, encrypted and compressed backups, and is very good at doing what it does. A remote backup site can be almost any *nix host with SSH and borgbackup installed.

I used to execute the daily and automated remote backups using shell scripts and cron. Those scripts are still around and work, but they were getting a bit elaborate to maintain. I’ve since moved to borgmatic, to get a bit more declarative approach to backups. This required a bit of fiddling and perhaps even abusing borgmatic’s ability to run pre and post scripts, but it works well. Borgmatic also includes backup configuration files in the backups, so they are easier to transfer to other hosts too.

Wrapping up

These are the basic building blocks for what is in my mind a somewhat reliable setup for running important services. For example, my personal Nextcloud hosts calendar and contacts, which replace the respective Google services on Android on my phone. I wouldn’t want that going out of business all of a sudden.

In the next post on the series, I’ll be covering the layout of my setup. The main idea is that it’s quite easy to lift and shift it elsewhere. Some may consider it a useless perk, but when self-hosting is also a hobby, keeping the services as transferrable as possible is a big advantage.