Table of contents

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:
- Beelink S12 (Intel N100 processor, 16GB RAM, and 512GB SSD)
- Raspberry pi 4B 4GB RAM
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.
- Expand Ansible automation: Right now, I’m configuring the CNAME DNS entries with an Ansible playbook.
After configuring the DNS entry, I need to manually add:
- The Nginx vhost for a service, with its SSL config
- A new Uptime Kuma to check if that service is up. So, I’d like to automate this with ansible as well.
- Storage: Configure a proper NAS. Improve the backup strategy (or have one, I should say :P). Play with a distributed filesystem like Ceph.
- Networking: Add a 10Gb managed switch (mainly for the NAS). Configure an appropriate VLAN architecture. Or, an Ubiquiti access point, so that I get more control of the traffic flow between every device or network, and faster WiFi.
- Try some intrusion detection and prevention system.
- High availability: Add a second physical node so that I can run services in HA and get more
RAM at the same time. Migrate some of those services to Kubernetes instead of plain docker-compose.
- One of the first services that I would like to run in High Availability is Home assistant. I’d need new zigbee controller, so that the zigbee network is working in HA as well, and if one of the nodes needs to be restarted, the switches, lights, etc continue working properly.
- VPN mesh network. As explained in the VPN setup, I’d like to learn how to configure my VPN setup as a proper mesh network.
What
IoT
Misc services
- Open WebUI - Frontend for Ollama
- Searxng - Search engine
- Miniflux - RSS reader
- N8n - For LLM automation. Still figuring out how to use it.
- Syncthing
Multimedia
Development
Audio
- Snapcast - The server facilitating multi-room audio system at home
- Librespot - To serve Spotify in every room