Image of a PC under a desk Image of a PC under a desk

Hardware:

Some old PC my uni computer lab was going to throw away otherwise along with my previous router (TL-WR841N), configured to function in AP mode.

It also has a 128 GB SSD as well as a 1 TB HDD.

Tech Stack:

  • Proxmox is used as the hypervisor.
  • Networking is handled by virtualized OPNSense, both for VMs and for my various devices, which is why the TL-WR841N is in AP mode. I did consider flashing it with OpenWRT, but it is not supported by the latest version, and I did not want to risk bricking it as it’s my only such device. I don’t run a pi-hole as it’s made redundant by the unbound DNS blocklist feature in OPNSense.
  • As my home network is behind CG-NAT, a VM keeps a constant wireguard connection up to a hosthatch VPS. This allows port forwarding for a remote proxy as well as connecting into my LAN via wireguard.
  • Services are run using docker compose in their own individual Fedora VMs.

Presently running services:

  • Synapse server for matrix. In addition, it has sliding sync (to allow usage with ElementX) and is bridged with mautrix-meta so it can also receive messages from instagram.
  • Forgejo git instance.
  • Seafile for file syncing (for obsidian notes as well as for jellyfin media) and backups of important documents. Nextcloud was considered, but seafile was apparently simpler to setup and less buggier.
  • Jellyfin for having a cross-device music library.

Security:

  • The LAN is not treated as a reliable security boundary, all services have restrictive firewall rules, and TLS is used for everything, including the proxmox and OPNSense web UIs. Certs are acquired using acme.sh and auto renewed using scoped deSEC tokens.
  • No wildcard certs are used. Just because the deSEC DNS token for one service is compromised doesn’t mean it can be used to issue TLS certificates for another subdomain (or for the base domain).
  • Where possible, Chainguard images are used in order to be as up to date and have as minimal attack surface as possible. Otherwise, Polarix containers are used. gVisor is also used as a hardened runtime for all compatible containers. Otherwise, an entire VM is allocated to the service (in the case of forgejo-runner). In the case of jellyfin, a custom build is used to patch out gvisor incompatible code.
  • dnf packages and docker images are auto updated daily. gvisor is auto updated every boot.
  • The hardware is too old to have a TPM 2.0, but I currently use a LUKS2 keyfile to encrypt the SSD where proxmox is installed. The HDD (where the VM disks are stored) is encrypted using ZFS native encryption to maintain performance. This doesn’t really protect against someone breaking into my home and disassembling the PC, but it does save me from having to worry about leaking sensitive data when I dispose of the drives in the distant future.
  • SSH is configured based off of GrapheneOS infrastructure’s config, only public key auth and modern ciphers with key exchange methods are allowed.

Miscellaneous config files can be found here.

Future plans:

  • Learn ansible. Right now, I simply clone a VM which I keep as a base template, but that can get cumbersome when I want to make a change to it.
  • Document my current configs better so I’m not completely lost when I come back to it six months from now.
  • Self host more services such as Xanity or morss
  • Have a better backup strategy. Right now there is no redundancy or backup if the hardware gets damaged.