How and what i self host

coding

Photo by Luca Bravo on Unsplash

Self Hosting

Since i’m a long time lurker of r/selfhosted and the amount of stuff i host for myself increases ever after, i decieded to make a quick blog post about how i host that stuff, how i deploy it and which services are or are not currently publicly available.

How i host stuff

Since this is my side project and i consider myself fairly minimalist i tried to keep the setup here so basic, that i know how this all works, even if i do not look at it for over a year. All my stuff is hosted on a Hetzner CPX21 VM running Ubuntu LTS. I do not do backups of the stuff i host here. Most of the things are either disposable or aren’t worth retaining.

The VM can be recreated at any time using a single terraform resource, all the initial configuration is done via cloud-init. If Hetzner decides to kill or corrupt my machine or i do stupid things, i’m able to rebuilt it in less than two minutes. In my cloud-init setup there is included:

  • Installing basic packages like vim, git, openjdk-8-jre..
  • The Caddy Setup (which acts as the point of entry for all user traffic and this website)
  • SSH Setup, configuring fail2ban, adding my ssh public keys
  • Setting up prometheus, node-exporter and my personal gitlab-runner for the gitlab.com instance
  • finally, my wireguard configuration is also distributed and wireguard is set up

The installation and hosting of the apps is done using containers. I did not want to put them all in the cloud-init script, it is already large enough anyways. I got a folder structure like this:

├── grafana
│   ├── grafana.ini
│   └── Makefile
├── minecraft
│   └── Makefile
├── ots
│   └── Makefile
├── prometheus
│   ├── Makefile
│   └── prometheus.yml
├── uptimekuma
│   └── Makefile
└── wastebin
    └── Makefile

Each folder represents an application i host and the Makefile has mostly only one single target: deploy. this website is also a “self hosted app” and has a similar Makefile.

This target runs the deployment using ssh and starts the container. Sometimes i additionally configure stuff using other commands but the OTS example below shows my basic Makefile i reuse:

deploy:
	ssh hetzner docker rm -f ots || true
	ssh hetzner docker pull docker.io/luzifer/ots:v1.0.0
	ssh hetzner docker run -d -p 127.0.0.1:3444:3000 --restart=always --name ots docker.io/luzifer/ots:v1.0.0

The app is then exposed using Caddy using the reverse_proxy directive:

ots.alxndr13.xyz {
	reverse_proxy localhost:3444
}

In case of a corrupt machine where i need to start from scratch i got a deploy_all.sh script in the top-level folder which cd’s in all the subfolders and runs make deploy. Takes about 30 seconds for all the containers to pull and start. Add that to the two minutes until the VM instance is ready, we’re then back in 2:30 minutes for all my stuff.

To summarize:

  • cloud-init and a single terraform instance provisions the vm
  • deploy_all.sh script deploys all the apps

What i host

publicly available

Privately

  • a Grafana Instance
  • a Prometheus Instance
  • a Minecraft Server
  • my own Gitlab Runner
  • a Redis Instance
  • a Wireguard Node (which i mostly use to surf when in public WiFi Networks or to access my home network)

Some manual labor

The only things i had to do manually over the last 2 years were:

  • upgrade docker images of the apps
  • Download the minecraft world folder so that someone of the lads has a copy, just in case

APT Upgrades are handled using UnattendedUpgrades

Update 27th July 2023

Today i added an personal owncloud instance to my repertoire: owncloud.alxndr13.xyz.

I was amazed what the owncloud team achieved with their Go rewrite. The docker image is small, setup is easy and everything was up and running in less than 20 minutes. Performance is way better than what i had in mind when i last tried it. Good job, folks!