What's running in my Homelab? (Oct 2025)

Oct 22, 2025 · 6 minutes read

Table of contents

diagram

Introduction

In this blog post, I’ll give an overview of “how” and “what” I’m running in my home lab setup as of October 2025. For the “how” part, I’ll focus on the hardware, virtualization and networking aspects since they form the foundation that supports everything else.

How

As of now, there are only two servers running my entire homelab:

I also use the Beelink S12 connected to my TV to consume content from Youtube, Jellyfin, or other streaming platforms. Although the setup has enough resources to manage the entire homelab, sometimes, when I’ve had a lot of Youtube tabs opened (and I mean a looot), I’ve run out of memory. This has happened only twice in a year, so it’s not something super urgent to fix — and it helps to keep my browser tabs diet in check at the same time :)

DNS and DHCP

I use Pi-hole for DNS, DHCP and adblocking at the DNS level. Pi-hole acts as a recursive DNS server, forwarding public DNS queries to unbound, which then forwards those queries to the public DNS server via DNS over TLS.

Every machine in my LAN requesting an IP address via DHCP will get a domain name assigned by Pi-hole.

For the actual services, I configure a CNAME entry pointing to the actual machine that runs a given service. For example, for Immich, I have a domain in pihole like immich.jtorr.eu as a CNAME record pointing to incus-container-1.lan. If I later decide to move that service to a different machine, I only need to change the CNAME record.

There are two pi-hole nodes on my LAN: the main one runs in the Raspberry Pi and another as a backup in the Beelink server. DHCP is configured so that it returns both DNS servers. The two pi-hole instances respond to DHCP requests on the LAN. This setup makes the LAN (sort of) work even if one of the nodes is down.

Let me explain the “sort of” piece. If the Raspberry Pi is down, a client will make a DNS query. Since it is down, it will fail so it will try with the second DNS server. This makes DNS queries slower but at least every node in the LAN has internet. I might try using keepalived to improve this like @TechnoTim shows in this video, but for now, this setup works ok for me.

The two pi-hole instances configurations are synchronized using nebula-sync, so I only configure the instance on the Raspberry Pi and the other instance eventually gets those changes.

Virtualization

I’m using Incus to manage virtual machines and Linux containers. Every Linux-container or VM is exposed to the LAN as if it was a physical machine connected to the switch. So, when an incus VM or container starts, pihole will assign it an IP and a domain name based on the hostname.

To make incus machines appear in the network as if they were physical machines, I configured a bridge interface on the host machine with the main host physical interface as a child of that bridge. Then, in the default incus profile, I add to the guest machines an eth0 interface as a child of the host bridge like this:

...
devices:
  eth0:
    nictype: bridged
    parent: br0
    type: nic
...

I plan to publish a post in the future to explain this setup in detail, as it took me quite a while to get it working properly due to the amount of different network configurations incus supports.

On top of an incus container, most services run in docker-compose stacks as specified in the diagram above.

SSL

All the services running in my homelab receive a Let’s Encrypt SSL certificate, even though these services’ DNS names are not public (only visible in my LAN or VPN). I use NginxProxyManager to manage the certificates and as a reverse proxy for all the services.

VPN

For the VPN, I’m using WireGuard. I didn’t want to open any ports on my home router nor configure dynamic DNS to access it when I’m not at home, so this is the solution I’m using right now: I run wireguard in a VPS that has a public static ip. The Beelink server and my mobile phone (when it’s on 5g) connect directly to that VPS. When all of them are connected to the VPN they can see each other. The drawback of this setup is that all packets need to go through the VPS instead of talking directly to each other, which adds latency. It works ok for the use cases I use it for but I’d like to configure it as a proper mesh network where devices discover each other and find the best route. Similarly to what Tailscale provides, but in a DIY fashion. I’m curious to understand how the BGP protocol works so this might be a good learning opportunity to study it. This will also teach me something about UDP hole punching, STUN, ICE, and some of those cool protocols used in WebRTC and other P2P applications.

Other things that I’d like to improve (or play with) in the future.

What

IoT

Misc services

Multimedia

Development

Audio

Networking

Monitoring

Homelab Management

Virtualization and Containerization

Hardware