Inside My Home Lab - Hardware, Self-Hosted Services, and Architecture
3 May 2026 · 11 min read
I started my Home Lab to learn how server deployment actually worked, and to host a few custom Discord bots. It turned into something a lot bigger than that. The first setup was modest: a single Raspberry Pi running six to eight PM2 processes, and that tiny board handled everything I threw at it for over a year.
Home Labs rarely stay small, however. I kept adding layers, a NordVPN Meshnet node here, a Plex media stack there, and the limits of single-board computing started to show. The setup grew sluggish and services would drop out at random, which made it clear that if I wanted something resilient I was going to need real hardware.
[ Raspberry Pi 3B ] ---> [ Raspberry Pi 5 (8GB) ] ---> [ Beelink EQ14 ]
(Foundational Node) (Databases & APIs) (Primary Compute)
The Raspberry Pi 3B is where I started, back in 2023. It was tougher than I expected, hosting my early PM2 bots and a few simple websites for friends. It's retired from the stack now, but it's the board I learnt everything on, and it had a second act for a while as a dedicated VPN server for remote access.
The Raspberry Pi 5 (8GB) joined in December 2024, running Ubuntu Server, to take the heavier workloads off the 3B. By mid-2025 I'd moved my main development stack over to TypeScript and shifted applications into Docker containers, and the Pi 5 kept my local and production environments in sync. This is important because it allowed me to develop against the same runtime I was shipping to, rather than catching the differences after deploy. It now hosts my core Database instances, my custom Roblox API gateways, and a self-hosted Kanban tool, Plankaban.
In February 2026 I brought in the Beelink EQ14 as the primary compute engine. It runs an Intel N150 (4 cores, 4 threads) with 16GB of DDR4 and a 1TB NVMe SSD, which cleared up the compute and I/O bottlenecks I'd been fighting. I wiped the pre-installed Operating System and put Ubuntu Server on it, to keep everything lean for headless work.
The NVMe holds the OS, container images, and application data. A separate 1TB HDD hangs off the EQ14 for the bulk stuff, the Jellyfin media library and the Paperless-ngx document archive, which keeps the big files off the faster drive and leaves me room to grow.
That bulk data currently sits on a single drive with no local redundancy. This is a deliberate trade-off, due to the fact that the records in Paperless-ngx that actually matter are covered by off-site S3 backups. The plan is to move file storage onto a dedicated, rack-mounted NAS running RAID 10, so that I've got proper local redundancy and I'm not leaning entirely on off-site recovery.
The upgrade got me two things straight away:
Future networking plan: The EQ14 has dual Ethernet ports, and my next network iteration is to use them to segment the LAN, putting homelab services on their own VLAN next to a standalone physical security network.
With the EQ14 handling primary compute, I split the service architecture into layers: productivity, media, custom development, and system management.
+-----------------------------------------------------------------------+
| BEELINK EQ14 (Primary) |
| +--------------------+ +--------------------+ +-----------------+ |
| | Document & Wiki | | Media Stack | | Custom Tools | |
| | • Paperless-ngx | | • Jellyfin | | • Rehook | |
| | • Outline | | • Jellyseerr | | • Discord Bots | |
| | | | • Servarr Suite | | | |
| +--------------------+ +--------------------+ +-----------------+ |
+-----------------------------------------------------------------------+
|
v
+-----------------------------------------------------------------------+
| RASPBERRY PI 5 (Secondary) |
| +--------------------+ +--------------------+ +-----------------+ |
| | Project Tracking | | Integrations & DBs | | Management | |
| | • Plankaban | | • Roblox API GW | | • Portainer | |
| | | | • PostgreSQL/Redis | | • Cockpit | |
| +--------------------+ +--------------------+ +-----------------+ |
+-----------------------------------------------------------------------+
Paperless-ngx: My document digitisation pipeline, running on the EQ14 with dedicated postgres, redis, gotenberg, and tika containers behind it. It OCRs anything I upload, screenshots or PDFs, so that I can search the text later and generate temporary share links.
Outline: My knowledge base and runbook store, and where I dump ideas. It has its own isolated PostgreSQL and Redis pair, to ensure that its data stays separate from everything else running on the node.
Plankaban: A private Kanban board running in Docker on the Pi 5. It's the roadmap hub for my Roblox game projects and infrastructure milestones.
I ran Plex originally, but a few things pushed me off it. Features I wanted kept ending up behind a Plex Pass subscription, metadata and account auth ran through Plex's cloud, and it never stopped nudging me towards its own discovery and streaming products. Jellyfin is open-source, doesn't paywall hardware transcoding, and phones home to nobody. Once QuickSync was doing the heavy lifting, playback was as good as Plex had ever been, and the whole thing was mine.
Roblox API Gateway: A private gateway on the Pi 5 that bridges Roblox game servers to external data. It's what allows in-game features like custom player-voting to talk directly to outside databases and apps.
Rehook: Something I built to catch webhook payloads from services that only emit raw data, Outline Wiki for one, then process and tidy them up.
Discord Bots: Containerised TypeScript bots on the EQ14, Docket Bot and Commerce Service Desk among them, plus the legacy PM2 bots I'm phasing out on the Pi 5.
Portainer: Running on both boxes, Server and Agent across the EQ14 and Pi 5, as one visual console for container lifecycles and environment variables.
Cockpit: Also on both nodes, giving me a web terminal and host management, disk usage, updates, and live metrics, straight from a browser.
A dozen-plus containers across two nodes means image updates stack up fast. I still do all of it by hand. That's on purpose, but it's also the part of the stack most in need of automation.
A reliable home lab takes more than spinning up services. Access has to be locked down, health has to be visible, and the data that matters has to survive a dead drive.
+-------------------------------------------------------------------------+
| PUBLIC INTERNET |
+-------------------------------------------------------------------------+
| |
| (Zero-Trust Ingress) | (Off-Grid Status Page)
v v
+-----------------------+ +----------------------------------+
| Cloudflare Tunnels | | UptimeFlare (Cloudflare Pages) |
+-----------------------+ +----------------------------------+
| |
+--------------+ | (Monitors Health)
| v
v +----------------------------------+
+-----------------------+ | Local Home Lab |
| Local Web Services | | (EQ14 & Raspberry Pi Stack) |
+-----------------------+ +----------------------------------+
|
| (Nightly Incremental Sync)
v
+---------------------------------------------------------------+
| AWS S3 BACKUP PIPELINE |
| Standard (0-30 days) -> S3-IA (30-90 days) -> Glacier (90+) |
+---------------------------------------------------------------+
Rather than open router ports or wrangle port-forwarding tables, and put my public IP in front of every scanner on the internet, I route external traffic through Cloudflare Tunnels. The tunnel is an encrypted, outbound-only connection from my network to Cloudflare's edge, which is to ensure that I can reach Outline or Paperless-ngx from anywhere, whilst getting Cloudflare's DDoS protection for free and never exposing a port to the public internet.
cloudflared runs in Docker with one tunnel per application. Each tunnel points straight at its service over container:port on the internal Docker network, so that requests land on the right container and nothing is exposed on the host.
To watch availability without depending on the very hardware I'm watching, I run UptimeFlare on Cloudflare Pages.
A dozen-plus containers means a lot of sensitive config: API keys, database passwords, the .env files holding it all together. All of it lives in a KeePass Database, my single source of truth for credentials across my files and devices.
Right now that vault sits in a cloud store so that it stays synced across my devices. Convenient, yes, but trusting a third party with my most sensitive data is exactly the dependency this whole project exists to shed, so self-hosting the vault sync is on the roadmap.
Not losing data matters, particularly the digitised personal records in Paperless-ngx. To keep backups safe without paying for hot storage I never touch, I set up an AWS S3 lifecycle pipeline:
Building this stack out has been one of my favourite projects, and moving from one Raspberry Pi to an x86 box changed how I run everything. It also taught me a few things the hard way.
Finish the Docker migration: I've started pulling the legacy PM2 apps off the Pi 5 and moving them into containers, to get to full containerisation on both nodes.
Network-wide DNS with Pi-hole: I'm tempted to bring the retired 3B back as a Pi-hole box, for network-wide ad blocking and local DNS. A fitting job for the board that kicked all this off.
Network segmentation via dual NICs: Using the EQ14's two Ethernet ports is high on the list. I want core homelab apps on one subnet and physical security/IoT gear walled off on a separate, firewalled VLAN.
Automating service updates: Every container and host update is manual right now, which doesn't hold up across two nodes and a growing pile of services. Release notifications first, then reviewed automated rollouts, so that staying current stops eating my time.
More Infrastructure as Code: Pushing further on repeatable container rollouts and automated updates across both nodes, so that config changes stay documented and reproducible.
Dedicated NAS with RAID 10: Getting bulk storage off the EQ14's single HDD and onto a proper NAS in RAID 10, so that a dead drive isn't a call to my off-site S3 backups. It'll be rack-mounted as part of the rack build below.
Self-hosted secrets sync: Bringing the KeePass vault sync in-house, so that my most sensitive data stops depending on someone else's cloud. One of the last external dependencies left to cut.
An observability stack: Standing up Grafana and Prometheus to get past simple up/down checks. Real metrics would tell me how the network actually behaves, and the retired 3B could host it.
A proper rack and managed networking: Longer term, I want everything in a dedicated rack, probably 8U or 12U: the compute nodes, the new NAS, and managed gear like a UniFi gateway and switches. Partly for the tidier footprint, mostly for the excuse to go deeper on networking with hardware that can actually do it.
Cloudflare Tunnels
Zero-trust ingress docs for exposing local services without opening ports.
developers.cloudflare.comUptimeFlare
Open-source, Cloudflare Pages-based status monitor used for off-grid uptime tracking.
github.comPaperless-ngx
Documentation for the document digitisation and OCR pipeline.
docs.paperless-ngx.comOutline
Self-hosted knowledge base and wiki used for runbooks and notes.
docs.getoutline.comJellyfin
Free, self-hosted media server docs, including hardware acceleration setup.
jellyfin.orgCockpit
Browser-based Linux server management interface.
cockpit-project.org11 min read
Published on Sunday, 3 May 2026
Last Updated on Monday, 10 August 2026