homelab

Home lab

A personal infrastructure designed, deployed and documented end to end: resilient virtualisation, network security, encrypted remote access and versioned configurations.

Network architecture

Home lab network architectureInfrastructure diagram: double NAT, a two-node Proxmox cluster with a quorum witness, containerised services and remote access over a mesh VPN.InternetISP routerNAT 1 · public IPPersonal routerNAT 2 · DHCP · firewallSwitchLAN 192.168.1.0/24Proxmox VE cluster — 3 quorum votespve1Proxmox VE · x86_64Raspberry PiQDevice · 3rd votepve2Proxmox VE · x86_64corosyncVirtual machines and LXC / Docker containersPi-holeLXC · pve1CaddyLXC · pve1ZabbixLXC · pve1GiteaDocker · pve2FossFLOWDocker · pve2Bot DiscordDocker · pve2Laptop or phoneRemote accessTailscaleWireGuard meshTraverses both NAT layersno port forwardingPhysical hardwareVM / containerWired network pathEncrypted WireGuard tunnel
Home lab topology: a two-node Proxmox cluster backed by a quorum witness, containerised services, and remote access over a mesh VPN.
Text description of the diagram:
  1. The Internet connection terminates on the ISP router, which performs a first address translation (NAT 1) and holds the public IP address.
  2. The ISP router feeds a personal router, which performs a second address translation (NAT 2) and provides DHCP and firewalling for the internal network. This stacking is what constitutes double NAT.
  3. The router connects to a switch, which distributes the 192.168.1.0/24 local network.
  4. The switch serves three machines: two x86_64 Proxmox VE servers named pve1 and pve2, and a Raspberry Pi.
  5. The three machines form a Proxmox cluster with three quorum votes: pve1 and pve2 contribute one vote each, and the Raspberry Pi contributes the third as a Corosync QDevice. The Pi hosts no virtual machine.
  6. pve1 hosts the LXC containers Pi-hole (DNS and filtering), Caddy (reverse proxy) and Zabbix (monitoring).
  7. pve2 hosts the Docker containers Gitea (Git forge), FossFLOW (infrastructure diagrams) and the Discord bot.
  8. A remote laptop or phone connects through Tailscale, a WireGuard-based mesh VPN. The encrypted tunnel reaches the hosted services directly without traversing either NAT layer, removing any need for port forwarding.

Deployed services

Deployed services
ServiceRoleHostingStatus
Cluster Proxmox VEHigh-availability virtualisation foundationTwo x86_64 nodes + Raspberry PiIn production
Pi-holeLocal DNS and network-wide ad blockingLXC container on ProxmoxIn production
CaddyReverse proxy and HTTPS terminationDedicated LXC container on ProxmoxIn production
TailscaleMesh VPN for remote accessAgent on hosts and containersIn production
GiteaSelf-hosted Git forgeDocker containerIn production
FossFLOWVisual infrastructure documentationDocker containerIn production
Bot DiscordAutomation and notificationsDocker (compared against LXC, VM and bare metal)In production

Method applied to every project

Every component follows the same process, which keeps technical decisions traceable and makes each deployment reproducible.

  1. 01

    Context and objective

    Identify the real need — security, availability, productivity — before picking a tool. The tool follows from the need, never the other way round.

  2. 02

    Requirements analysis

    Size CPU, memory, storage and network, then choose the hosting environment (LXC, Docker, VM or bare metal) according to the expected load.

  3. 03

    Documented installation

    Write procedures as the deployment progresses — scripts, docker-compose, commands — so they can be reproduced identically.

  4. 04

    Configuration and hardening

    Systematically apply the same rules: static IP, firewall, strong passwords, two-factor authentication, HTTPS, least privilege.

  5. 05

    Verification and testing

    Prove resilience through explicit scenarios: node failure, service loss, DNS outage, remote access from outside.

  6. 06

    Documentation and archiving

    Record each project in a structured note — context, requirements, installation, configuration, good practices, troubleshooting, checklist — centralised in a single knowledge base.

  7. 07

    Ongoing maintenance

    Updates, monitoring, backups and improvements are recorded in the same note: the decision history stays alongside the procedure.

~/methode — principe

"Document while building": the technical write-up is produced during deployment, not afterwards. Once a service is stable, the note is archived and remains available as a reference.

Cluster Proxmox VE

Two x86_64 nodes + Raspberry Pi

Objective Achieve a stable three-vote quorum without buying a third full server: two x86_64 nodes (pve1, pve2) are complemented by a Raspberry Pi acting as a Corosync quorum witness. Without that third vote, shutting down a single node would be enough for the cluster to lose quorum.

Testing carried out

  • Deliberate node shutdown: verified that quorum holds and services fail over.
  • Loss of the QDevice alone: the cluster keeps two votes out of three and stays operational.
  • Combined scenario (node + QDevice): validated the expected behaviour when quorum is lost.

Good practices

  • Static IP addresses on all three machines.
  • Raspberry Pi wired over Ethernet rather than Wi-Fi: a quorum witness must not depend on wireless.
  • UPS protecting the cluster.
  • Monitoring through Zabbix.
  • Backup of /etc/pve/, which holds the entire cluster configuration.

Known limitations

  • The Raspberry Pi hosts no virtual machine: it is an arbiter, not a third node.
  • Planned evolution towards a genuine three-node cluster.

Technical stack

  • Proxmox VE
  • Corosync
  • corosync-qnetd
  • corosync-qdevice
  • Raspberry Pi

Pi-hole

LXC container on Proxmox

Objective Filter advertising and tracking at the network level rather than device by device. Pi-hole acts as a DNS sinkhole: every device on the network is protected without any local install, including those where nothing can be installed (TVs, IoT devices).

Hardening

  • Static IP address is mandatory: a DNS server that changes address takes the whole network down.
  • Firewall (UFW) restricted to the DNS and web administration ports only.
  • Administrator password changed at install time.
  • Log privacy level adjusted to the context (personal use versus GDPR compliance).

Good practices

  • LXC chosen over a full VM: near-instant boot and a 300–400 MB memory footprint.
  • Sizing from 512 MB (small network) up to 4 GB of RAM depending on DNS query volume.

Technical stack

  • Pi-hole
  • LXC
  • Debian
  • UFW
  • DNS

Caddy

Dedicated LXC container on Proxmox

Objective Reach internal services through readable domain names (fossflow.memel.lab) rather than IP-and-port pairs. Convenience is not the only benefit: a stable name survives a change of address or port on the underlying service.

Hardening

  • Local HTTPS through `tls internal`, or certificates via the Cloudflare DNS challenge.
  • No port exposed to the Internet: remote access goes through Tailscale, never through port forwarding.

Good practices

  • Strict separation of roles: one LXC for DNS (Pi-hole), one LXC for the proxy (Caddy).
  • Subdomains preferred over sub-paths: more readable, and avoids fragile URL rewriting.
  • Regular Caddyfile backups, logs followed through journalctl.

Technical stack

  • Caddy
  • LXC
  • HTTPS
  • Cloudflare DNS
  • Let’s Encrypt

Tailscale

Agent on hosts and containers

Objective Reach the whole home lab remotely even though the setup sits behind double NAT — the ISP router, then a personal router. In that configuration port forwarding is either impossible or must be requested from the ISP; a WireGuard-based mesh VPN sidesteps the issue by establishing connections from inside the network.

Hardening

  • Two-factor authentication enabled on the Tailscale account: that account is the key to the entire infrastructure.
  • Access control lists (ACLs) restricting which devices can reach which.

Good practices

  • MagicDNS: machines reachable by name rather than by address.
  • Subnet Router: the whole 192.168.1.0/24 network is reachable through a single entry point, without installing the agent everywhere.

Technical stack

  • Tailscale
  • WireGuard
  • MagicDNS
  • Subnet Router

Gitea

Docker container

Objective Retain control over the home lab code, scripts and technical documentation without depending on a third-party service. Written in Go, Gitea runs comfortably where GitLab would demand several gigabytes of memory.

Hardening

  • Public sign-up disabled: without it, an exposed instance fills up with automated accounts.
  • Two-factor authentication on the administrator account.
  • Regular backups of the data directory.

Good practices

  • Single container with an embedded SQLite database and persistent volumes.
  • Repositories organised by domain: homelab-configs, scripts-sysadmin, ad-setup, zabbix-templates, cours-bts.

Technical stack

  • Gitea
  • Docker
  • SQLite
  • Git

FossFLOW

Docker container

Objective Produce isometric diagrams of the network topology, the Proxmox cluster and the Active Directory architecture. An up-to-date diagram makes an infrastructure explainable to someone else — the precondition for genuine knowledge transfer.

Good practices

  • Diagrams stored as JSON on the server, backed up automatically.
  • Deliberate complementarity: FossFLOW for 3D isometric views, Excalidraw for quick 2D sketches.

Technical stack

  • FossFLOW
  • Docker
  • PWA
  • JSON

Bot Discord

Docker (compared against LXC, VM and bare metal)

Objective Automate notifications while serving as a testbed to concretely compare lightweight deployment environments: Docker, LXC, virtual machine and bare metal, each with its CPU, memory and storage sizing.

Hardening

  • Secrets (the bot token) isolated in a .env file, never committed.

Good practices

  • Modular Cog-based architecture: each feature is a module that can be reloaded independently.
  • Automatic restart through `--restart always` or a systemd unit.

Technical stack

  • Python
  • discord.py
  • Docker
  • systemd