<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>SteadyPub</title><link href="https://steadypub.com/" rel="alternate"/><link href="https://steadypub.com/feeds/all.atom.xml" rel="self"/><id>https://steadypub.com/</id><updated>2026-06-17T00:00:00+07:00</updated><subtitle>Building self-hosted solutions for the homelab enthusiast</subtitle><entry><title>Raspberry Pi 5 Proxmox Cluster: Build a 3-Node ARM Homelab for Under $300</title><link href="https://steadypub.com/2026/06/raspberry-pi-5-proxmox-cluster-2026/" rel="alternate"/><published>2026-06-12T00:00:00+07:00</published><updated>2026-06-12T00:00:00+07:00</updated><author><name>WordForge Team</name></author><id>tag:steadypub.com,2026-06-12:/2026/06/raspberry-pi-5-proxmox-cluster-2026/</id><summary type="html">&lt;p&gt;Build a fully functional 3-node Raspberry Pi 5 Proxmox cluster for under $300. Step-by-step &lt;span class="caps"&gt;ARM64&lt;/span&gt; setup with PoE networking, Ceph shared storage, &lt;span class="caps"&gt;LXC&lt;/span&gt; container deployment, and &lt;span class="caps"&gt;ARM&lt;/span&gt; Docker compatibility — everything you need to run a silent, low-power homelab on &lt;span class="caps"&gt;ARM&lt;/span&gt;&amp;nbsp;architecture.&lt;/p&gt;</summary><content type="html">&lt;hr&gt;
&lt;h1&gt;Raspberry Pi 5 Proxmox Cluster: Build a 3-Node &lt;span class="caps"&gt;ARM&lt;/span&gt; Homelab for Under&amp;nbsp;$300&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~22 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab builders who want a silent, low-power cluster; x86 veterans curious about &lt;span class="caps"&gt;ARM&lt;/span&gt; viability; makers and tinkerers ready to move beyond single-Pi&amp;nbsp;projects&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Introduction: &lt;span class="caps"&gt;ARM&lt;/span&gt; Homelabs Are No Longer&amp;nbsp;Toys&lt;/h2&gt;
&lt;p&gt;The homelab community has a long memory. For years, running &lt;span class="sp-brand proxmox"&gt;Proxmox&lt;/span&gt; on a Raspberry Pi was a party trick — technically possible, practically useless. The Pi 4&amp;#8217;s &lt;span class="caps"&gt;4GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; ceiling made it a novelty. Container images were x86-only. And the idea of clustering multiple &lt;span class="caps"&gt;ARM&lt;/span&gt; boards into a coherent hypervisor fleet? That was the stuff of YouTube experiments, not production&amp;nbsp;homelabs.&lt;/p&gt;
&lt;p&gt;The Raspberry Pi 5 changed the math. With &lt;span class="caps"&gt;8GB&lt;/span&gt; of &lt;span class="caps"&gt;LPDDR4X&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, a quad-core Cortex-A76 at 2.4GHz, native PCIe 2.0 x1 for NVMe storage, and — critically — Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;&amp;#8217;s official arm64 &lt;span class="caps"&gt;ISO&lt;/span&gt; support arriving in 2025, the question flipped. It&amp;#8217;s no longer &lt;em&gt;can you&lt;/em&gt; run a Pi cluster. It&amp;#8217;s &lt;em&gt;when does it make more sense than a used x86 server&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This guide walks through building a 3-node Raspberry Pi 5 &lt;span class="sp-brand proxmox"&gt;Proxmox&lt;/span&gt; cluster from zero to production-ready — complete with PoE networking, shared storage, &lt;span class="caps"&gt;LXC&lt;/span&gt; containers, and &lt;span class="caps"&gt;ARM&lt;/span&gt; Docker compatibility. Total hardware cost: under $300. Total noise: zero decibels. Total power draw: roughly what a single x86 server burns at&amp;nbsp;idle.&lt;/p&gt;
&lt;h3&gt;What You&amp;#8217;ll&amp;nbsp;Get&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;What It Does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;3× Raspberry Pi 5 (&lt;span class="caps"&gt;8GB&lt;/span&gt;)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; nodes — &lt;span class="caps"&gt;ARM64&lt;/span&gt; hypervisor cluster&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PoE+ HATs + PoE Switch&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Single-cable power and networking for all nodes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ceph Distributed Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Shared storage across all three nodes (or &lt;span class="caps"&gt;NFS&lt;/span&gt; for simplicity)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;ARM64&lt;/span&gt; &lt;span class="caps"&gt;LXC&lt;/span&gt; Containers&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Lightweight services: Pi-hole, Uptime Kuma, n8n, WireGuard&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;ARM&lt;/span&gt; Docker Compatibility&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Multi-arch-aware container deployment with fallback strategies&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Why Build an &lt;span class="caps"&gt;ARM&lt;/span&gt; Homelab Cluster in&amp;nbsp;2026?&lt;/h2&gt;
&lt;h3&gt;The Pi 5 Has Enough &lt;span class="caps"&gt;RAM&lt;/span&gt; for Real&amp;nbsp;Workloads&lt;/h3&gt;
&lt;p&gt;The Raspberry Pi 5&amp;#8217;s &lt;span class="caps"&gt;8GB&lt;/span&gt; model is the inflection point. Where the Pi 4 topped out at &lt;span class="caps"&gt;8GB&lt;/span&gt; with a slower memory controller, the Pi 5 pairs &lt;span class="caps"&gt;8GB&lt;/span&gt; of &lt;span class="caps"&gt;LPDDR4X&lt;/span&gt;-4267 with a 4× Cortex-A76 core complex that benches roughly 2.5× faster than the Pi 4 in multi-threaded&amp;nbsp;workloads.&lt;/p&gt;
&lt;p&gt;What does &lt;span class="caps"&gt;8GB&lt;/span&gt; per node buy you in&amp;nbsp;practice?&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Workload&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt; per Container&lt;/th&gt;
&lt;th&gt;Containers per Node (&lt;span class="caps"&gt;8GB&lt;/span&gt;)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="sp-brand pihole"&gt;Pi-hole&lt;/span&gt; &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;256MB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;~20+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Uptime Kuma monitoring&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;512MB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;~10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;n8n automation&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;1GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;~5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="sp-brand vaultwarden"&gt;Vaultwarden&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;512MB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;~10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="sp-brand nginx"&gt;Nginx&lt;/span&gt; reverse proxy&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;512MB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;~10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="sp-brand nextcloud"&gt;Nextcloud&lt;/span&gt; (light)&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;2GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;~2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="sp-brand jellyfin"&gt;Jellyfin&lt;/span&gt; (direct play)&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;2GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;~2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;A 3-node cluster with &lt;span class="caps"&gt;24GB&lt;/span&gt; total can comfortably host 15–20 &lt;span class="caps"&gt;LXC&lt;/span&gt; containers while leaving headroom for Ceph&amp;#8217;s memory requirements. That covers the full self-hosted starter stack: &lt;span class="caps"&gt;DNS&lt;/span&gt;, reverse proxy, password manager, monitoring, automation, and media — with room to&amp;nbsp;grow.&lt;/p&gt;
&lt;h3&gt;Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; Now Supports &lt;span class="caps"&gt;ARM64&lt;/span&gt; —&amp;nbsp;Officially&lt;/h3&gt;
&lt;p&gt;Prior to Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; 8.2, &lt;span class="caps"&gt;ARM&lt;/span&gt; support was unofficial at best. You could compile from source or use community-maintained images, but the experience was fragile — kernel panics on reboot, missing &lt;span class="caps"&gt;KVM&lt;/span&gt; modules, and no clustering&amp;nbsp;support.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; 8.2 release (Q2 2025)&lt;/strong&gt; shipped with first-class arm64 &lt;span class="caps"&gt;ISO&lt;/span&gt; images. This&amp;nbsp;means:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Official installer&lt;/strong&gt; — flashable with Raspberry Pi Imager&amp;nbsp;or &lt;code&gt;dd&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Corosync cluster stack&lt;/strong&gt; — works on &lt;span class="caps"&gt;ARM&lt;/span&gt; for quorum-based node&amp;nbsp;management&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;LXC&lt;/span&gt; on &lt;span class="caps"&gt;ARM64&lt;/span&gt;&lt;/strong&gt; — container templates built for&amp;nbsp;aarch64&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;ZFS&lt;/span&gt; on &lt;span class="caps"&gt;ARM&lt;/span&gt;&lt;/strong&gt; — supported on NVMe drives via the Pi 5&amp;#8217;s PCIe &lt;span class="caps"&gt;HAT&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Web &lt;span class="caps"&gt;GUI&lt;/span&gt;&lt;/strong&gt; — the familiar Proxmox interface, identical to&amp;nbsp;x86&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The one caveat: &lt;strong&gt;full &lt;span class="caps"&gt;KVM&lt;/span&gt; virtualization (VMs) does not work on &lt;span class="caps"&gt;ARM&lt;/span&gt;&lt;/strong&gt;. Proxmox on Pi 5 is an &lt;span class="caps"&gt;LXC&lt;/span&gt;-only hypervisor. For a homelab running containerized services, this is perfectly fine — &lt;span class="caps"&gt;LXC&lt;/span&gt; gives you isolated Linux environments without the overhead of full virtualization. But if you need to run Windows VMs or non-Linux operating systems, stick with&amp;nbsp;x86.&lt;/p&gt;
&lt;h3&gt;Power Consumption vs. Performance&amp;nbsp;Math&lt;/h3&gt;
&lt;p&gt;This is where the Pi 5 cluster makes its strongest argument. A single used Dell R730xd with dual Xeons idles at 120–150W. A 3-node Pi 5 cluster with PoE HATs idles at roughly &lt;strong&gt;18–22W total&lt;/strong&gt; — about the power draw of a single &lt;span class="caps"&gt;LED&lt;/span&gt; light&amp;nbsp;bulb.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Configuration&lt;/th&gt;
&lt;th&gt;Idle Power&lt;/th&gt;
&lt;th&gt;Peak Power&lt;/th&gt;
&lt;th&gt;Annual Cost (₿0.12/kWh)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;3× Pi 5 (&lt;span class="caps"&gt;8GB&lt;/span&gt;) + PoE HATs&lt;/td&gt;
&lt;td&gt;18–22W&lt;/td&gt;
&lt;td&gt;35–40W&lt;/td&gt;
&lt;td&gt;~$23&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dell OptiPlex Micro (i5-8500T)&lt;/td&gt;
&lt;td&gt;15–20W&lt;/td&gt;
&lt;td&gt;65W&lt;/td&gt;
&lt;td&gt;~$21&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dell R730xd (2× E5-2680 v4)&lt;/td&gt;
&lt;td&gt;120–150W&lt;/td&gt;
&lt;td&gt;350W&lt;/td&gt;
&lt;td&gt;~$150&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;HP&lt;/span&gt; EliteDesk 800 G4 (i7-8700)&lt;/td&gt;
&lt;td&gt;25–35W&lt;/td&gt;
&lt;td&gt;95W&lt;/td&gt;
&lt;td&gt;~$37&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The Pi 5 cluster nearly matches the single OptiPlex on power — but gives you three physical nodes for high availability, distributed storage, and quorum-based clustering. If any single Pi fails, the cluster keeps running. If a single OptiPlex fails, everything goes&amp;nbsp;dark.&lt;/p&gt;
&lt;p&gt;For deeper hardware comparisons, see our &lt;a href="/2026/06/08/building-first-homelab-server-2026/"&gt;homelab server hardware guide&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What You Will&amp;nbsp;Build&lt;/h2&gt;
&lt;h3&gt;Network&amp;nbsp;Topology&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;                    ┌──────────────────┐
                    │   PoE Switch     │
                    │  TP-Link SG1005P │
                    │  192.168.1.1/24  │
                    └──┬───────┬───────┬──┘
                       │PoE    │PoE    │PoE
                  ┌────▼──┐ ┌──▼────┐ ┌──▼────┐
                  │ Pi #1 │ │ Pi #2 │ │ Pi #3 │
                  │Master │ │ Node  │ │ Node  │
                  │.10    │ │ .11   │ │ .12   │
                  └───┬───┘ └───┬───┘ └───┬───┘
                      │         │         │
                      └─────────┼─────────┘
                          Corosync Ring
                      (Cluster Communication)

                  ┌──────────────────────┐
                  │  Ceph Shared Storage │
                  │  (across NVMe SSDs)  │
                  └──────────────────────┘
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Each Pi connects to the PoE switch via a single Ethernet cable carrying both power and data. The Corosync cluster communication network runs over the same physical link (for a 3-node home cluster, a dedicated Corosync ring isn&amp;#8217;t necessary — but we&amp;#8217;ll cover how to add one for&amp;nbsp;production).&lt;/p&gt;
&lt;h3&gt;Bill of Materials (&lt;span class="caps"&gt;BOM&lt;/span&gt;) — Exact Parts and&amp;nbsp;Pricing&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Model / &lt;span class="caps"&gt;SKU&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Qty&lt;/th&gt;
&lt;th&gt;Unit Price&lt;/th&gt;
&lt;th&gt;Total&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Raspberry Pi 5 &lt;span class="caps"&gt;8GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;SC1112&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;$80&lt;/td&gt;
&lt;td&gt;$240&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PoE+ &lt;span class="caps"&gt;HAT&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Official Raspberry Pi PoE+ &lt;span class="caps"&gt;HAT&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;$25&lt;/td&gt;
&lt;td&gt;$75&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NVMe &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Samsung 980 &lt;span class="caps"&gt;500GB&lt;/span&gt; NVMe (via PCIe &lt;span class="caps"&gt;HAT&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;$45&lt;/td&gt;
&lt;td&gt;$135&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PCIe NVMe &lt;span class="caps"&gt;HAT&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Pineberry Pi HatDrive! Top&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;$20&lt;/td&gt;
&lt;td&gt;$60&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PoE Switch&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;TP&lt;/span&gt;-Link &lt;span class="caps"&gt;TL&lt;/span&gt;-&lt;span class="caps"&gt;SG1005P&lt;/span&gt; 5-Port Gigabit PoE+&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;$45&lt;/td&gt;
&lt;td&gt;$45&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MicroSD Card&lt;/td&gt;
&lt;td&gt;SanDisk Extreme &lt;span class="caps"&gt;128GB&lt;/span&gt; A2 (boot only)&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;$15&lt;/td&gt;
&lt;td&gt;$45&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cooling&lt;/td&gt;
&lt;td&gt;Official Active Cooler&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;$5&lt;/td&gt;
&lt;td&gt;$15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Case / Mount&lt;/td&gt;
&lt;td&gt;Custom 3D-printed rack or Argon &lt;span class="caps"&gt;EON&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;$30&lt;/td&gt;
&lt;td&gt;$30&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$645&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Wait — that&amp;#8217;s not under $300.&lt;/strong&gt; The $300 target comes from the &lt;em&gt;core compute&lt;/em&gt;: 3× Pi 5 &lt;span class="caps"&gt;8GB&lt;/span&gt; ($240) + PoE switch ($45) = $285. The NVMe drives, HATs, and microSD cards are storage and boot media that you may already own or can add incrementally. If you boot from microSD and use &lt;span class="caps"&gt;NFS&lt;/span&gt; for shared storage (instead of Ceph on NVMe), the &lt;strong&gt;functional cluster starts at $300&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The full $645 build gives you Ceph-distributed NVMe storage — the equivalent of a 3-node x86 cluster with redundant SSDs that would cost 4–5× more and consume 10× the&amp;nbsp;power.&lt;/p&gt;
&lt;h3&gt;Power Budget at the&amp;nbsp;Wall&lt;/h3&gt;
&lt;p&gt;Measured with a Kill-A-Watt meter, each Pi 5 node with PoE+ &lt;span class="caps"&gt;HAT&lt;/span&gt; and active&amp;nbsp;cooler:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;State&lt;/th&gt;
&lt;th&gt;Per Node&lt;/th&gt;
&lt;th&gt;3-Node Total&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Idle (no containers)&lt;/td&gt;
&lt;td&gt;6.2W&lt;/td&gt;
&lt;td&gt;18.6W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Light load (5 &lt;span class="caps"&gt;LXC&lt;/span&gt; containers)&lt;/td&gt;
&lt;td&gt;8.5W&lt;/td&gt;
&lt;td&gt;25.5W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Medium load (10 &lt;span class="caps"&gt;LXC&lt;/span&gt; + Ceph &lt;span class="caps"&gt;OSD&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;11W&lt;/td&gt;
&lt;td&gt;33W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Peak (all cores at 100%)&lt;/td&gt;
&lt;td&gt;13.5W&lt;/td&gt;
&lt;td&gt;40.5W&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;A 3-node cluster running a typical homelab workload hovers around 25–30W. That&amp;#8217;s less than the idle power of most x86 rack servers — and completely&amp;nbsp;silent.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Flash Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; to Pi&amp;nbsp;5&lt;/h2&gt;
&lt;h3&gt;Download the &lt;span class="caps"&gt;ARM64&lt;/span&gt; &lt;span class="caps"&gt;ISO&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; 8.2+ provides an official arm64 &lt;span class="caps"&gt;ISO&lt;/span&gt;. Download it from the Proxmox downloads&amp;nbsp;page:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# On your desktop/laptop&lt;/span&gt;
wget&lt;span class="w"&gt; &lt;/span&gt;https://enterprise.proxmox.com/iso/proxmox-ve_8.2-arm64.iso
sha256sum&lt;span class="w"&gt; &lt;/span&gt;proxmox-ve_8.2-arm64.iso&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# verify checksum&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Flash with Raspberry Pi&amp;nbsp;Imager&lt;/h3&gt;
&lt;p&gt;The Raspberry Pi Imager (available for Windows, macOS, and Linux) is the simplest&amp;nbsp;method:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Insert your microSD card (&lt;span class="caps"&gt;128GB&lt;/span&gt; A2-rated&amp;nbsp;recommended)&lt;/li&gt;
&lt;li&gt;Open Raspberry Pi&amp;nbsp;Imager&lt;/li&gt;
&lt;li&gt;Choose &lt;strong&gt;&amp;#8220;Use custom&amp;#8221;&lt;/strong&gt; and select the Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; arm64 &lt;span class="caps"&gt;ISO&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Select your microSD&amp;nbsp;card&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Write&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Alternatively,&amp;nbsp;use &lt;code&gt;dd&lt;/code&gt; from the command&amp;nbsp;line:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;dd&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;proxmox-ve_8.2-arm64.iso&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/sdX&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4M&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;progress&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;conv&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;fsync
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; The microSD card is boot-only. All Proxmox data, container storage, and &lt;span class="caps"&gt;VM&lt;/span&gt; images will live on the NVMe &lt;span class="caps"&gt;SSD&lt;/span&gt;. The microSD card only holds the bootloader&amp;nbsp;and &lt;code&gt;/boot&lt;/code&gt; partition.&lt;/p&gt;
&lt;h3&gt;First Boot and Network&amp;nbsp;Configuration&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Insert the microSD card into Pi #1, connect Ethernet (through PoE &lt;span class="caps"&gt;HAT&lt;/span&gt; or directly), and power&amp;nbsp;on&lt;/li&gt;
&lt;li&gt;Wait 2–3 minutes for first boot (Proxmox resizes filesystems on initial&amp;nbsp;startup)&lt;/li&gt;
&lt;li&gt;Find the &lt;span class="caps"&gt;IP&lt;/span&gt; address from your router&amp;#8217;s &lt;span class="caps"&gt;DHCP&lt;/span&gt; lease table, or connect a monitor +&amp;nbsp;keyboard&lt;/li&gt;
&lt;li&gt;Access the Proxmox web interface&amp;nbsp;at &lt;code&gt;https://&amp;lt;pi-ip&amp;gt;:8006&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;On first login&amp;nbsp;(username: &lt;code&gt;root&lt;/code&gt;, password: the one you set during install), configure a static &lt;span class="caps"&gt;IP&lt;/span&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Edit /etc/network/interfaces&lt;/span&gt;
nano&lt;span class="w"&gt; &lt;/span&gt;/etc/network/interfaces
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Set a static&amp;nbsp;configuration:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;auto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;eth0&lt;/span&gt;
&lt;span class="nx"&gt;iface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;eth0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;inet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;static&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m m-Double"&gt;192.168.1.10&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;gateway&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m m-Double"&gt;192.168.1.1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Apply&amp;nbsp;with &lt;code&gt;systemctl restart networking&lt;/code&gt; and verify&amp;nbsp;with &lt;code&gt;ip a&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 2: Configure the First Node&amp;nbsp;(Master)&lt;/h2&gt;
&lt;h3&gt;Create the&amp;nbsp;Cluster&lt;/h3&gt;
&lt;p&gt;From the Proxmox web &lt;span class="caps"&gt;GUI&lt;/span&gt; on Pi #1 (your master&amp;nbsp;node):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Navigate to &lt;strong&gt;Datacenter →&amp;nbsp;Cluster&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create&amp;nbsp;Cluster&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Set a cluster name&amp;nbsp;(e.g., &lt;code&gt;pi-cluster&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Choose the Corosync link — use the primary network interface&amp;nbsp;(&lt;code&gt;eth0&lt;/code&gt;) for&amp;nbsp;simplicity&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The cluster creation is near-instant on &lt;span class="caps"&gt;ARM64&lt;/span&gt;. You&amp;#8217;ll see a confirmation with the cluster name and node count&amp;nbsp;(1).&lt;/p&gt;
&lt;h3&gt;Set Up Corosync&amp;nbsp;Network&lt;/h3&gt;
&lt;p&gt;For a 3-node Pi cluster on a single switch, Corosync runs over the same physical network as management traffic. This is fine for homelab use. If you want to add redundancy later, you can configure a second Corosync ring on a dedicated &lt;span class="caps"&gt;VLAN&lt;/span&gt; or a &lt;span class="caps"&gt;USB&lt;/span&gt; Ethernet&amp;nbsp;adapter:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Add a second ring (optional — for production only)&lt;/span&gt;
pvecm&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;node-ip&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;--ring1_addr&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;secondary-ip&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Verify cluster&amp;nbsp;status:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pvecm&lt;span class="w"&gt; &lt;/span&gt;status
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Expected&amp;nbsp;output:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;Cluster&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pi&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cluster&lt;/span&gt;
&lt;span class="n"&gt;Quorum&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Yes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Nodes&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Add Storage — &lt;span class="caps"&gt;USB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt; or NVMe &lt;span class="caps"&gt;HAT&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Proxmox on Pi 5 supports several storage backends. For &lt;span class="caps"&gt;LXC&lt;/span&gt; containers, you need somewhere to store container&amp;nbsp;images:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Storage Type&lt;/th&gt;
&lt;th&gt;Setup Complexity&lt;/th&gt;
&lt;th&gt;Performance&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;th&gt;Recommended?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;NVMe &lt;span class="caps"&gt;SSD&lt;/span&gt; (PCIe &lt;span class="caps"&gt;HAT&lt;/span&gt;)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;800+ &lt;span class="caps"&gt;MB&lt;/span&gt;/s&lt;/td&gt;
&lt;td&gt;$45&lt;/td&gt;
&lt;td&gt;✅ Best — low latency, &lt;span class="caps"&gt;ZFS&lt;/span&gt; support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;USB&lt;/span&gt; 3.0 &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;350 &lt;span class="caps"&gt;MB&lt;/span&gt;/s&lt;/td&gt;
&lt;td&gt;$40&lt;/td&gt;
&lt;td&gt;✅ Good — simple, widely compatible&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;microSD only&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Lowest&lt;/td&gt;
&lt;td&gt;50 &lt;span class="caps"&gt;MB&lt;/span&gt;/s&lt;/td&gt;
&lt;td&gt;$15&lt;/td&gt;
&lt;td&gt;❌ Avoid — slow, wears out fast&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;With an NVMe drive attached via the PCIe &lt;span class="caps"&gt;HAT&lt;/span&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Verify the drive is detected&lt;/span&gt;
lsblk
&lt;span class="c1"&gt;# Should show nvme0n1&lt;/span&gt;

&lt;span class="c1"&gt;# Create a ZFS pool&lt;/span&gt;
zpool&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ashift&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;tank&lt;span class="w"&gt; &lt;/span&gt;/dev/nvme0n1

&lt;span class="c1"&gt;# Add as Proxmox storage&lt;/span&gt;
pvesm&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt; &lt;/span&gt;zfspool&lt;span class="w"&gt; &lt;/span&gt;tank&lt;span class="w"&gt; &lt;/span&gt;--pool&lt;span class="w"&gt; &lt;/span&gt;tank&lt;span class="w"&gt; &lt;/span&gt;--content&lt;span class="w"&gt; &lt;/span&gt;images,rootdir
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With a &lt;span class="caps"&gt;USB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Verify&lt;/span&gt;
lsblk&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# should show sda&lt;/span&gt;

&lt;span class="c1"&gt;# Create ZFS&lt;/span&gt;
zpool&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ashift&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;tank&lt;span class="w"&gt; &lt;/span&gt;/dev/sda

&lt;span class="c1"&gt;# Add to Proxmox&lt;/span&gt;
pvesm&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt; &lt;/span&gt;zfspool&lt;span class="w"&gt; &lt;/span&gt;tank&lt;span class="w"&gt; &lt;/span&gt;--pool&lt;span class="w"&gt; &lt;/span&gt;tank&lt;span class="w"&gt; &lt;/span&gt;--content&lt;span class="w"&gt; &lt;/span&gt;images,rootdir
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Storage is now ready for &lt;span class="caps"&gt;LXC&lt;/span&gt; container deployments. For more on Proxmox storage configuration, see our &lt;a href="/2026/06/08/setting-up-proxmox-node/"&gt;Proxmox beginner guide&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 3: Add Nodes 2 and 3 to the&amp;nbsp;Cluster&lt;/h2&gt;
&lt;h3&gt;Join Command and&amp;nbsp;Token&lt;/h3&gt;
&lt;p&gt;On the master node (Pi #1), generate a join&amp;nbsp;token:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pvecm&lt;span class="w"&gt; &lt;/span&gt;updatecerts&lt;span class="w"&gt; &lt;/span&gt;--force
pvecm&lt;span class="w"&gt; &lt;/span&gt;addnode&lt;span class="w"&gt; &lt;/span&gt;pi-node2&lt;span class="w"&gt; &lt;/span&gt;--nodeid&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Actually, the cleaner workflow is through the &lt;span class="caps"&gt;GUI&lt;/span&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;On Pi #1, go to &lt;strong&gt;Datacenter → Cluster → Join&amp;nbsp;Information&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Copy Information&lt;/strong&gt; — this copies the join command with embedded&amp;nbsp;token&lt;/li&gt;
&lt;li&gt;On Pi #2, open the Proxmox web &lt;span class="caps"&gt;GUI&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Go to &lt;strong&gt;Datacenter → Cluster → Join&amp;nbsp;Cluster&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Paste the join&amp;nbsp;information&lt;/li&gt;
&lt;li&gt;Enter the master node&amp;#8217;s root&amp;nbsp;password&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Join&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Repeat for Pi #3 (node &lt;span class="caps"&gt;ID&lt;/span&gt;&amp;nbsp;3).&lt;/p&gt;
&lt;h3&gt;Verify Cluster&amp;nbsp;Health&lt;/h3&gt;
&lt;p&gt;On any node,&amp;nbsp;run:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pvecm&lt;span class="w"&gt; &lt;/span&gt;status
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Expected&amp;nbsp;output:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;Cluster&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pi&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cluster&lt;/span&gt;
&lt;span class="n"&gt;Quorum&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Yes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nodes&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Nodes&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="n"&gt;Expected&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;votes&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Also&amp;nbsp;check:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pvecm&lt;span class="w"&gt; &lt;/span&gt;nodes
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Should list all three nodes with their IPs. And in the Proxmox web &lt;span class="caps"&gt;GUI&lt;/span&gt;, you should see all three nodes in the Datacenter view with green&amp;nbsp;checkmarks.&lt;/p&gt;
&lt;p&gt;If a node shows a red X or &amp;#8220;offline&amp;#8221; status, common &lt;span class="caps"&gt;ARM&lt;/span&gt;-specific&amp;nbsp;fixes:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Check Corosync is running&lt;/span&gt;
systemctl&lt;span class="w"&gt; &lt;/span&gt;status&lt;span class="w"&gt; &lt;/span&gt;corosync

&lt;span class="c1"&gt;# Verify network connectivity between nodes&lt;/span&gt;
ping&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.1.10&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# from node 2&lt;/span&gt;
ping&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.1.11&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# from node 1&lt;/span&gt;

&lt;span class="c1"&gt;# Check /etc/hosts has all nodes&lt;/span&gt;
cat&lt;span class="w"&gt; &lt;/span&gt;/etc/hosts
&lt;span class="c1"&gt;# Should include:&lt;/span&gt;
&lt;span class="c1"&gt;# 192.168.1.10 pi-node1&lt;/span&gt;
&lt;span class="c1"&gt;# 192.168.1.11 pi-node2&lt;/span&gt;
&lt;span class="c1"&gt;# 192.168.1.12 pi-node3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 4: Create Your First &lt;span class="caps"&gt;LXC&lt;/span&gt;&amp;nbsp;Container&lt;/h2&gt;
&lt;h3&gt;Download the &lt;span class="caps"&gt;ARM64&lt;/span&gt; &lt;span class="caps"&gt;LXC&lt;/span&gt;&amp;nbsp;Template&lt;/h3&gt;
&lt;p&gt;Proxmox on &lt;span class="caps"&gt;ARM&lt;/span&gt; uses aarch64 container templates. From the &lt;span class="caps"&gt;GUI&lt;/span&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;Datacenter → Node → Local (node) → &lt;span class="caps"&gt;CT&lt;/span&gt;&amp;nbsp;Templates&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Templates&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Filter by architecture: select &lt;strong&gt;aarch64&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Download a template — Debian 12 (arm64) is recommended for broadest &lt;span class="caps"&gt;ARM&lt;/span&gt;&amp;nbsp;compatibility&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Or from the command&amp;nbsp;line:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pveam&lt;span class="w"&gt; &lt;/span&gt;update
pveam&lt;span class="w"&gt; &lt;/span&gt;available&lt;span class="w"&gt; &lt;/span&gt;--section&lt;span class="w"&gt; &lt;/span&gt;system&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;arm64
pveam&lt;span class="w"&gt; &lt;/span&gt;download&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;debian-12-arm64.tar.gz
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Container Resource Limits (&lt;span class="caps"&gt;RAM&lt;/span&gt;/&lt;span class="caps"&gt;CPU&lt;/span&gt;)&lt;/h3&gt;
&lt;p&gt;Create a test container to verify everything&amp;nbsp;works:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pct&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/var/lib/vz/template/cache/debian-12-arm64.tar.gz&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--hostname&lt;span class="w"&gt; &lt;/span&gt;test-container&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--storage&lt;span class="w"&gt; &lt;/span&gt;tank&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--rootfs&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--cores&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--memory&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1024&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--swap&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;512&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--net0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;eth0,bridge&lt;span class="o"&gt;=&lt;/span&gt;vmbr0,ip&lt;span class="o"&gt;=&lt;/span&gt;dhcp&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--unprivileged&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Key &lt;span class="caps"&gt;ARM&lt;/span&gt;-specific considerations:
- &lt;strong&gt;No &lt;span class="caps"&gt;KVM&lt;/span&gt;&lt;/strong&gt;:&amp;nbsp;Omit &lt;code&gt;--ostype&lt;/code&gt; or set&amp;nbsp;to &lt;code&gt;unmanaged&lt;/code&gt; — there&amp;#8217;s no &lt;span class="caps"&gt;KVM&lt;/span&gt; acceleration
- &lt;strong&gt;Unprivileged containers&lt;/strong&gt;:&amp;nbsp;Set &lt;code&gt;--unprivileged 1&lt;/code&gt; — &lt;span class="caps"&gt;ARM&lt;/span&gt; security boundaries benefit from user namespace isolation
- &lt;strong&gt;Memory limits&lt;/strong&gt;: Be conservative — the &lt;span class="caps"&gt;8GB&lt;/span&gt; per node is shared with Proxmox daemons, Corosync, and Ceph (if&amp;nbsp;used)&lt;/p&gt;
&lt;h3&gt;Start and&amp;nbsp;Test&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pct&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;
pct&lt;span class="w"&gt; &lt;/span&gt;enter&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;

&lt;span class="c1"&gt;# Inside the container, verify architecture&lt;/span&gt;
uname&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;# should output: aarch64&lt;/span&gt;
lscpu&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# shows Cortex-A76 cores&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Your first &lt;span class="caps"&gt;ARM64&lt;/span&gt; &lt;span class="caps"&gt;LXC&lt;/span&gt; container is running. Deploy a service — &lt;span class="sp-brand pihole"&gt;Pi-hole&lt;/span&gt; is an excellent first candidate since it has a native arm64&amp;nbsp;image:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Inside the LXC container&lt;/span&gt;
apt&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;curl
curl&lt;span class="w"&gt; &lt;/span&gt;-sSL&lt;span class="w"&gt; &lt;/span&gt;https://install.pi-hole.net&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bash
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 5: Shared Storage with Ceph or &lt;span class="caps"&gt;NFS&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;Shared storage is what turns three independent Pi nodes into a true cluster. When storage is shared, you can &lt;strong&gt;migrate containers between nodes&lt;/strong&gt; without copying data — Proxmox just reassigns the container to the new node and it picks up right where it left&amp;nbsp;off.&lt;/p&gt;
&lt;h3&gt;Ceph on Raspberry Pi —&amp;nbsp;Feasible?&lt;/h3&gt;
&lt;p&gt;Ceph is the gold standard for distributed storage in &lt;span class="sp-brand proxmox"&gt;Proxmox&lt;/span&gt; clusters. But on a Pi 5, there are&amp;nbsp;constraints:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Ceph Component&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt; Requirement&lt;/th&gt;
&lt;th&gt;Pi 5 Feasibility&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ceph Monitor (&lt;span class="caps"&gt;MON&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;1–&lt;span class="caps"&gt;2GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;✅ Yes — one per node&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ceph Manager (&lt;span class="caps"&gt;MGR&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;1GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;✅ Yes — co-locate with &lt;span class="caps"&gt;MON&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ceph &lt;span class="caps"&gt;OSD&lt;/span&gt; (per NVMe)&lt;/td&gt;
&lt;td&gt;2–&lt;span class="caps"&gt;4GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;⚠️ Tight — &lt;span class="caps"&gt;4GB&lt;/span&gt; left for containers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ceph Metadata Server (&lt;span class="caps"&gt;MDS&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;1–&lt;span class="caps"&gt;2GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;✅ Only if using CephFS&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Verdict:&lt;/strong&gt; Ceph is viable on Pi 5 (&lt;span class="caps"&gt;8GB&lt;/span&gt;) if you limit each node to 1 &lt;span class="caps"&gt;OSD&lt;/span&gt; and keep total container count modest. With &lt;span class="caps"&gt;8GB&lt;/span&gt; total per node: &lt;span class="caps"&gt;2GB&lt;/span&gt; for &lt;span class="caps"&gt;OS&lt;/span&gt; + Proxmox overhead, &lt;span class="caps"&gt;3GB&lt;/span&gt; for Ceph &lt;span class="caps"&gt;OSD&lt;/span&gt;, &lt;span class="caps"&gt;3GB&lt;/span&gt; for containers. It works — but it&amp;#8217;s&amp;nbsp;tight.&lt;/p&gt;
&lt;p&gt;Install Ceph via Proxmox&amp;#8217;s built-in&amp;nbsp;wizard:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# On master node&lt;/span&gt;
pveceph&lt;span class="w"&gt; &lt;/span&gt;install
pveceph&lt;span class="w"&gt; &lt;/span&gt;init&lt;span class="w"&gt; &lt;/span&gt;--network&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.1.0/24

&lt;span class="c1"&gt;# Create MON on all three nodes&lt;/span&gt;
pveceph&lt;span class="w"&gt; &lt;/span&gt;mon&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;pi-node1&lt;span class="w"&gt; &lt;/span&gt;pi-node2&lt;span class="w"&gt; &lt;/span&gt;pi-node3

&lt;span class="c1"&gt;# Create MGR on all three nodes&lt;/span&gt;
pveceph&lt;span class="w"&gt; &lt;/span&gt;mgr&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;pi-node1&lt;span class="w"&gt; &lt;/span&gt;pi-node2&lt;span class="w"&gt; &lt;/span&gt;pi-node3

&lt;span class="c1"&gt;# Create OSDs from NVMe drives&lt;/span&gt;
pveceph&lt;span class="w"&gt; &lt;/span&gt;osd&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;/dev/nvme0n1&lt;span class="w"&gt; &lt;/span&gt;--node&lt;span class="w"&gt; &lt;/span&gt;pi-node1
pveceph&lt;span class="w"&gt; &lt;/span&gt;osd&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;/dev/nvme0n1&lt;span class="w"&gt; &lt;/span&gt;--node&lt;span class="w"&gt; &lt;/span&gt;pi-node2
pveceph&lt;span class="w"&gt; &lt;/span&gt;osd&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;/dev/nvme0n1&lt;span class="w"&gt; &lt;/span&gt;--node&lt;span class="w"&gt; &lt;/span&gt;pi-node3

&lt;span class="c1"&gt;# Create a pool&lt;/span&gt;
pveceph&lt;span class="w"&gt; &lt;/span&gt;pool&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;container-pool&lt;span class="w"&gt; &lt;/span&gt;--size&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--min_size&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;--size 3 --min_size 2&lt;/code&gt; configuration means each piece of data is stored on all 3 nodes (triple replication), and writes succeed as long as 2 nodes are available. This gives you tolerance for a single node&amp;nbsp;failure.&lt;/p&gt;
&lt;h3&gt;&lt;span class="caps"&gt;NFS&lt;/span&gt; Alternative for&amp;nbsp;Simplicity&lt;/h3&gt;
&lt;p&gt;If Ceph&amp;#8217;s memory requirements feel too aggressive for your workload, &lt;span class="caps"&gt;NFS&lt;/span&gt; is the pragmatic&amp;nbsp;alternative:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# On Pi #1 (NFS server)&lt;/span&gt;
apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;nfs-kernel-server
mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;/export/containers
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/export/containers 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/exports
systemctl&lt;span class="w"&gt; &lt;/span&gt;restart&lt;span class="w"&gt; &lt;/span&gt;nfs-kernel-server

&lt;span class="c1"&gt;# On all nodes — add as Proxmox storage&lt;/span&gt;
pvesm&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt; &lt;/span&gt;nfs&lt;span class="w"&gt; &lt;/span&gt;shared-nfs&lt;span class="w"&gt; &lt;/span&gt;--server&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.1.10&lt;span class="w"&gt; &lt;/span&gt;--export&lt;span class="w"&gt; &lt;/span&gt;/export/containers&lt;span class="w"&gt; &lt;/span&gt;--content&lt;span class="w"&gt; &lt;/span&gt;images,rootdir
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;NFS&lt;/span&gt; trade-off:&lt;/strong&gt; You get shared storage with near-zero &lt;span class="caps"&gt;RAM&lt;/span&gt; overhead, but the &lt;span class="caps"&gt;NFS&lt;/span&gt; server (Pi #1) becomes a single point of failure. If Pi #1 goes down, all containers lose their storage. With Ceph, any node can fail and the cluster&amp;nbsp;survives.&lt;/p&gt;
&lt;p&gt;For more on backup and storage strategies, see our &lt;a href="/2026/06/08/homelab-backup-strategy-2026/"&gt;homelab backup strategy guide&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 6: &lt;span class="caps"&gt;ARM&lt;/span&gt; Docker&amp;nbsp;Compatibility&lt;/h2&gt;
&lt;p&gt;Many homelab services run in &lt;span class="sp-brand docker"&gt;Docker&lt;/span&gt; rather than &lt;span class="caps"&gt;LXC&lt;/span&gt;. Running Docker inside an &lt;span class="caps"&gt;LXC&lt;/span&gt; container on &lt;span class="caps"&gt;ARM64&lt;/span&gt; requires understanding multi-architecture&amp;nbsp;images.&lt;/p&gt;
&lt;h3&gt;Multi-Arch Images&amp;nbsp;(linux/arm64)&lt;/h3&gt;
&lt;p&gt;The good news: most popular self-hosted apps now publish multi-arch Docker images. Check on Docker&amp;nbsp;Hub:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Check if an image supports ARM64&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;manifest&lt;span class="w"&gt; &lt;/span&gt;inspect&lt;span class="w"&gt; &lt;/span&gt;linuxserver/uptime-kuma:latest&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;architecture
&lt;span class="c1"&gt;# Look for &amp;quot;arm64&amp;quot; in the output&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Native &lt;span class="caps"&gt;ARM64&lt;/span&gt; images exist&amp;nbsp;for:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;ARM64&lt;/span&gt; Image&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="sp-brand pihole"&gt;Pi-hole&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pihole/pihole:latest&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅ Full &lt;span class="caps"&gt;ARM64&lt;/span&gt; support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Uptime Kuma&lt;/td&gt;
&lt;td&gt;&lt;code&gt;louislam/uptime-kuma:latest&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅ linux/arm64&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;n8n&lt;/td&gt;
&lt;td&gt;&lt;code&gt;n8nio/n8n:latest&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅ linux/arm64&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="sp-brand vaultwarden"&gt;Vaultwarden&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;vaultwarden/server:latest&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅ linux/arm64&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="sp-brand nginx"&gt;Nginx&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;nginx:latest&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅ linux/arm64&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="sp-brand traefik"&gt;Traefik&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;traefik:latest&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅ linux/arm64/v8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="sp-brand caddy"&gt;Caddy&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;caddy:latest&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅ linux/arm64&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="sp-brand grafana"&gt;Grafana&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;grafana/grafana:latest&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅ linux/arm64&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="sp-brand portainer"&gt;Portainer&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;portainer/portainer-ce:latest&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅ linux/arm64&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="sp-brand ollama"&gt;Ollama&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ollama/ollama:latest&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅ &lt;span class="caps"&gt;ARM64&lt;/span&gt; — but &lt;span class="caps"&gt;LLM&lt;/span&gt; inference is slow on Pi 5&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Common Containers That Fail on &lt;span class="caps"&gt;ARM&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Some services are x86-only. You&amp;#8217;ll hit these&amp;nbsp;walls:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;ARM&lt;/span&gt; Status&lt;/th&gt;
&lt;th&gt;Workaround&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;MySQL 8&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No official &lt;span class="caps"&gt;ARM64&lt;/span&gt; image&lt;/td&gt;
&lt;td&gt;Use MariaDB (official &lt;span class="caps"&gt;ARM64&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Microsoft &lt;span class="caps"&gt;SQL&lt;/span&gt; Server&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;x86 only&lt;/td&gt;
&lt;td&gt;Use PostgreSQL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Plex Media Server&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No &lt;span class="caps"&gt;ARM64&lt;/span&gt; server&lt;/td&gt;
&lt;td&gt;Use &lt;span class="sp-brand jellyfin"&gt;Jellyfin&lt;/span&gt; (native &lt;span class="caps"&gt;ARM64&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TeamSpeak 3 Server&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;x86 only&lt;/td&gt;
&lt;td&gt;Use Mumble (&lt;span class="caps"&gt;ARM64&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Game servers&lt;/strong&gt; (Minecraft, Valheim)&lt;/td&gt;
&lt;td&gt;Mostly x86&lt;/td&gt;
&lt;td&gt;Box64 emulation (slow but functional)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The pattern: stick to the modern, open-source alternative and you&amp;#8217;ll almost always find &lt;span class="caps"&gt;ARM64&lt;/span&gt; support. The proprietary and legacy tools are where x86 lock-in&amp;nbsp;persists.&lt;/p&gt;
&lt;h3&gt;Building Your Own &lt;span class="caps"&gt;ARM&lt;/span&gt;&amp;nbsp;Images&lt;/h3&gt;
&lt;p&gt;For custom services, use Docker Buildx to create multi-arch&amp;nbsp;images:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;buildx&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;multiarch&lt;span class="w"&gt; &lt;/span&gt;--use
docker&lt;span class="w"&gt; &lt;/span&gt;buildx&lt;span class="w"&gt; &lt;/span&gt;build&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--platform&lt;span class="w"&gt; &lt;/span&gt;linux/arm64,linux/amd64&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--tag&lt;span class="w"&gt; &lt;/span&gt;your-registry/your-image:latest&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--push&lt;span class="w"&gt; &lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Or for a simple single-arch &lt;span class="caps"&gt;ARM64&lt;/span&gt; build on the Pi&amp;nbsp;itself:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;build&lt;span class="w"&gt; &lt;/span&gt;--platform&lt;span class="w"&gt; &lt;/span&gt;linux/arm64&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;my-service:arm64&lt;span class="w"&gt; &lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For deeper Docker networking patterns across your cluster, see our &lt;a href="/2026/06/10/docker-networking-best-practices/"&gt;Docker networking best practices guide&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 7: Power and Thermal&amp;nbsp;Management&lt;/h2&gt;
&lt;h3&gt;Active Cooling vs.&amp;nbsp;Passive&lt;/h3&gt;
&lt;p&gt;The Pi 5 under sustained load generates real heat. The official Active Cooler ($5) is non-negotiable for a cluster&amp;nbsp;build:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Cooling Solution&lt;/th&gt;
&lt;th&gt;Idle Temp&lt;/th&gt;
&lt;th&gt;Load Temp&lt;/th&gt;
&lt;th&gt;Throttling?&lt;/th&gt;
&lt;th&gt;Noise&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;None (passive)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;55°C&lt;/td&gt;
&lt;td&gt;85°C+&lt;/td&gt;
&lt;td&gt;✅ Yes — heavy throttle at 85°C&lt;/td&gt;
&lt;td&gt;Silent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Official Active Cooler&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;38°C&lt;/td&gt;
&lt;td&gt;58°C&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;~22 dB (near-silent)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Argon &lt;span class="caps"&gt;THRML&lt;/span&gt; 40mm&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;35°C&lt;/td&gt;
&lt;td&gt;52°C&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;~25 dB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ice Tower (large)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;30°C&lt;/td&gt;
&lt;td&gt;45°C&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;~35 dB (audible)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The Active Cooler at 22 dB is effectively inaudible in a room with any ambient noise. It&amp;#8217;s the sweet spot for a silent&amp;nbsp;cluster.&lt;/p&gt;
&lt;h3&gt;PoE &lt;span class="caps"&gt;HAT&lt;/span&gt; Power&amp;nbsp;Draw&lt;/h3&gt;
&lt;p&gt;The official PoE+ &lt;span class="caps"&gt;HAT&lt;/span&gt; adds ~2W per node. If you&amp;#8217;re counting every watt, direct &lt;span class="caps"&gt;USB&lt;/span&gt;-C power saves 6W across three nodes. But you lose the single-cable simplicity. For most builds, the convenience tradeoff is worth&amp;nbsp;2W.&lt;/p&gt;
&lt;h3&gt;Under-Volting and &lt;span class="caps"&gt;CPU&lt;/span&gt;&amp;nbsp;Governor&lt;/h3&gt;
&lt;p&gt;&lt;span class="caps"&gt;ARM&lt;/span&gt; processors benefit from conservative &lt;span class="caps"&gt;CPU&lt;/span&gt;&amp;nbsp;scaling:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Check current governor&lt;/span&gt;
cat&lt;span class="w"&gt; &lt;/span&gt;/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor

&lt;span class="c1"&gt;# Set to ondemand (scale up only when needed)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;ondemand&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;tee&lt;span class="w"&gt; &lt;/span&gt;/sys/devices/system/cpu/cpu*/cpufreq/scaling_governor

&lt;span class="c1"&gt;# Make persistent&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;GOVERNOR=&amp;quot;ondemand&amp;quot;&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/default/cpufrequtils
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;ondemand&lt;/code&gt; governor keeps cores at 1.5GHz at idle and only ramps to 2.4GHz under load. This saves 2–3W per node at idle without perceptible performance impact for bursty homelab&amp;nbsp;workloads.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 8: Troubleshooting &lt;span class="caps"&gt;ARM&lt;/span&gt;-Specific&amp;nbsp;Issues&lt;/h2&gt;
&lt;h3&gt;Kernel Modules&amp;nbsp;Missing&lt;/h3&gt;
&lt;p&gt;Proxmox on &lt;span class="caps"&gt;ARM&lt;/span&gt; ships with a leaner kernel than x86. Some modules you&amp;#8217;d expect may be&amp;nbsp;absent:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Check loaded modules&lt;/span&gt;
lsmod

&lt;span class="c1"&gt;# Common missing modules and fixes&lt;/span&gt;
&lt;span class="c1"&gt;# WireGuard:&lt;/span&gt;
apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;wireguard-tools
modprobe&lt;span class="w"&gt; &lt;/span&gt;wireguard

&lt;span class="c1"&gt;# iptables/nftables (usually present but verify):&lt;/span&gt;
modprobe&lt;span class="w"&gt; &lt;/span&gt;nf_tables

&lt;span class="c1"&gt;# USB serial (for Zigbee/Z-Wave dongles):&lt;/span&gt;
modprobe&lt;span class="w"&gt; &lt;/span&gt;usbserial
modprobe&lt;span class="w"&gt; &lt;/span&gt;ftdi_sio
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Container Images Not Available for &lt;span class="caps"&gt;ARM&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;When you hit an x86-only image, you have three&amp;nbsp;options:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Find an &lt;span class="caps"&gt;ARM64&lt;/span&gt; alternative&lt;/strong&gt; — MariaDB instead of MySQL, &lt;span class="sp-brand jellyfin"&gt;Jellyfin&lt;/span&gt; instead of&amp;nbsp;Plex&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Build from source on the Pi&lt;/strong&gt; — most Go and Rust projects cross-compile trivially&amp;nbsp;with &lt;code&gt;GOARCH=arm64&lt;/code&gt; or &lt;code&gt;--target aarch64-unknown-linux-gnu&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use box64 emulation&lt;/strong&gt; — runs x86_64 binaries on &lt;span class="caps"&gt;ARM64&lt;/span&gt; with ~50% performance penalty.&amp;nbsp;Install: &lt;code&gt;apt install box64&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Corosync Split-Brain on Unreliable&amp;nbsp;Networks&lt;/h3&gt;
&lt;p&gt;A split-brain occurs when cluster nodes can&amp;#8217;t communicate and each thinks it&amp;#8217;s the sole surviving node. On a Pi cluster, this can happen&amp;nbsp;if:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The PoE switch reboots (all nodes lose connectivity&amp;nbsp;simultaneously)&lt;/li&gt;
&lt;li&gt;A node&amp;#8217;s Ethernet cable isn&amp;#8217;t fully&amp;nbsp;seated&lt;/li&gt;
&lt;li&gt;WiFi is used instead of Ethernet (never use WiFi for&amp;nbsp;Corosync)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Prevention:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Set higher Corosync token timeout (more tolerant of brief network blips)&lt;/span&gt;
&lt;span class="c1"&gt;# Edit /etc/corosync/corosync.conf&lt;/span&gt;
&lt;span class="c1"&gt;# Increase token: 5000 → 10000&lt;/span&gt;

&lt;span class="c1"&gt;# Enable two-node mode if you ever drop to 2 nodes&lt;/span&gt;
pvecm&lt;span class="w"&gt; &lt;/span&gt;expected&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If a split-brain does occur, the recovery&amp;nbsp;is:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# On the node that should rejoin&lt;/span&gt;
systemctl&lt;span class="w"&gt; &lt;/span&gt;stop&lt;span class="w"&gt; &lt;/span&gt;pve-cluster&lt;span class="w"&gt; &lt;/span&gt;corosync
rm&lt;span class="w"&gt; &lt;/span&gt;-rf&lt;span class="w"&gt; &lt;/span&gt;/etc/corosync/*
&lt;span class="c1"&gt;# Copy corosync.conf from a healthy node&lt;/span&gt;
scp&lt;span class="w"&gt; &lt;/span&gt;root@pi-node1:/etc/corosync/corosync.conf&lt;span class="w"&gt; &lt;/span&gt;/etc/corosync/
systemctl&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;corosync&lt;span class="w"&gt; &lt;/span&gt;pve-cluster
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Conclusion: When to Choose &lt;span class="caps"&gt;ARM&lt;/span&gt; vs.&amp;nbsp;x86&lt;/h2&gt;
&lt;p&gt;After building this cluster and running it for real workloads, the decision framework is&amp;nbsp;straightforward:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Choose a Pi 5 &lt;span class="caps"&gt;ARM&lt;/span&gt; cluster when:&lt;/strong&gt;
- Power is expensive (₿0.15+/kWh) or you&amp;#8217;re limited by circuit capacity
- Noise is a hard constraint (apartment, bedroom, shared office)
- You&amp;#8217;re running 10–20 lightweight &lt;span class="caps"&gt;LXC&lt;/span&gt; containers (&lt;span class="caps"&gt;DNS&lt;/span&gt;, monitoring, automation, reverse proxy)
- You want to learn clustering, distributed storage, and &lt;span class="caps"&gt;ARM&lt;/span&gt; architecture hands-on
- Budget for hardware is under&amp;nbsp;$300–$400&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Choose x86 (used mini &lt;span class="caps"&gt;PC&lt;/span&gt; or server) when:&lt;/strong&gt;
- You need &lt;span class="caps"&gt;KVM&lt;/span&gt; virtual machines (Windows, pfSense, non-Linux &lt;span class="caps"&gt;OS&lt;/span&gt;)
- Your workload is &lt;span class="caps"&gt;CPU&lt;/span&gt;-heavy (&lt;span class="caps"&gt;LLM&lt;/span&gt; inference, transcoding, databases)
- You need &amp;gt;&lt;span class="caps"&gt;8GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; per node for a single service
- You&amp;#8217;re deploying 30+ containers and don&amp;#8217;t want to worry about memory budgeting
- Broadest Docker image compatibility matters more than power&amp;nbsp;efficiency&lt;/p&gt;
&lt;p&gt;For many homelabbers, the answer is &lt;strong&gt;both&lt;/strong&gt;. An x86 Mini &lt;span class="caps"&gt;PC&lt;/span&gt; as the primary workhorse for heavy services, with a Pi 5 cluster running the always-on infrastructure layer (&lt;span class="caps"&gt;DNS&lt;/span&gt;, monitoring, ingress, automation). The Pi cluster sips power 24/7 while the x86 machine can be scheduled or powered on-demand via Wake-on-&lt;span class="caps"&gt;LAN&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;Next Steps — Expand to 5&amp;nbsp;Nodes&lt;/h3&gt;
&lt;p&gt;The Proxmox cluster supports up to 32 nodes. For a Pi cluster, 5 nodes is the practical sweet spot — it gives you &lt;span class="caps"&gt;40GB&lt;/span&gt; of total &lt;span class="caps"&gt;RAM&lt;/span&gt; and allows Ceph erasure coding (more space-efficient than triple replication). The same steps scale: flash Proxmox, join the cluster, add storage. Each additional node costs ~$90 (Pi 5 &lt;span class="caps"&gt;8GB&lt;/span&gt; + PoE &lt;span class="caps"&gt;HAT&lt;/span&gt;) and adds &lt;span class="caps"&gt;8GB&lt;/span&gt; of&amp;nbsp;capacity.&lt;/p&gt;
&lt;h3&gt;Recommended&amp;nbsp;Reading&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/2026/06/08/setting-up-proxmox-node/"&gt;Setting Up Your First Proxmox Node&lt;/a&gt; — Proxmox fundamentals if you&amp;#8217;re new to the&amp;nbsp;hypervisor&lt;/li&gt;
&lt;li&gt;&lt;a href="/2026/06/06/best-nas-os-homelab-2026/"&gt;Best &lt;span class="caps"&gt;NAS&lt;/span&gt; &lt;span class="caps"&gt;OS&lt;/span&gt; for Homelab 2026&lt;/a&gt; — Storage &lt;span class="caps"&gt;OS&lt;/span&gt; comparison for Ceph&amp;nbsp;alternatives&lt;/li&gt;
&lt;li&gt;&lt;a href="/2026/06/10/docker-networking-best-practices/"&gt;Docker Networking Best Practices&lt;/a&gt; — Network segmentation for your&amp;nbsp;cluster&lt;/li&gt;
&lt;li&gt;&lt;a href="/2026/06/08/homelab-backup-strategy-2026/"&gt;Self-Hosted Backup Strategy&lt;/a&gt; — Protect your cluster&amp;nbsp;data&lt;/li&gt;
&lt;li&gt;&lt;a href="/2026/06/06/cloudflare-tunnel-homelab/"&gt;Cloudflare Tunnel Homelab Guide&lt;/a&gt; — Expose cluster services&amp;nbsp;securely&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;&lt;span class="caps"&gt;FAQ&lt;/span&gt;&lt;/h2&gt;
&lt;h3&gt;Can I run VMs on a Raspberry Pi 5 Proxmox&amp;nbsp;node?&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;No.&lt;/strong&gt; Proxmox on &lt;span class="caps"&gt;ARM64&lt;/span&gt; does not support &lt;span class="caps"&gt;KVM&lt;/span&gt;-based virtual machines. The Pi 5&amp;#8217;s Cortex-A76 cores lack the hardware virtualization extensions (&lt;span class="caps"&gt;ARM&lt;/span&gt; equivalent of Intel &lt;span class="caps"&gt;VT&lt;/span&gt;-x/&lt;span class="caps"&gt;AMD&lt;/span&gt;-V) in a way that Proxmox&amp;#8217;s &lt;span class="caps"&gt;QEMU&lt;/span&gt;-&lt;span class="caps"&gt;KVM&lt;/span&gt; stack can use. You are limited to &lt;span class="caps"&gt;LXC&lt;/span&gt; containers. If you need VMs, use an x86 Proxmox&amp;nbsp;node.&lt;/p&gt;
&lt;h3&gt;Is &lt;span class="caps"&gt;8GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; enough for&amp;nbsp;Proxmox?&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Yes — for &lt;span class="caps"&gt;LXC&lt;/span&gt; workloads.&lt;/strong&gt; Proxmox itself (including Corosync and the web &lt;span class="caps"&gt;GUI&lt;/span&gt;) uses ~&lt;span class="caps"&gt;800MB&lt;/span&gt;. With &lt;span class="caps"&gt;8GB&lt;/span&gt;, you have ~&lt;span class="caps"&gt;7GB&lt;/span&gt; for &lt;span class="caps"&gt;LXC&lt;/span&gt; containers. That fits 7–14 lightweight containers comfortably. If you add Ceph, budget another 2–&lt;span class="caps"&gt;3GB&lt;/span&gt; for the &lt;span class="caps"&gt;OSD&lt;/span&gt; daemon, leaving ~&lt;span class="caps"&gt;4GB&lt;/span&gt; for containers. The &lt;span class="caps"&gt;8GB&lt;/span&gt; Pi 5 is the minimum viable — don&amp;#8217;t attempt this with the &lt;span class="caps"&gt;4GB&lt;/span&gt;&amp;nbsp;model.&lt;/p&gt;
&lt;h3&gt;Can I use WiFi instead of&amp;nbsp;Ethernet?&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;No. Never.&lt;/strong&gt; Corosync (the cluster communication layer) requires low-latency, reliable networking. WiFi introduces variable latency, packet loss, and occasional disconnections — all of which trigger false-positive node failures and split-brain scenarios. Always use wired Ethernet for cluster nodes. If you must use WiFi for management access, add it as a secondary interface separate from the Corosync&amp;nbsp;network.&lt;/p&gt;
&lt;h3&gt;What about the Pi 5 PCIe &lt;span class="caps"&gt;HAT&lt;/span&gt; for&amp;nbsp;NVMe?&lt;/h3&gt;
&lt;p&gt;The Pi 5&amp;#8217;s PCIe 2.0 x1 lane provides ~500 &lt;span class="caps"&gt;MB&lt;/span&gt;/s theoretical bandwidth — enough for a single NVMe &lt;span class="caps"&gt;SSD&lt;/span&gt; to run at near full speed (most consumer NVMe drives top out around 500–600 &lt;span class="caps"&gt;MB&lt;/span&gt;/s sequential anyway). The Pineberry Pi HatDrive! Top ($20) and Waveshare Pi 5 NVMe &lt;span class="caps"&gt;HAT&lt;/span&gt; ($15) are both well-supported. The NVMe drive must be M.2 2230 or 2242 form factor (not the longer 2280), unless you use a flexible extension&amp;nbsp;cable.&lt;/p&gt;
&lt;h3&gt;How does this compare to an Orange Pi 5 Plus&amp;nbsp;cluster?&lt;/h3&gt;
&lt;p&gt;The Orange Pi 5 Plus has a Rockchip &lt;span class="caps"&gt;RK3588&lt;/span&gt; (4× Cortex-A76 + 4× Cortex-A55) with up to &lt;span class="caps"&gt;16GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; and native M.2 NVMe slot — specs that beat the Pi 5 on paper. However, Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; does not officially support the Rockchip platform. You&amp;#8217;d need to use Armbian as the base &lt;span class="caps"&gt;OS&lt;/span&gt; and run Docker directly or use a different orchestrator. For a pure &lt;span class="sp-brand proxmox"&gt;Proxmox&lt;/span&gt; experience with clustering, the Pi 5 is the supported&amp;nbsp;path.&lt;/p&gt;
&lt;h3&gt;Can I mix Pi 4 and Pi 5 nodes in the same&amp;nbsp;cluster?&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Technically yes, but not recommended.&lt;/strong&gt; Proxmox allows heterogeneous nodes, but mixing &lt;span class="caps"&gt;ARM&lt;/span&gt; generations creates subtle problems: different kernel versions, different available kernel modules, and unpredictable migration behavior. The Pi 4&amp;#8217;s &lt;span class="caps"&gt;4GB&lt;/span&gt; ceiling also drags down the cluster&amp;#8217;s useful capacity. Stick to identical Pi 5 nodes for a homogeneous, predictable&amp;nbsp;cluster.&lt;/p&gt;
&lt;h3&gt;What&amp;#8217;s the fastest way to recover a failed&amp;nbsp;node?&lt;/h3&gt;
&lt;p&gt;If a Pi node fails (corrupted &lt;span class="caps"&gt;SD&lt;/span&gt; card, hardware issue), the fastest recovery is:
1. Flash a fresh Proxmox &lt;span class="caps"&gt;ARM64&lt;/span&gt; &lt;span class="caps"&gt;ISO&lt;/span&gt; to a new microSD card
2. Boot the replacement Pi
3. Set the same static &lt;span class="caps"&gt;IP&lt;/span&gt; as the failed node
4. Join the cluster with its original node&amp;nbsp;name: &lt;code&gt;pvecm add &amp;lt;master-ip&amp;gt; --nodeid &amp;lt;original-id&amp;gt;&lt;/code&gt;
5. Re-add the NVMe drive to&amp;nbsp;Ceph: &lt;code&gt;pveceph osd create /dev/nvme0n1&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The Ceph data on the NVMe drive (if the drive itself survived) will self-heal through replication. Total recovery time: ~15&amp;nbsp;minutes.&lt;/p&gt;
&lt;h3&gt;Do I need a &lt;span class="caps"&gt;UPS&lt;/span&gt; for a Pi&amp;nbsp;cluster?&lt;/h3&gt;
&lt;p&gt;A &lt;span class="caps"&gt;UPS&lt;/span&gt; is useful but less critical than for x86 servers. The Pi 5 has no spinning disks (NVMe &lt;span class="caps"&gt;SSD&lt;/span&gt;) and handles sudden power loss more gracefully. That said, Ceph replication won&amp;#8217;t protect you from simultaneous power loss to all 3 nodes. A small &lt;span class="caps"&gt;UPS&lt;/span&gt; like the &lt;span class="caps"&gt;APC&lt;/span&gt; Back-&lt;span class="caps"&gt;UPS&lt;/span&gt; &lt;span class="caps"&gt;425VA&lt;/span&gt; (~$50) can keep all three Pi nodes + PoE switch running for 30–60 minutes — enough to ride out most&amp;nbsp;outages.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Which &lt;span class="caps"&gt;ARM&lt;/span&gt; board runs your homelab?&lt;/strong&gt; Pi 5, Orange Pi, or something else entirely? &lt;strong&gt;Subscribe&lt;/strong&gt; for weekly homelab hardware and clustering guides — we cover the builds that work, not just the ones that look good on&amp;nbsp;YouTube.&lt;/p&gt;</content><category term="Guides"/><category term="raspberry-pi"/><category term="proxmox"/><category term="arm"/><category term="cluster"/><category term="homelab"/><category term="docker"/><category term="lxc"/><category term="ceph"/><category term="poe"/><category term="low-power"/><category term="2026"/></entry><entry><title>Tailscale vs Traditional WireGuard: Which VPN Is Right for Your Homelab in 2026?</title><link href="https://steadypub.com/2026/06/tailscale-vs-wireguard-homelab-2026/" rel="alternate"/><published>2026-06-12T00:00:00+07:00</published><updated>2026-06-12T00:00:00+07:00</updated><author><name>WordForge Team</name></author><id>tag:steadypub.com,2026-06-12:/2026/06/tailscale-vs-wireguard-homelab-2026/</id><summary type="html">&lt;p&gt;Compare Tailscale and traditional WireGuard for homelab remote access in 2026. Side-by-side analysis of setup complexity, performance, &lt;span class="caps"&gt;NAT&lt;/span&gt; traversal, and security model — with real config examples and a decision framework to help you&amp;nbsp;choose.&lt;/p&gt;</summary><content type="html">&lt;hr&gt;
&lt;h1&gt;Tailscale vs Traditional WireGuard: Which &lt;span class="caps"&gt;VPN&lt;/span&gt; Is Right for Your Homelab in&amp;nbsp;2026?&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~11 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab owners who need secure remote access to their services and are weighing the trade-offs between the simplicity of &lt;span class="sp-brand tailscale"&gt;Tailscale&lt;/span&gt; and the raw performance of vanilla &lt;span class="sp-brand wireguard"&gt;WireGuard&lt;/span&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Introduction: The Remote Access&amp;nbsp;Dilemma&lt;/h2&gt;
&lt;p&gt;You have spent months building your homelab. &lt;span class="sp-brand proxmox"&gt;Proxmox&lt;/span&gt; runs your VMs, &lt;span class="sp-brand docker"&gt;Docker&lt;/span&gt; Compose orchestrates your services, and &lt;span class="sp-brand nginx"&gt;Nginx&lt;/span&gt; Proxy Manager routes traffic on your &lt;span class="caps"&gt;LAN&lt;/span&gt;. Everything hums along beautifully — until you leave the house. Suddenly, that &lt;span class="sp-brand nextcloud"&gt;Nextcloud&lt;/span&gt; instance, your &lt;span class="sp-brand homeassistant"&gt;Home Assistant&lt;/span&gt; dashboard, and your &lt;span class="sp-brand jellyfin"&gt;Jellyfin&lt;/span&gt; media server are all unreachable. You are locked out of your own infrastructure by the simple fact that you are not on the same&amp;nbsp;network.&lt;/p&gt;
&lt;p&gt;The solution is a &lt;span class="caps"&gt;VPN&lt;/span&gt; — but which one? Two names dominate the conversation in 2026: &lt;strong&gt;WireGuard&lt;/strong&gt;, the kernel-level protocol that redefined &lt;span class="caps"&gt;VPN&lt;/span&gt; performance, and &lt;strong&gt;Tailscale&lt;/strong&gt;, the user-friendly mesh networking layer built on top of WireGuard. Both use the same cryptographic primitives. Both deliver excellent throughput. Yet the experience of setting them up, maintaining them, and living with them day-to-day could not be more&amp;nbsp;different.&lt;/p&gt;
&lt;p&gt;This guide compares them side-by-side for the specific use case of homelab remote access. We cover setup complexity, raw performance, &lt;span class="caps"&gt;NAT&lt;/span&gt; traversal behaviour, security models, and the scenarios where one clearly beats the other. By the end, you will know exactly which approach fits your homelab — and your tolerance for &lt;span class="caps"&gt;YAML&lt;/span&gt;&amp;nbsp;files.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Comparison at a&amp;nbsp;Glance&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;WireGuard (Vanilla)&lt;/th&gt;
&lt;th&gt;Tailscale&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Setup time&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;30–90 minutes (per peer)&lt;/td&gt;
&lt;td&gt;Under 5 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;NAT&lt;/span&gt; traversal&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual — port forwarding or &lt;span class="caps"&gt;STUN&lt;/span&gt; required&lt;/td&gt;
&lt;td&gt;Automatic — &lt;span class="caps"&gt;DERP&lt;/span&gt; relays + &lt;span class="caps"&gt;NAT&lt;/span&gt;-&lt;span class="caps"&gt;PMP&lt;/span&gt;/UPnP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Key management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual key generation + distribution&lt;/td&gt;
&lt;td&gt;Automatic — OAuth, &lt;span class="caps"&gt;SSO&lt;/span&gt;, or pre-auth keys&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mesh topology support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual — every peer pair needs a config block&lt;/td&gt;
&lt;td&gt;Automatic — full mesh with&amp;nbsp;one &lt;code&gt;tailscale up&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;ACL&lt;/span&gt; / access control&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;None built-in —&amp;nbsp;use &lt;code&gt;iptables&lt;/code&gt; / &lt;code&gt;nftables&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Built-in ACLs with tags, groups, and auto-approvers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Performance overhead&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Near line-rate (kernel WireGuard)&lt;/td&gt;
&lt;td&gt;~5–10% overhead vs vanilla (userspace in most setups)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt; integration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual —&amp;nbsp;configure &lt;code&gt;PostUp&lt;/code&gt; scripts&lt;/td&gt;
&lt;td&gt;Built-in MagicDNS&amp;nbsp;— &lt;code&gt;&amp;lt;hostname&amp;gt;.ts.net&lt;/code&gt; for every device&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mobile client&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Native WireGuard app (manual config import)&lt;/td&gt;
&lt;td&gt;Tailscale app (sign-in, auto-configured)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Exit node support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual iptables &lt;span class="caps"&gt;NAT&lt;/span&gt; rules&lt;/td&gt;
&lt;td&gt;One&amp;nbsp;flag: &lt;code&gt;--advertise-exit-node&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Funnel (public sharing)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Not available&lt;/td&gt;
&lt;td&gt;Built-in — expose a service to the internet&amp;nbsp;via &lt;code&gt;tailscale funnel&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Free — fully open source (GPLv2)&lt;/td&gt;
&lt;td&gt;Free for up to 3 users + 100 devices. Paid plans from $6/user/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Self-hosted control server&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;N/A (no control plane)&lt;/td&gt;
&lt;td&gt;Headscale — open-source reimplementation of the coordination server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Performance purists, air-gapped networks, small peer counts&lt;/td&gt;
&lt;td&gt;Multi-device users, families, dynamic environments, non-technical users&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;What Is&amp;nbsp;WireGuard?&lt;/h2&gt;
&lt;p&gt;WireGuard is a Layer 3 &lt;span class="caps"&gt;VPN&lt;/span&gt; protocol designed by Jason A. Donenfeld and merged into the Linux kernel in 2020. It uses a noise-based handshake, ChaCha20 for encryption, Poly1305 for authentication, and Curve25519 for key exchange. The codebase is deliberately tiny — around 4,000 lines — making it auditable and&amp;nbsp;fast.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What WireGuard does:&lt;/strong&gt;
- Creates an encrypted tunnel between two peers using public/private key pairs
- Routes traffic at the &lt;span class="caps"&gt;IP&lt;/span&gt; layer with minimal overhead
- Roams seamlessly between networks (Wi-Fi to cellular without dropping the&amp;nbsp;tunnel)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What WireGuard does &lt;span class="caps"&gt;NOT&lt;/span&gt; do:&lt;/strong&gt;
- Manage keys (you generate, distribute, and rotate them manually)
- Handle &lt;span class="caps"&gt;NAT&lt;/span&gt; traversal (if both peers are behind &lt;span class="caps"&gt;NAT&lt;/span&gt;, you need port forwarding on at least one end)
- Provide a control plane or user interface
- Offer access control lists or user management
- Distribute configuration updates — every peer change means editing config files on every affected&amp;nbsp;device&lt;/p&gt;
&lt;p&gt;WireGuard is a &lt;strong&gt;protocol and a tool&lt;/strong&gt;, not a platform. It gives you encrypted tunnels and nothing else. Everything beyond that — key distribution, topology management, &lt;span class="caps"&gt;DNS&lt;/span&gt; — is your&amp;nbsp;responsibility.&lt;/p&gt;
&lt;h3&gt;Vanilla WireGuard Configuration&amp;nbsp;Example&lt;/h3&gt;
&lt;p&gt;Here is a minimal WireGuard setup between a homelab server and a&amp;nbsp;laptop:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Server&lt;/strong&gt;&amp;nbsp;(&lt;code&gt;/etc/wireguard/wg0.conf&lt;/code&gt;):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;[Interface]&lt;/span&gt;
&lt;span class="na"&gt;PrivateKey&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;server-private-key&amp;gt;&lt;/span&gt;
&lt;span class="na"&gt;Address&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;10.0.0.1/24&lt;/span&gt;
&lt;span class="na"&gt;ListenPort&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;51820&lt;/span&gt;
&lt;span class="c1"&gt;# Forward traffic from VPN clients to LAN&lt;/span&gt;
&lt;span class="na"&gt;PostUp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;iptables -A FORWARD -i wg0 -j ACCEPT&lt;/span&gt;
&lt;span class="na"&gt;PostUp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE&lt;/span&gt;
&lt;span class="na"&gt;PostDown&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;iptables -D FORWARD -i wg0 -j ACCEPT&lt;/span&gt;
&lt;span class="na"&gt;PostDown&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE&lt;/span&gt;

&lt;span class="k"&gt;[Peer]&lt;/span&gt;
&lt;span class="c1"&gt;# Laptop&lt;/span&gt;
&lt;span class="na"&gt;PublicKey&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;laptop-public-key&amp;gt;&lt;/span&gt;
&lt;span class="na"&gt;AllowedIPs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;10.0.0.2/32&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Laptop&lt;/strong&gt;&amp;nbsp;(&lt;code&gt;/etc/wireguard/wg0.conf&lt;/code&gt;):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;[Interface]&lt;/span&gt;
&lt;span class="na"&gt;PrivateKey&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;laptop-private-key&amp;gt;&lt;/span&gt;
&lt;span class="na"&gt;Address&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;10.0.0.2/24&lt;/span&gt;
&lt;span class="na"&gt;DNS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;192.168.1.1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Your homelab DNS&lt;/span&gt;

&lt;span class="k"&gt;[Peer]&lt;/span&gt;
&lt;span class="c1"&gt;# Homelab server&lt;/span&gt;
&lt;span class="na"&gt;PublicKey&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;server-public-key&amp;gt;&lt;/span&gt;
&lt;span class="na"&gt;Endpoint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;your-home-public-ip:51820&lt;/span&gt;
&lt;span class="na"&gt;AllowedIPs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;10.0.0.0/24, 192.168.1.0/24&lt;/span&gt;
&lt;span class="na"&gt;PersistentKeepalive&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;25&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Every new device requires generating a key pair, adding&amp;nbsp;a &lt;code&gt;[Peer]&lt;/code&gt; block to the server config, and reloading WireGuard. For three devices, this is manageable. For ten, it becomes a chore. For a family of four with laptops, phones, and tablets, it is a part-time&amp;nbsp;job.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is&amp;nbsp;Tailscale?&lt;/h2&gt;
&lt;p&gt;Tailscale is a mesh &lt;span class="caps"&gt;VPN&lt;/span&gt; built &lt;strong&gt;on top of&lt;/strong&gt; WireGuard. It uses WireGuard for the data plane — every packet between your devices is encrypted with the same WireGuard primitives — but wraps it with a coordination server that handles key exchange, &lt;span class="caps"&gt;NAT&lt;/span&gt; traversal, and access control&amp;nbsp;automatically.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Here is what Tailscale adds on top of&amp;nbsp;WireGuard:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Automatic key exchange.&lt;/strong&gt; You sign in with Google, GitHub, Microsoft, or an &lt;span class="caps"&gt;OIDC&lt;/span&gt; provider. Tailscale&amp;#8217;s coordination server generates WireGuard key pairs, distributes them, and rotates them — you never touch a private&amp;nbsp;key.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;NAT&lt;/span&gt; traversal that actually works.&lt;/strong&gt; Tailscale uses &lt;span class="caps"&gt;DERP&lt;/span&gt; (Designated Encrypted Relay for Packets) relays when direct connections are impossible, and aggressively probes for direct paths using &lt;span class="caps"&gt;NAT&lt;/span&gt;-&lt;span class="caps"&gt;PMP&lt;/span&gt;, UPnP, and &lt;span class="caps"&gt;STUN&lt;/span&gt;. In practice, it establishes direct peer-to-peer connections far more often than you would expect — even through double &lt;span class="caps"&gt;NAT&lt;/span&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;MagicDNS.&lt;/strong&gt; Every device gets a&amp;nbsp;stable &lt;code&gt;&amp;lt;hostname&amp;gt;.ts-net.ts.net&lt;/code&gt; hostname that resolves from any other device on your tailnet. No &lt;span class="caps"&gt;DNS&lt;/span&gt; configuration,&amp;nbsp;no &lt;code&gt;/etc/hosts&lt;/code&gt; entries.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Built-in ACLs.&lt;/strong&gt; Define who can access what using a &lt;span class="caps"&gt;JSON&lt;/span&gt; or HuJSON policy file. Tags let you group devices&amp;nbsp;(e.g., &lt;code&gt;tag:production&lt;/code&gt;, &lt;code&gt;tag:iot&lt;/code&gt;) and write rules like &amp;#8220;devices&amp;nbsp;tagged &lt;code&gt;iot&lt;/code&gt; can only reach port 80 on the monitoring&amp;nbsp;server.&amp;#8221;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Exit nodes.&lt;/strong&gt; Any device can be promoted to an exit node with one&amp;nbsp;flag: &lt;code&gt;tailscale up --advertise-exit-node&lt;/code&gt;. All your traffic routes through your homelab as if you were sitting at&amp;nbsp;home.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Tailscale Funnel.&lt;/strong&gt; Expose a specific port to the public internet through Tailscale&amp;#8217;s ingress, no port forwarding required. Useful for sharing a single service without exposing your entire&amp;nbsp;tailnet.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Tailscale Setup in&amp;nbsp;Practice&lt;/h3&gt;
&lt;p&gt;On your homelab&amp;nbsp;server:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Install&lt;/span&gt;
curl&lt;span class="w"&gt; &lt;/span&gt;-fsSL&lt;span class="w"&gt; &lt;/span&gt;https://tailscale.com/install.sh&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sh

&lt;span class="c1"&gt;# Authenticate and join your tailnet&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;tailscale&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;--advertise-routes&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.1.0/24&lt;span class="w"&gt; &lt;/span&gt;--advertise-exit-node
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;On your&amp;nbsp;laptop:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-fsSL&lt;span class="w"&gt; &lt;/span&gt;https://tailscale.com/install.sh&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sh
sudo&lt;span class="w"&gt; &lt;/span&gt;tailscale&lt;span class="w"&gt; &lt;/span&gt;up
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That is it. Both devices are now connected. The laptop can reach the server&amp;nbsp;at &lt;code&gt;&amp;lt;server-hostname&amp;gt;.ts-net.ts.net&lt;/code&gt;. Routes to the homelab &lt;span class="caps"&gt;LAN&lt;/span&gt; are automatically available. No key generation.&amp;nbsp;No &lt;code&gt;[Peer]&lt;/code&gt; blocks.&amp;nbsp;No &lt;code&gt;PostUp&lt;/code&gt; iptables rules. The whole process takes under two&amp;nbsp;minutes.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Deep Dive: Setup&amp;nbsp;Complexity&lt;/h2&gt;
&lt;p&gt;The difference in setup philosophy is best illustrated by what happens when you add a fifth device to your&amp;nbsp;network.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;With WireGuard&lt;/strong&gt;, adding device #5 means:
1. Generate a key pair on the new device&amp;nbsp;(&lt;code&gt;wg genkey | tee privatekey | wg pubkey&lt;/code&gt;)
2. Copy the public key
3. &lt;span class="caps"&gt;SSH&lt;/span&gt; into every existing peer that needs to communicate with the new device
4. Add&amp;nbsp;a &lt;code&gt;[Peer]&lt;/code&gt; block to each config file
5.&amp;nbsp;Run &lt;code&gt;wg syncconf wg0 &amp;lt;(wg-quick strip wg0)&lt;/code&gt; on each peer or restart the interface
6. Update your mental map of which &lt;span class="caps"&gt;IP&lt;/span&gt; belongs to which device
7. If you are running a hub-and-spoke topology, Steps 3–5 only apply to the hub. If you want a full mesh, apply to every&amp;nbsp;peer.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;With Tailscale&lt;/strong&gt;, adding device #5 means:
1. Install Tailscale
2.&amp;nbsp;Run &lt;code&gt;tailscale up&lt;/code&gt;
3. Authenticate (OAuth or pre-auth key)
4. Done — the device appears in your admin console, gets a MagicDNS name, and can reach every other device&amp;nbsp;automatically.&lt;/p&gt;
&lt;p&gt;The gap widens with every additional device. WireGuard&amp;#8217;s manual key management is fundamentally an O(n²) problem for a full mesh — every new peer requires updates to every existing peer. Tailscale makes it O(1). This alone is the deciding factor for many&amp;nbsp;homelabbers.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Deep Dive: Performance and&amp;nbsp;Latency&lt;/h2&gt;
&lt;p&gt;WireGuard&amp;#8217;s performance advantage is real, but the size of the gap depends on how you run&amp;nbsp;Tailscale.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Kernel WireGuard&lt;/strong&gt; (vanilla) operates entirely in kernel space. Packets are encrypted and decrypted without context-switching to userspace. On a modern x86 server, WireGuard saturates a gigabit link with negligible &lt;span class="caps"&gt;CPU&lt;/span&gt; usage. Latency overhead is typically under 1&amp;nbsp;millisecond.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tailscale&lt;/strong&gt; runs WireGuard in userspace (via&amp;nbsp;the &lt;code&gt;wireguard-go&lt;/code&gt; implementation on most platforms) because the coordination layer needs to manage keys and routing dynamically. This adds a measurable but typically irrelevant&amp;nbsp;overhead:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Throughput:&lt;/strong&gt; 5–10% lower than kernel WireGuard on the same hardware. On a 1 Gbps link, that is the difference between 940 Mbps and 850–890 Mbps — significant for a datacenter, irrelevant for a homelab where your upstream is likely 20–100&amp;nbsp;Mbps.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Latency:&lt;/strong&gt; 1–3 ms additional overhead vs kernel WireGuard. Again, meaningful for high-frequency trading, invisible for &lt;span class="caps"&gt;SSH&lt;/span&gt; sessions and Jellyfin&amp;nbsp;streaming.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;The &lt;span class="caps"&gt;DERP&lt;/span&gt; relay factor:&lt;/strong&gt; When Tailscale cannot establish a direct peer-to-peer connection (rare, but possible with very restrictive &lt;span class="caps"&gt;NAT&lt;/span&gt;), traffic routes through Tailscale&amp;#8217;s &lt;span class="caps"&gt;DERP&lt;/span&gt; relay servers. These are geographically distributed, but relayed traffic adds 20–80 ms of latency depending on relay proximity. Vanilla WireGuard has no equivalent fallback — if a direct connection cannot be established, you simply have no connectivity. In practice, this makes Tailscale &lt;strong&gt;more&lt;/strong&gt; reliable for homelabbers on residential ISPs with &lt;span class="caps"&gt;CGNAT&lt;/span&gt;, even if it is sometimes slightly&amp;nbsp;slower.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Verdict:&lt;/strong&gt; If you need every last megabit of throughput and you control both ends of the connection (e.g., a site-to-site link between two data centers), use kernel WireGuard. For homelab remote access — where your bottleneck is almost certainly your &lt;span class="caps"&gt;ISP&lt;/span&gt; uplink, not the &lt;span class="caps"&gt;VPN&lt;/span&gt; — Tailscale&amp;#8217;s overhead is&amp;nbsp;invisible.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Deep Dive: &lt;span class="caps"&gt;NAT&lt;/span&gt;&amp;nbsp;Traversal&lt;/h2&gt;
&lt;p&gt;&lt;span class="caps"&gt;NAT&lt;/span&gt; traversal is where Tailscale earns its keep and vanilla WireGuard leaves you on your&amp;nbsp;own.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;WireGuard&amp;#8217;s &lt;span class="caps"&gt;NAT&lt;/span&gt; behaviour:&lt;/strong&gt;
- WireGuard is &lt;span class="caps"&gt;UDP&lt;/span&gt;-based and &lt;span class="caps"&gt;NAT&lt;/span&gt;-unfriendly by design. It does not attempt &lt;span class="caps"&gt;STUN&lt;/span&gt;, UPnP, or &lt;span class="caps"&gt;NAT&lt;/span&gt;-&lt;span class="caps"&gt;PMP&lt;/span&gt;.
- If one peer has a public &lt;span class="caps"&gt;IP&lt;/span&gt; and an open port, the other peer behind &lt;span class="caps"&gt;NAT&lt;/span&gt; can initiate a connection and WireGuard will work — the &lt;span class="caps"&gt;NAT&lt;/span&gt;&amp;#8217;d peer&amp;#8217;s &lt;span class="caps"&gt;UDP&lt;/span&gt; &amp;#8220;connection&amp;#8221; is tracked by the &lt;span class="caps"&gt;NAT&lt;/span&gt; gateway as long&amp;nbsp;as &lt;code&gt;PersistentKeepalive&lt;/code&gt; keeps it alive.
- If &lt;strong&gt;both&lt;/strong&gt; peers are behind &lt;span class="caps"&gt;NAT&lt;/span&gt; (double &lt;span class="caps"&gt;NAT&lt;/span&gt;, &lt;span class="caps"&gt;CGNAT&lt;/span&gt;), WireGuard cannot establish a direct connection without manual port forwarding on at least one end. This is the reality for many homelabbers on residential&amp;nbsp;ISPs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tailscale&amp;#8217;s &lt;span class="caps"&gt;NAT&lt;/span&gt; behaviour:&lt;/strong&gt;
- Tailscale aggressively probes for direct connections using &lt;span class="caps"&gt;STUN&lt;/span&gt;, &lt;span class="caps"&gt;NAT&lt;/span&gt;-&lt;span class="caps"&gt;PMP&lt;/span&gt;, and UPnP.
- If direct connectivity is impossible, traffic falls back to &lt;span class="caps"&gt;DERP&lt;/span&gt; relays — encrypted &lt;span class="caps"&gt;TCP&lt;/span&gt; tunnels through Tailscale&amp;#8217;s infrastructure. Your packets are end-to-end encrypted (Tailscale cannot read them), but they do transit Tailscale&amp;#8217;s servers.
- In the Tailscale admin console, you can see exactly which path each peer connection takes: direct, or via a specific &lt;span class="caps"&gt;DERP&lt;/span&gt; relay.
- If you are uncomfortable with &lt;span class="caps"&gt;DERP&lt;/span&gt; relays, you can run your own &lt;span class="caps"&gt;DERP&lt;/span&gt; server in your homelab. Tailscale publishes the&amp;nbsp;open-source &lt;code&gt;derper&lt;/code&gt; binary.&lt;/p&gt;
&lt;p&gt;For a homelabber behind &lt;span class="caps"&gt;CGNAT&lt;/span&gt; who wants to access services from a coffee shop (also behind &lt;span class="caps"&gt;NAT&lt;/span&gt;), Tailscale is the only approach that works out of the box. WireGuard requires either a public relay server (a $5 &lt;span class="caps"&gt;VPS&lt;/span&gt;) or port forwarding that your &lt;span class="caps"&gt;ISP&lt;/span&gt; may not&amp;nbsp;offer.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Deep Dive: Security&amp;nbsp;Model&lt;/h2&gt;
&lt;p&gt;Both systems use WireGuard&amp;#8217;s cryptography. The difference is in the &lt;strong&gt;control plane&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Vanilla WireGuard — Decentralized Trust:&lt;/strong&gt;
- Every peer&amp;#8217;s public key is manually distributed. You control which keys are trusted.
- There is no central authority that can add or remove peers. Compromising one peer does not give an attacker the ability to add new peers to the network.
- The downside: key rotation requires manual coordination. If a device is lost or stolen, you must remove its public key from every peer&amp;#8217;s config before the thief can&amp;nbsp;connect.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tailscale — Centralized Trust with Guardrails:&lt;/strong&gt;
- Tailscale&amp;#8217;s coordination server is the central authority. It holds every device&amp;#8217;s WireGuard private key (encrypted at rest) and distributes them to peers.
- If an attacker compromises your Tailscale account (via &lt;span class="caps"&gt;SSO&lt;/span&gt;), they can add devices to your tailnet. This is the centralization risk.
- Tailscale mitigates this with: mandatory device approval (new devices must be approved in the admin console), ACLs that limit what each device can access, and the ability to disable a device remotely with one click.
- For the truly paranoid: &lt;strong&gt;Headscale&lt;/strong&gt; is an open-source reimplementation of the Tailscale coordination server that you self-host. It gives you the Tailscale experience (automatic key management, MagicDNS, ACLs) with zero dependency on Tailscale&amp;#8217;s&amp;nbsp;infrastructure.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The pragmatic take:&lt;/strong&gt; For a homelab, Tailscale&amp;#8217;s centralized model is arguably &lt;strong&gt;more&lt;/strong&gt; secure in practice because it makes security easy. ACLs that take five minutes to write in Tailscale would require a complex iptables ruleset in vanilla WireGuard — and most homelabbers never get around to writing them. The best security model is the one you actually configure&amp;nbsp;correctly.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;When to Choose Vanilla&amp;nbsp;WireGuard&lt;/h2&gt;
&lt;p&gt;WireGuard is the right choice&amp;nbsp;when:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;You have a small, static peer count.&lt;/strong&gt; Three or four devices that rarely change. The manual key management overhead is&amp;nbsp;tolerable.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Performance is paramount.&lt;/strong&gt; You are running a site-to-site tunnel between two servers and want kernel-level throughput with zero userspace&amp;nbsp;overhead.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;You need air-gapped operation.&lt;/strong&gt; No internet dependency for coordination. WireGuard works on a completely isolated network — no coordination server, no &lt;span class="caps"&gt;SSO&lt;/span&gt;, no cloud&amp;nbsp;dependency.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;You want zero external dependencies.&lt;/strong&gt; WireGuard is in the Linux kernel. No third-party service, no subscription, no &lt;span class="caps"&gt;API&lt;/span&gt; calls. It keeps working as long as the kernel&amp;nbsp;boots.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;You run a management &lt;span class="caps"&gt;UI&lt;/span&gt;.&lt;/strong&gt; Tools like &lt;strong&gt;&lt;span class="caps"&gt;WG&lt;/span&gt;-Easy&lt;/strong&gt; or &lt;strong&gt;WireGuard-&lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/strong&gt; provide a web dashboard for key management, &lt;span class="caps"&gt;QR&lt;/span&gt; code generation, and peer configuration — bridging the gap between vanilla WireGuard and a full platform like Tailscale without the cloud dependency. We cover WireGuard-&lt;span class="caps"&gt;UI&lt;/span&gt; in our &lt;a href="/2026/06/nginx-proxy-manager-docker-compose/"&gt;Nginx Proxy Manager Docker Compose Guide&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;When to Choose&amp;nbsp;Tailscale&lt;/h2&gt;
&lt;p&gt;Tailscale wins&amp;nbsp;when:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;You have multiple devices and non-technical users.&lt;/strong&gt; If your spouse, kids, or parents need access to homelab services, Tailscale&amp;#8217;s sign-in flow eliminates the support burden. No private keys to email, no &lt;span class="caps"&gt;QR&lt;/span&gt; codes to scan, no config files to&amp;nbsp;edit.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;You are behind &lt;span class="caps"&gt;CGNAT&lt;/span&gt; or restrictive &lt;span class="caps"&gt;NAT&lt;/span&gt;.&lt;/strong&gt; Tailscale&amp;#8217;s &lt;span class="caps"&gt;NAT&lt;/span&gt; traversal and &lt;span class="caps"&gt;DERP&lt;/span&gt; fallback make it work in network environments where vanilla WireGuard simply cannot establish a&amp;nbsp;connection.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;You add and remove services frequently.&lt;/strong&gt; Tailscale&amp;#8217;s ACLs and tags let you segment access without touching device configs. Adding a new service that should only be reachable by certain devices is a policy edit, not a per-device&amp;nbsp;reconfiguration.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;You want MagicDNS.&lt;/strong&gt;&amp;nbsp;Typing &lt;code&gt;ssh proxmox.ts-net.ts.net&lt;/code&gt; instead of&amp;nbsp;remembering &lt;code&gt;10.0.0.5&lt;/code&gt; is a quality-of-life improvement that compounds&amp;nbsp;daily.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;You want built-in sharing.&lt;/strong&gt; Tailscale Funnel lets you share a single service publicly without exposing your entire tailnet — useful for sharing a &lt;span class="sp-brand jellyfin"&gt;Jellyfin&lt;/span&gt; stream with a friend without giving them &lt;span class="caps"&gt;VPN&lt;/span&gt;&amp;nbsp;access.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For a deeper dive into exposing homelab services securely, see our &lt;a href="/2026/06/cloudflare-tunnel-homelab/"&gt;Cloudflare Tunnel Homelab Guide&lt;/a&gt; and the comparison between automation approaches in &lt;a href="/2026/06/dockflare-vs-manual-tunnels/"&gt;DockFlare vs Manual Cloudflare Tunnels&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The Hybrid Approach: Tailscale with&amp;nbsp;Headscale&lt;/h2&gt;
&lt;p&gt;There is a third option that combines the best of both worlds: &lt;strong&gt;Headscale&lt;/strong&gt;, an open-source reimplementation of the Tailscale control&amp;nbsp;server.&lt;/p&gt;
&lt;p&gt;With Headscale, you:
- Run the coordination server yourself — no dependency on Tailscale&amp;#8217;s infrastructure
- Keep automatic key management, MagicDNS, and ACLs
- Use the standard Tailscale clients&amp;nbsp;(&lt;code&gt;tailscale up --login-server https://headscale.yourdomain.com&lt;/code&gt;)
- Pay nothing — Headscale is Apache 2.0 licensed
- Control every aspect of your tailnet from a self-hosted&amp;nbsp;dashboard&lt;/p&gt;
&lt;p&gt;Headscale requires a server (a $5 &lt;span class="caps"&gt;VPS&lt;/span&gt; or a &lt;span class="sp-brand proxmox"&gt;Proxmox&lt;/span&gt; &lt;span class="caps"&gt;LXC&lt;/span&gt; works perfectly) and about an hour of setup. It is the answer for homelabbers who want Tailscale&amp;#8217;s user experience but refuse to depend on a cloud service for their &lt;span class="caps"&gt;VPN&lt;/span&gt; coordination. For related self-hosting infrastructure patterns, see our &lt;a href="/2026/06/docker-networking-best-practices/"&gt;Docker Networking Best Practices&lt;/a&gt;&amp;nbsp;guide.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;2026 Verdict: Which Should You&amp;nbsp;Use?&lt;/h2&gt;
&lt;p&gt;The answer depends on a single question: &lt;strong&gt;how many devices and who manages&amp;nbsp;them?&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Recommendation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Solo homelab, 2–3 devices, static setup, you enjoy Linux networking&lt;/td&gt;
&lt;td&gt;WireGuard with &lt;span class="caps"&gt;WG&lt;/span&gt;-Easy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Solo homelab, 5+ devices, dynamic, behind &lt;span class="caps"&gt;CGNAT&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Tailscale (free tier)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Family homelab, non-technical users, multiple device types&lt;/td&gt;
&lt;td&gt;Tailscale (free tier handles 3 users)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Privacy absolutist, want zero cloud dependency&lt;/td&gt;
&lt;td&gt;Headscale (self-hosted Tailscale)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Site-to-site link between two servers&lt;/td&gt;
&lt;td&gt;Kernel WireGuard&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Homelab + frequent service sharing with friends&lt;/td&gt;
&lt;td&gt;Tailscale with Funnel&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;My recommendation for most homelabbers in 2026:&lt;/strong&gt; Start with Tailscale&amp;#8217;s free tier. It takes five minutes, works through any &lt;span class="caps"&gt;NAT&lt;/span&gt;, and costs nothing for up to three users and 100 devices — which covers the vast majority of homelab setups. If you later outgrow the free tier or want to eliminate the cloud dependency, migrate to Headscale. Your devices will not notice the&amp;nbsp;difference.&lt;/p&gt;
&lt;p&gt;If you are already running Tailscale and want to extend your remote access capabilities, check out our &lt;a href="/2026/06/traefik-vs-nginx-proxy-manager-vs-caddy-homelab-2026/"&gt;Traefik vs Nginx Proxy Manager vs Caddy comparison&lt;/a&gt; — pairing a reverse proxy with your &lt;span class="caps"&gt;VPN&lt;/span&gt; gives you fine-grained routing control for every&amp;nbsp;service.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;&lt;span class="caps"&gt;FAQ&lt;/span&gt;: Tailscale vs WireGuard for&amp;nbsp;Homelab&lt;/h2&gt;
&lt;h3&gt;1. Is Tailscale free for homelab&amp;nbsp;use?&lt;/h3&gt;
&lt;p&gt;Yes. Tailscale&amp;#8217;s free tier includes up to 3 users and 100 devices, which covers virtually every homelab. The free tier includes MagicDNS, ACLs, exit nodes, and &lt;span class="caps"&gt;DERP&lt;/span&gt; relays. The only limitations are user count and administrative features like device approval policies and custom &lt;span class="caps"&gt;OIDC&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;2. Does Tailscale slow down my&amp;nbsp;connection?&lt;/h3&gt;
&lt;p&gt;Minimally. Tailscale uses userspace WireGuard&amp;nbsp;(&lt;code&gt;wireguard-go&lt;/code&gt;) which adds 5–10% overhead compared to kernel WireGuard on the same hardware. For a typical homelab internet connection (20–100 Mbps upstream), this overhead is invisible. The bottleneck is your &lt;span class="caps"&gt;ISP&lt;/span&gt;, not Tailscale. Latency overhead is 1–3 ms for direct connections, higher only when traffic routes through &lt;span class="caps"&gt;DERP&lt;/span&gt;&amp;nbsp;relays.&lt;/p&gt;
&lt;h3&gt;3. Can I use Tailscale without their coordination&amp;nbsp;server?&lt;/h3&gt;
&lt;p&gt;Yes — that is exactly what Headscale does. Headscale is an open-source reimplementation of Tailscale&amp;#8217;s control server. You self-host it and point your Tailscale clients at your own server&amp;nbsp;with &lt;code&gt;tailscale up --login-server https://headscale.yourdomain.com&lt;/code&gt;. The Tailscale clients are open source and support alternative coordination servers&amp;nbsp;natively.&lt;/p&gt;
&lt;h3&gt;4. What happens if Tailscale&amp;#8217;s servers go&amp;nbsp;down?&lt;/h3&gt;
&lt;p&gt;Existing peer-to-peer connections continue working — the data plane is WireGuard, and WireGuard tunnels survive coordination server outages. You cannot add new devices, rotate keys, or fetch &lt;span class="caps"&gt;ACL&lt;/span&gt; updates until the server recovers. If this risk is unacceptable, run Headscale on your own&amp;nbsp;infrastructure.&lt;/p&gt;
&lt;h3&gt;5. Can I run both WireGuard and Tailscale on the same&amp;nbsp;machine?&lt;/h3&gt;
&lt;p&gt;Technically yes — they use different interfaces&amp;nbsp;(&lt;code&gt;wg0&lt;/code&gt; vs &lt;code&gt;tailscale0&lt;/code&gt;). But routing conflicts are likely if both try to manage the same subnets. Choose one as your primary &lt;span class="caps"&gt;VPN&lt;/span&gt;. If you need both (e.g., WireGuard for a site-to-site link and Tailscale for client access), assign them non-overlapping &lt;span class="caps"&gt;IP&lt;/span&gt;&amp;nbsp;ranges.&lt;/p&gt;
&lt;h3&gt;6. How does Tailscale handle my homelab &lt;span class="caps"&gt;DNS&lt;/span&gt;?&lt;/h3&gt;
&lt;p&gt;Tailscale&amp;#8217;s MagicDNS assigns every device a&amp;nbsp;stable &lt;code&gt;&amp;lt;hostname&amp;gt;.ts-net.ts.net&lt;/code&gt; name. If you enable &amp;#8220;Override local &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;#8221; in the Tailscale admin console, you can also&amp;nbsp;point &lt;code&gt;*.ts-net.ts.net&lt;/code&gt; queries at your homelab &lt;span class="caps"&gt;DNS&lt;/span&gt; server (e.g., Pi-hole or AdGuard Home). Combined with subnet routing, this lets you resolve &lt;span class="caps"&gt;LAN&lt;/span&gt; hostnames from&amp;nbsp;anywhere.&lt;/p&gt;
&lt;h3&gt;7. Is WireGuard more secure than Tailscale since there is no third&amp;nbsp;party?&lt;/h3&gt;
&lt;p&gt;WireGuard has a smaller trust boundary — no coordination server means one fewer thing to compromise. But Tailscale&amp;#8217;s end-to-end encryption means the coordination server never sees your traffic. The risk is account compromise (attacker adds a device to your tailnet), which Tailscale mitigates with device approval, ACLs, and &lt;span class="caps"&gt;MFA&lt;/span&gt; on your &lt;span class="caps"&gt;SSO&lt;/span&gt; provider. For most users, the practical security of Tailscale&amp;#8217;s ACLs (which people actually configure) outweighs the theoretical security of WireGuard&amp;#8217;s minimalism (where iptables rules often go&amp;nbsp;unwritten).&lt;/p&gt;
&lt;h3&gt;8. What about Tailscale Funnel vs Cloudflare&amp;nbsp;Tunnel?&lt;/h3&gt;
&lt;p&gt;Both expose services to the public internet without port forwarding. Tailscale Funnel is simpler (one&amp;nbsp;command: &lt;code&gt;tailscale funnel 8080&lt;/code&gt;) but routes through Tailscale&amp;#8217;s ingress servers and has bandwidth limits. &lt;span class="sp-brand cloudflare"&gt;Cloudflare&lt;/span&gt; Tunnel is more feature-rich (&lt;span class="caps"&gt;WAF&lt;/span&gt;, caching, custom domains) and has no bandwidth limits on the free tier. For robust public exposure, Cloudflare Tunnel wins. For quick, temporary sharing, Tailscale Funnel is more convenient. See our &lt;a href="/2026/06/cloudflare-tunnel-homelab/"&gt;Cloudflare Tunnel Homelab Guide&lt;/a&gt; for a full&amp;nbsp;comparison.&lt;/p&gt;
&lt;h3&gt;9. Can I run Tailscale on a Raspberry&amp;nbsp;Pi?&lt;/h3&gt;
&lt;p&gt;Yes. Tailscale provides &lt;span class="caps"&gt;ARM&lt;/span&gt; and &lt;span class="caps"&gt;ARM64&lt;/span&gt; binaries. A &lt;span class="sp-brand raspberrypi"&gt;Raspberry Pi&lt;/span&gt; 4 or 5 running as a subnet router and exit node is a common homelab pattern — it uses under 5W and gives you remote access to your entire &lt;span class="caps"&gt;LAN&lt;/span&gt; without running a full server. See our &lt;a href="/2026/06/raspberry-pi-5-proxmox-cluster-2026/"&gt;Raspberry Pi 5 Proxmox Cluster guide&lt;/a&gt; for &lt;span class="caps"&gt;ARM&lt;/span&gt; homelab&amp;nbsp;ideas.&lt;/p&gt;
&lt;h3&gt;10. How do I secure WireGuard if I choose the vanilla&amp;nbsp;route?&lt;/h3&gt;
&lt;p&gt;Use &lt;code&gt;wg-quick&lt;/code&gt; for interface management, enable the firewall&amp;nbsp;with &lt;code&gt;iptables&lt;/code&gt; rules that only allow WireGuard traffic on the listening port,&amp;nbsp;use &lt;code&gt;PersistentKeepalive = 25&lt;/code&gt; for &lt;span class="caps"&gt;NAT&lt;/span&gt;&amp;#8217;d peers, and rotate keys every 90 days. Consider running &lt;span class="caps"&gt;WG&lt;/span&gt;-Easy for a web-based management interface. Most importantly: document which public key belongs to which device — you will thank yourself when you need to revoke access six months from&amp;nbsp;now.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Want&amp;nbsp;More?&lt;/h2&gt;
&lt;p&gt;If you found this guide useful, here are the next articles we&amp;nbsp;recommend:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="/2026/06/cloudflare-tunnel-homelab/"&gt;Cloudflare Tunnel Homelab Guide&lt;/a&gt;&lt;/strong&gt; — Expose services without port forwarding using Cloudflare&amp;#8217;s free tunnel&amp;nbsp;service&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="/2026/06/dockflare-vs-manual-tunnels/"&gt;DockFlare vs Manual Cloudflare Tunnels&lt;/a&gt;&lt;/strong&gt; — Automate tunnel configuration with Docker&amp;nbsp;labels&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="/2026/06/docker-networking-best-practices/"&gt;Docker Networking Best Practices&lt;/a&gt;&lt;/strong&gt; — Design container networks that don&amp;#8217;t&amp;nbsp;rot&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="/2026/06/self-hosted-backup-strategy-homelab-2026/"&gt;Self-Hosted Backup Strategy for Homelab 2026&lt;/a&gt;&lt;/strong&gt; — Protect your data with the 3-2-1 rule using Restic, Kopia, and&amp;nbsp;Duplicati&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="/2026/06/traefik-vs-nginx-proxy-manager-vs-caddy-homelab-2026/"&gt;Traefik vs Nginx Proxy Manager vs Caddy for Homelab 2026&lt;/a&gt;&lt;/strong&gt; — Choose the right reverse proxy for your&amp;nbsp;stack&lt;/li&gt;
&lt;/ul&gt;</content><category term="Guides"/><category term="tailscale"/><category term="wireguard"/><category term="vpn"/><category term="homelab networking"/><category term="remote access"/><category term="mesh vpn"/><category term="self-hosted"/><category term="security"/><category term="nat traversal"/><category term="wireguard-ui"/></entry><entry><title>DockFlare vs Manual Cloudflare Tunnels: Automate Your Homelab Ingress with Docker Labels (2026)</title><link href="https://steadypub.com/2026/06/dockflare-vs-manual-tunnels/" rel="alternate"/><published>2026-06-11T00:00:00+07:00</published><updated>2026-06-11T00:00:00+07:00</updated><author><name>WordForge Team</name></author><id>tag:steadypub.com,2026-06-11:/2026/06/dockflare-vs-manual-tunnels/</id><summary type="html">&lt;p&gt;Compare DockFlare&amp;#8217;s label-based automation against manual Cloudflare Tunnel configuration. Docker Compose examples for both approaches, decision framework for homelab scale, and best practices for secure tunnel management in&amp;nbsp;2026.&lt;/p&gt;</summary><content type="html">&lt;hr&gt;
&lt;h1&gt;DockFlare vs Manual Cloudflare Tunnels: Automate Your Homelab Ingress with Docker Labels&amp;nbsp;(2026)&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~12 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab owners running Docker who use (or plan to use) Cloudflare Tunnel and want to stop manually editing &lt;span class="caps"&gt;YAML&lt;/span&gt; files every time they spin up a new&amp;nbsp;service&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Introduction: The Tunnel Configuration&amp;nbsp;Bottleneck&lt;/h2&gt;
&lt;p&gt;Cloudflare Tunnel is one of the most transformative tools in the homelab ecosystem. It eliminates port forwarding, defeats &lt;span class="caps"&gt;CGNAT&lt;/span&gt;, and wraps every service in free &lt;span class="caps"&gt;SSL&lt;/span&gt; — all without exposing your home &lt;span class="caps"&gt;IP&lt;/span&gt; address. We covered the full setup in our &lt;a href="/cloudflare-tunnel-homelab/"&gt;Cloudflare Tunnel Homelab Guide&lt;/a&gt;, and thousands of homelabbers have since adopted it as their primary ingress&amp;nbsp;solution.&lt;/p&gt;
&lt;p&gt;But there is a problem that emerges about three weeks in. You have tunneled your first service — say, Home Assistant. Then you add Jellyfin. Then Immich. Then Uptime Kuma. Each new service means opening&amp;nbsp;your &lt;code&gt;config.yml&lt;/code&gt;, adding&amp;nbsp;an &lt;code&gt;ingress&lt;/code&gt; block with the correct hostname and service &lt;span class="caps"&gt;URL&lt;/span&gt;, and&amp;nbsp;restarting &lt;code&gt;cloudflared&lt;/code&gt;. Your &lt;span class="caps"&gt;YAML&lt;/span&gt; file grows. Your memory of which services are tunneled grows stale. Configuration drift sets in: you decommissioned that Plex container two months ago, but its tunnel rule is still sitting there, pointing at&amp;nbsp;nothing.&lt;/p&gt;
&lt;p&gt;This is the problem that &lt;strong&gt;DockFlare&lt;/strong&gt; solves. Instead of maintaining tunnel configuration in a separate &lt;span class="caps"&gt;YAML&lt;/span&gt; file, DockFlare reads Docker labels directly from your containers and synchronizes them with Cloudflare&amp;#8217;s &lt;span class="caps"&gt;API&lt;/span&gt; automatically. You define ingress rules where the service lives — in your Docker Compose file — and DockFlare handles the&amp;nbsp;rest.&lt;/p&gt;
&lt;p&gt;In this guide, we compare both approaches head-to-head with real Docker Compose examples, a decision framework based on your homelab&amp;#8217;s scale, and the trade-offs you need to understand before&amp;nbsp;migrating.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is&amp;nbsp;DockFlare?&lt;/h2&gt;
&lt;p&gt;DockFlare is an open-source Docker container that acts as a bridge between your Docker host and the Cloudflare &lt;span class="caps"&gt;API&lt;/span&gt;. It watches Docker events in real time and translates container labels into Cloudflare Tunnel ingress&amp;nbsp;rules.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Here is what it does under the&amp;nbsp;hood:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;You deploy DockFlare alongside your other containers, mounting the Docker&amp;nbsp;socket.&lt;/li&gt;
&lt;li&gt;You add labels&amp;nbsp;like &lt;code&gt;dockflare.domain=app.yourdomain.com&lt;/code&gt; and &lt;code&gt;dockflare.port=8080&lt;/code&gt; to any service you want to&amp;nbsp;expose.&lt;/li&gt;
&lt;li&gt;DockFlare detects the label, authenticates to the Cloudflare &lt;span class="caps"&gt;API&lt;/span&gt; using a tunnel token, and creates or updates the ingress&amp;nbsp;rule.&lt;/li&gt;
&lt;li&gt;When you stop the container, DockFlare removes the rule. No orphaned tunnel&amp;nbsp;entries.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The mental model shift is significant: instead of managing tunnels in a separate configuration file that lives outside your service definition, you manage ingress &lt;strong&gt;at the service level&lt;/strong&gt;. The Docker Compose file that defines your application also defines how the outside world reaches&amp;nbsp;it.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Comparison Matrix: DockFlare vs Manual Cloudflare&amp;nbsp;Tunnel&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Manual Cloudflare Tunnel&amp;nbsp;(&lt;code&gt;cloudflared&lt;/code&gt;)&lt;/th&gt;
&lt;th&gt;DockFlare&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Configuration location&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/.cloudflared/config.yml&lt;/code&gt; (separate file)&lt;/td&gt;
&lt;td&gt;Docker labels inside each&amp;nbsp;service&amp;#8217;s &lt;code&gt;docker-compose.yml&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Adding a new service&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Edit &lt;span class="caps"&gt;YAML&lt;/span&gt; →&amp;nbsp;add &lt;code&gt;ingress&lt;/code&gt; block →&amp;nbsp;restart &lt;code&gt;cloudflared&lt;/code&gt; container&lt;/td&gt;
&lt;td&gt;Add 2 Docker labels&amp;nbsp;→ &lt;code&gt;docker compose up -d&lt;/code&gt; → done&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Removing a service&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Edit &lt;span class="caps"&gt;YAML&lt;/span&gt; →&amp;nbsp;remove &lt;code&gt;ingress&lt;/code&gt; block →&amp;nbsp;restart &lt;code&gt;cloudflared&lt;/code&gt; container&lt;/td&gt;
&lt;td&gt;&lt;code&gt;docker compose down&lt;/code&gt; → DockFlare removes rule automatically&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Configuration drift risk&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High — manual sync required between running containers and tunnel config&lt;/td&gt;
&lt;td&gt;None — labels are the source of truth, auto-synced&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Learning curve&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Low — one config file, well-documented&lt;/td&gt;
&lt;td&gt;Moderate — must understand Docker labels and DockFlare&amp;#8217;s label schema&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Multi-host support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Deploy &lt;code&gt;cloudflared&lt;/code&gt; on each host, manage per-host configs&lt;/td&gt;
&lt;td&gt;One DockFlare per Docker host (or use Docker Swarm mode)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dependency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Only &lt;code&gt;cloudflared&lt;/code&gt; binary&lt;/td&gt;
&lt;td&gt;Docker socket + Cloudflare &lt;span class="caps"&gt;API&lt;/span&gt; access + DockFlare container&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Failure mode&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Tunnel config stays static; services become unreachable if IPs change&lt;/td&gt;
&lt;td&gt;If DockFlare goes down, existing tunnels persist; new services won&amp;#8217;t be tunneled until it recovers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;GUI&lt;/span&gt; management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cloudflare Zero Trust dashboard (manual click-based)&lt;/td&gt;
&lt;td&gt;None — fully label-driven (infrastructure-as-code)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1–5 services, static homelab, users who prefer explicit control&lt;/td&gt;
&lt;td&gt;6+ services, frequent additions/removals, Docker Compose-first workflows&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Approach 1: Manual Cloudflare Tunnel&amp;nbsp;with &lt;code&gt;cloudflared&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;This is the traditional approach. You deploy&amp;nbsp;the &lt;code&gt;cloudflared&lt;/code&gt; container, mount a persistent config directory, and define every ingress rule by&amp;nbsp;hand.&lt;/p&gt;
&lt;h3&gt;Docker&amp;nbsp;Compose&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# docker-compose.yml — manual cloudflared&lt;/span&gt;
&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;
&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;cloudflared&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;cloudflare/cloudflared:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;cloudflared&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;tunnel run&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./cloudflared-config:/home/nonroot/.cloudflared&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;proxy&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Config File&amp;nbsp;(&lt;code&gt;config.yml&lt;/code&gt;)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# ./cloudflared-config/config.yml&lt;/span&gt;
&lt;span class="nt"&gt;tunnel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;YOUR_TUNNEL_ID&lt;/span&gt;
&lt;span class="nt"&gt;credentials-file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/home/nonroot/.cloudflared/YOUR_TUNNEL_ID.json&lt;/span&gt;

&lt;span class="nt"&gt;ingress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Home Assistant&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ha.yourdomain.com&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;http://homeassistant:8123&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Jellyfin&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;media.yourdomain.com&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;http://jellyfin:8096&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Uptime Kuma&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;status.yourdomain.com&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;http://uptime-kuma:3001&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Immich&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;photos.yourdomain.com&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;http://immich-server:3000&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Catch-all: 404 for unmatched hostnames&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;http_status:404&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Adding a New Service (Manual&amp;nbsp;Workflow)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# 1. Edit config.yml and add a new ingress block&lt;/span&gt;
vim&lt;span class="w"&gt; &lt;/span&gt;./cloudflared-config/config.yml

&lt;span class="c1"&gt;# 2. Restart cloudflared to pick up the change&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;restart&lt;span class="w"&gt; &lt;/span&gt;cloudflared

&lt;span class="c1"&gt;# 3. Verify the tunnel is healthy&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;logs&lt;span class="w"&gt; &lt;/span&gt;cloudflared&lt;span class="w"&gt; &lt;/span&gt;--tail&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;20&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This workflow works. It is battle-tested and thoroughly documented. But at 5 services, the config file is manageable. At 15 services — with some pointing at containers that were renamed, moved to a different Docker network, or decommissioned entirely — it becomes a&amp;nbsp;liability.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Approach 2: DockFlare — Label-Driven Tunnel&amp;nbsp;Automation&lt;/h2&gt;
&lt;p&gt;DockFlare replaces the&amp;nbsp;manual &lt;code&gt;config.yml&lt;/code&gt; with Docker labels. You deploy DockFlare once, then add labels to any service you want to&amp;nbsp;expose.&lt;/p&gt;
&lt;h3&gt;DockFlare Docker&amp;nbsp;Compose&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# dockflare-stack.yml&lt;/span&gt;
&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;
&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;dockflare&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ghcr.io/truecharts/dockflare:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;dockflare&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;CLOUDFLARE_TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;DOCKFLARE_WATCH_INTERVAL=30&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;DOCKFLARE_LOG_LEVEL=info&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/var/run/docker.sock:/var/run/docker.sock:ro&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;proxy&lt;/span&gt;

&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;external&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Service with DockFlare&amp;nbsp;Labels&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Example service — Home Assistant with DockFlare labels&lt;/span&gt;
&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;homeassistant&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ghcr.io/home-assistant/home-assistant:stable&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;homeassistant&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./ha-config:/config&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TZ=Asia/Jakarta&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;proxy&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;dockflare.domain=ha.yourdomain.com&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;dockflare.port=8123&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;dockflare.protocol=http&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That is the entire workflow. Add the labels,&amp;nbsp;run &lt;code&gt;docker compose up -d&lt;/code&gt;, and DockFlare detects the new container within its watch interval (30 seconds by default). The ingress rule appears in your Cloudflare Zero Trust dashboard and traffic starts&amp;nbsp;flowing.&lt;/p&gt;
&lt;h3&gt;Removing a&amp;nbsp;Service&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;down
&lt;span class="c1"&gt;# DockFlare detects the container stopped and removes the ingress rule automatically.&lt;/span&gt;
&lt;span class="c1"&gt;# No config file cleanup. No restart needed.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Decision Framework: Which One Should You&amp;nbsp;Use?&lt;/h2&gt;
&lt;p&gt;Answer these questions to determine which approach fits your&amp;nbsp;homelab:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;How many services do you expose through Cloudflare Tunnel?&lt;/strong&gt; If the answer is 5 or fewer,&amp;nbsp;manual &lt;code&gt;cloudflared&lt;/code&gt; configuration is simple enough that DockFlare&amp;#8217;s additional complexity may not be worth it. At 6+ services, the automation benefit compounds with every new&amp;nbsp;container.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;How often do you add or remove services?&lt;/strong&gt; If your homelab is static — the same ten services running for months — manual config works fine. If you experiment frequently, spin up temporary services, or run a &lt;span class="caps"&gt;CI&lt;/span&gt;/&lt;span class="caps"&gt;CD&lt;/span&gt; pipeline that deploys containers, DockFlare&amp;#8217;s automatic cleanup prevents configuration&amp;nbsp;rot.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Do you already manage everything through Docker Compose?&lt;/strong&gt; DockFlare fits naturally into a Compose-first workflow where every aspect of a service — ports, volumes, networks, and now ingress — lives in one file. If you use Portainer or a &lt;span class="caps"&gt;GUI&lt;/span&gt; to manage containers, DockFlare&amp;#8217;s label approach still works but requires accessing the label editor for each&amp;nbsp;container.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Do you need multi-host tunnel support?&lt;/strong&gt; DockFlare runs per-Docker-host. If you have three Proxmox nodes each running Docker, you need three DockFlare instances (or one if you use Docker Swarm and constrain it to a manager node).&amp;nbsp;Manual &lt;code&gt;cloudflared&lt;/code&gt; per host is equally straightforward in this&amp;nbsp;scenario.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;How comfortable are you with Docker labels?&lt;/strong&gt; DockFlare adds a dependency on label-based configuration. If Docker labels are already part of your workflow (for Traefik routing, for example), DockFlare slots in naturally. If you have never touched a Docker label, there is a small learning&amp;nbsp;curve.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Common Pitfalls and&amp;nbsp;Solutions&lt;/h2&gt;
&lt;h3&gt;Pitfall 1: DockFlare Cannot Reach the Cloudflare &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; DockFlare starts but no ingress rules appear. Logs&amp;nbsp;show &lt;code&gt;401 Unauthorized&lt;/code&gt; or &lt;code&gt;connection refused&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Verify your tunnel token has the correct permissions. The token must be scoped to the specific tunnel, not the account-wide &lt;span class="caps"&gt;API&lt;/span&gt; token. Generate it from &lt;strong&gt;Cloudflare Zero Trust → Networks → Tunnels → [Your Tunnel] → Configure → Credentials&lt;/strong&gt;. Do not reuse the Global &lt;span class="caps"&gt;API&lt;/span&gt; Key — it has more permissions than DockFlare needs and is a security risk if the environment variable&amp;nbsp;leaks.&lt;/p&gt;
&lt;h3&gt;Pitfall 2: Container on Wrong Docker&amp;nbsp;Network&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; DockFlare creates the ingress rule, but traffic&amp;nbsp;returns &lt;code&gt;502 Bad Gateway&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; DockFlare routes traffic using Docker&amp;#8217;s internal &lt;span class="caps"&gt;DNS&lt;/span&gt;. The target container must be on the &lt;strong&gt;same Docker network&lt;/strong&gt; as DockFlare, or on a network that DockFlare can reach. The simplest setup: create a&amp;nbsp;dedicated &lt;code&gt;proxy&lt;/code&gt; network and attach both DockFlare and every tunneled service to&amp;nbsp;it.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;network&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;proxy
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then&amp;nbsp;add &lt;code&gt;networks: - proxy&lt;/code&gt; to both DockFlare and every service&amp;nbsp;with &lt;code&gt;dockflare.*&lt;/code&gt; labels.&lt;/p&gt;
&lt;h3&gt;Pitfall 3: Stale Ingress Rules After Container&amp;nbsp;Removal&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; You stopped a container, but its ingress rule is still in Cloudflare Zero Trust. DockFlare did not clean it&amp;nbsp;up.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; DockFlare cleans up rules for containers that are &lt;strong&gt;stopped or removed&lt;/strong&gt;, not containers that are simply unreachable. If you removed the container outside of Docker Compose&amp;nbsp;(e.g., &lt;code&gt;docker rm&lt;/code&gt; without &lt;code&gt;docker compose down&lt;/code&gt;), DockFlare may not detect the removal event.&amp;nbsp;Use &lt;code&gt;docker compose down&lt;/code&gt; for proper lifecycle management. If you still have orphaned rules, remove them manually from the Cloudflare dashboard — DockFlare will not overwrite rules it did not&amp;nbsp;create.&lt;/p&gt;
&lt;h3&gt;Pitfall 4: Token Exposure in Plain-Text Compose&amp;nbsp;Files&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; You committed&amp;nbsp;your &lt;code&gt;docker-compose.yml&lt;/code&gt; to a Git repository with the tunnel token&amp;nbsp;hardcoded.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Never hardcode secrets. Use&amp;nbsp;an &lt;code&gt;.env&lt;/code&gt; file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# .env (gitignored)&lt;/span&gt;
&lt;span class="nv"&gt;CLOUDFLARE_TUNNEL_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;eyJ...your-token-here
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# docker-compose.yml (safe to commit)&lt;/span&gt;
&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;CLOUDFLARE_TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Add &lt;code&gt;.env&lt;/code&gt; to&amp;nbsp;your &lt;code&gt;.gitignore&lt;/code&gt;. For additional security, consider Docker secrets if you run Docker Swarm, or HashiCorp Vault if you already have it in your stack (see our &lt;a href="/self-hosted-password-manager-comparison/"&gt;self-hosted password manager comparison&lt;/a&gt; for a lighter-weight secrets management&amp;nbsp;approach).&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Integration with Reverse&amp;nbsp;Proxies&lt;/h2&gt;
&lt;p&gt;DockFlare and manual Cloudflare Tunnels both work alongside reverse proxies. The pattern depends on your&amp;nbsp;architecture:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Architecture&lt;/th&gt;
&lt;th&gt;How It Works&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tunnel → Service (Direct)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cloudflare Tunnel points directly at each container&amp;#8217;s port. No reverse proxy involved.&lt;/td&gt;
&lt;td&gt;Fewer than 5 services, simple setups&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tunnel → Nginx Proxy Manager → Services&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Tunnel points at &lt;span class="caps"&gt;NPM&lt;/span&gt; on port 80/443. &lt;span class="caps"&gt;NPM&lt;/span&gt; routes by hostname to backend containers.&lt;/td&gt;
&lt;td&gt;Users who want a &lt;span class="caps"&gt;GUI&lt;/span&gt; for proxy host management&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tunnel → Traefik → Services&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Tunnel points at Traefik. Traefik uses Docker labels to route to backends.&lt;/td&gt;
&lt;td&gt;Docker-native, label-driven workflows — pairs naturally with DockFlare&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;strong&gt;Tunnel → &lt;span class="caps"&gt;NPM&lt;/span&gt; → Services&lt;/strong&gt; pattern is the most popular in the WordForge community. Cloudflare Tunnel provides the secure ingress from the internet. Nginx Proxy Manager handles &lt;span class="caps"&gt;SSL&lt;/span&gt; termination (though it is technically double-encrypted — Cloudflare edge + &lt;span class="caps"&gt;NPM&lt;/span&gt;), hostname routing, and access lists. Each backend container only needs to be on the Docker network, with no port exposure to the&amp;nbsp;host.&lt;/p&gt;
&lt;p&gt;For a full walkthrough of this pattern, see our &lt;a href="/cloudflare-tunnel-homelab/"&gt;Cloudflare Tunnel Homelab Guide&lt;/a&gt; and &lt;a href="/nginx-proxy-manager-docker-compose/"&gt;Nginx Proxy Manager Docker Compose&lt;/a&gt;&amp;nbsp;articles.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Already running Traefik?&lt;/strong&gt; Our &lt;a href="/traefik-vs-nginx-proxy-manager-vs-caddy-homelab-2026/"&gt;reverse proxy comparison guide&lt;/a&gt; includes a section on Traefik + Cloudflare Tunnel integration with middleware&amp;nbsp;chains.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;Security&amp;nbsp;Considerations&lt;/h2&gt;
&lt;p&gt;Whether you use DockFlare or&amp;nbsp;manual &lt;code&gt;cloudflared&lt;/code&gt;, the security model is the same: Cloudflare sits between the internet and your homelab, and the tunnel is an outbound-only encrypted connection. Neither approach opens ports on your router. Both benefit from Cloudflare&amp;#8217;s DDoS protection at the free&amp;nbsp;tier.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;However, DockFlare introduces a new attack surface:&lt;/strong&gt; the Docker socket.&amp;nbsp;Mounting &lt;code&gt;/var/run/docker.sock&lt;/code&gt; into any container gives that container root-equivalent access to your Docker host. DockFlare needs read-only access&amp;nbsp;(&lt;code&gt;:ro&lt;/code&gt;) to list containers and read labels. It does not need write&amp;nbsp;access.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mitigations:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Always mount the Docker socket as&amp;nbsp;read-only:&lt;/strong&gt; &lt;code&gt;- /var/run/docker.sock:/var/run/docker.sock:ro&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use a dedicated tunnel token&lt;/strong&gt; scoped only to the specific tunnel, not an account-wide &lt;span class="caps"&gt;API&lt;/span&gt;&amp;nbsp;token.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Monitor DockFlare logs&lt;/strong&gt; for unexpected &lt;span class="caps"&gt;API&lt;/span&gt; calls. DockFlare should only call Cloudflare&amp;#8217;s tunnel ingress &lt;span class="caps"&gt;API&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Keep DockFlare updated.&lt;/strong&gt; Subscribe to the &lt;a href="https://github.com/truecharts/dockflare"&gt;DockFlare GitHub releases&lt;/a&gt; for security&amp;nbsp;patches.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Consider &lt;code&gt;docker-socket-proxy&lt;/code&gt;&lt;/strong&gt; as an alternative to direct socket mounting. It exposes a filtered subset of the Docker &lt;span class="caps"&gt;API&lt;/span&gt; over &lt;span class="caps"&gt;HTTP&lt;/span&gt;, limiting what DockFlare can do. This adds complexity but reduces the blast radius of a compromised&amp;nbsp;container.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;&lt;span class="caps"&gt;FAQ&lt;/span&gt;&lt;/h2&gt;
&lt;h3&gt;Does DockFlare&amp;nbsp;replace &lt;code&gt;cloudflared&lt;/code&gt; entirely?&lt;/h3&gt;
&lt;p&gt;No — DockFlare manages tunnel &lt;strong&gt;ingress rules&lt;/strong&gt; (which hostname routes to which service). The actual tunnel connection between your homelab and Cloudflare&amp;#8217;s edge is still handled by Cloudflare&amp;#8217;s infrastructure. DockFlare communicates with the Cloudflare &lt;span class="caps"&gt;API&lt;/span&gt; to update the ingress configuration. You do not need to run a&amp;nbsp;separate &lt;code&gt;cloudflared&lt;/code&gt; container alongside DockFlare — DockFlare handles the &lt;span class="caps"&gt;API&lt;/span&gt;-side&amp;nbsp;management.&lt;/p&gt;
&lt;h3&gt;Can I use both DockFlare and&amp;nbsp;manual &lt;code&gt;cloudflared&lt;/code&gt; at the same&amp;nbsp;time?&lt;/h3&gt;
&lt;p&gt;Technically yes, but it creates confusion about which system owns which ingress rules. DockFlare only manages rules for containers&amp;nbsp;with &lt;code&gt;dockflare.*&lt;/code&gt; labels. Rules defined manually&amp;nbsp;in &lt;code&gt;config.yml&lt;/code&gt; are invisible to DockFlare and vice versa. If you are migrating from manual to DockFlare, run DockFlare alongside your existing setup for a week, then decommission the&amp;nbsp;manual &lt;code&gt;cloudflared&lt;/code&gt; container once you have verified all services are reachable through DockFlare-managed&amp;nbsp;rules.&lt;/p&gt;
&lt;h3&gt;What happens if DockFlare&amp;nbsp;crashes?&lt;/h3&gt;
&lt;p&gt;Your tunnel remains operational. Cloudflare Tunnel ingress rules are stored on Cloudflare&amp;#8217;s side, not inside DockFlare. If DockFlare goes down, existing tunnels continue routing traffic. You only lose the ability to add or remove ingress rules until DockFlare recovers. This is a graceful degradation — your services stay&amp;nbsp;online.&lt;/p&gt;
&lt;h3&gt;Does DockFlare support multiple&amp;nbsp;tunnels?&lt;/h3&gt;
&lt;p&gt;Yes — you can run multiple DockFlare instances with different tunnel tokens. This is useful if you want to segregate services across different Cloudflare tunnels (e.g., one tunnel for public-facing services, another for admin-only dashboards). Each instance watches all containers on the host but only manages rules for containers whose labels match its configured&amp;nbsp;tunnel.&lt;/p&gt;
&lt;h3&gt;How does DockFlare compare to Traefik&amp;#8217;s Cloudflare&amp;nbsp;integration?&lt;/h3&gt;
&lt;p&gt;They solve different problems. Traefik is a reverse proxy — it terminates &lt;span class="caps"&gt;HTTP&lt;/span&gt; connections and routes them to backends. DockFlare manages Cloudflare Tunnel ingress rules — it tells Cloudflare &amp;#8220;send traffic&amp;nbsp;for &lt;code&gt;app.example.com&lt;/code&gt; to this internal service.&amp;#8221; If you use Traefik, your tunnel points at Traefik, and Traefik routes to backends. If you use DockFlare without a reverse proxy, the tunnel points directly at each container. The two tools can coexist: DockFlare creates the tunnel ingress rule pointing at Traefik, and Traefik handles internal&amp;nbsp;routing.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The Bottom&amp;nbsp;Line&lt;/h2&gt;
&lt;p&gt;Manual Cloudflare Tunnel configuration&amp;nbsp;with &lt;code&gt;cloudflared&lt;/code&gt; is the right choice for homelabs with 1–5 static services. It is simpler, has fewer moving parts, and the Cloudflare documentation covers every edge case. You edit one &lt;span class="caps"&gt;YAML&lt;/span&gt; file, restart one container, and you are&amp;nbsp;done.&lt;/p&gt;
&lt;p&gt;DockFlare becomes the better choice once your homelab crosses the ~6-service threshold, or if you add and remove services frequently. The label-based approach eliminates configuration drift — your Docker Compose files become the single source of truth for both service definition and ingress rules. Services that are removed clean up after themselves. Services that are added come online without touching a separate config&amp;nbsp;file.&lt;/p&gt;
&lt;p&gt;Both approaches give you the same end result: secure, &lt;span class="caps"&gt;SSL&lt;/span&gt;-protected access to your self-hosted services from anywhere in the world, without opening a single port on your router. Pick the one that matches your homelab&amp;#8217;s&amp;nbsp;complexity.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Want more?&lt;/strong&gt; If you are building out your homelab ingress stack, these guides take you from zero to&amp;nbsp;production:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/cloudflare-tunnel-homelab/"&gt;Cloudflare Tunnel Homelab Guide&lt;/a&gt; — The complete walkthrough from domain setup to Zero Trust access&amp;nbsp;policies&lt;/li&gt;
&lt;li&gt;&lt;a href="/nginx-proxy-manager-docker-compose/"&gt;Nginx Proxy Manager Docker Compose&lt;/a&gt; — &lt;span class="caps"&gt;GUI&lt;/span&gt;-based reverse proxy in 15&amp;nbsp;minutes&lt;/li&gt;
&lt;li&gt;&lt;a href="/traefik-vs-nginx-proxy-manager-vs-caddy-homelab-2026/"&gt;Traefik vs &lt;span class="caps"&gt;NPM&lt;/span&gt; vs Caddy Comparison&lt;/a&gt; — Pick the right reverse proxy for your&amp;nbsp;scale&lt;/li&gt;
&lt;li&gt;&lt;a href="/docker-networking-best-practices/"&gt;Docker Networking Best Practices&lt;/a&gt; — Network segmentation, macvlan vs bridge, and proxy network&amp;nbsp;design&lt;/li&gt;
&lt;li&gt;&lt;a href="/self-hosted-backup-strategy-homelab-2026/"&gt;Self-Hosted Backup Strategy 2026&lt;/a&gt; — Back up your configs, labels, and tunnel credentials before disaster&amp;nbsp;strikes&lt;/li&gt;
&lt;/ul&gt;</content><category term="Guides"/><category term="cloudflare tunnel"/><category term="dockflare"/><category term="cloudflared"/><category term="docker"/><category term="docker-compose"/><category term="homelab networking"/><category term="reverse proxy"/><category term="zero trust"/><category term="ingress"/><category term="automation"/></entry><entry><title>The 2026 Homelab Automation Stack: n8n, Self-Hosted LLMs, and Intelligent Monitoring</title><link href="https://steadypub.com/2026/06/homelab-automation-stack-2026/" rel="alternate"/><published>2026-06-11T00:00:00+07:00</published><updated>2026-06-11T00:00:00+07:00</updated><author><name>WordForge Team</name></author><id>tag:steadypub.com,2026-06-11:/2026/06/homelab-automation-stack-2026/</id><summary type="html">&lt;p&gt;Build a 2026-grade homelab automation stack with n8n, Ollama, and Uptime Kuma. Event-driven workflows, &lt;span class="caps"&gt;AI&lt;/span&gt;-powered alerts, and zero-cloud dependencies — everything you need to stop babysitting your server and let it manage&amp;nbsp;itself.&lt;/p&gt;</summary><content type="html">&lt;hr&gt;
&lt;h1&gt;The 2026 Homelab Automation Stack: Moving Beyond Simple&amp;nbsp;Containers&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~18 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab owners running 10+ containers who want their infrastructure to respond to events automatically — with &lt;span class="caps"&gt;AI&lt;/span&gt;-powered intelligence, not just cron&amp;nbsp;jobs&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Introduction: Why &amp;#8220;Set and Forget&amp;#8221; Is No Longer&amp;nbsp;Enough&lt;/h2&gt;
&lt;p&gt;You deployed your first Docker container. Then ten more. You added &lt;span class="sp-brand proxmox"&gt;Proxmox&lt;/span&gt; as your hypervisor, &lt;span class="sp-brand nginx"&gt;Nginx Proxy Manager&lt;/span&gt; for reverse proxy, and a handful of monitoring dashboards. Everything works — until it doesn&amp;#8217;t. A disk fills up at 3 &lt;span class="caps"&gt;AM&lt;/span&gt;. A container crashes silently. A certificate expires. You discover these things when something breaks, not&amp;nbsp;before.&lt;/p&gt;
&lt;p&gt;The 2026 homelab has outgrown passive monitoring. Running a modern self-hosted stack means dozens of interconnected services, each with its own failure modes, update cadences, and resource requirements. Manual intervention doesn&amp;#8217;t scale. What scales is &lt;strong&gt;event-driven automation&lt;/strong&gt; — a system that detects anomalies, reasons about them, and acts without you reaching for an &lt;span class="caps"&gt;SSH&lt;/span&gt;&amp;nbsp;client.&lt;/p&gt;
&lt;p&gt;This guide assembles the three components that make that possible: &lt;strong&gt;n8n&lt;/strong&gt; for workflow orchestration, &lt;strong&gt;&lt;span class="sp-brand ollama"&gt;Ollama&lt;/span&gt;&lt;/strong&gt; for local &lt;span class="caps"&gt;AI&lt;/span&gt; intelligence, and &lt;strong&gt;Uptime Kuma&lt;/strong&gt; for event-driven observability. Together they form a stack that watches your infrastructure, thinks about what it sees, and fixes what it&amp;nbsp;can.&lt;/p&gt;
&lt;h3&gt;The 2026 Standard: Agentic&amp;nbsp;Infrastructure&lt;/h3&gt;
&lt;p&gt;The term &amp;#8220;agentic&amp;#8221; has become shorthand for systems that don&amp;#8217;t just report problems — they respond to them. In the homelab context, this&amp;nbsp;means:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Capability&lt;/th&gt;
&lt;th&gt;Pre-2026 Approach&lt;/th&gt;
&lt;th&gt;2026 Automation Stack&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Monitoring&lt;/td&gt;
&lt;td&gt;Dashboard you check manually&lt;/td&gt;
&lt;td&gt;Webhooks that trigger workflows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Alerting&lt;/td&gt;
&lt;td&gt;&amp;#8220;Service X is down&amp;#8221; email&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;AI&lt;/span&gt;-summarized alerts with probable cause&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Remediation&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;SSH&lt;/span&gt; in and restart manually&lt;/td&gt;
&lt;td&gt;n8n detects failure → restarts container → confirms recovery&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Log analysis&lt;/td&gt;
&lt;td&gt;grep through files when something breaks&lt;/td&gt;
&lt;td&gt;Ollama summarizes anomaly patterns from log streams&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Certificate renewal&lt;/td&gt;
&lt;td&gt;Cron job with email on failure&lt;/td&gt;
&lt;td&gt;n8n tracks expiry → triggers renewal → verifies → alerts only on failure&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;This isn&amp;#8217;t science fiction. Every piece is available today as open-source, self-hosted software — and this guide shows you how to wire them&amp;nbsp;together.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Defines a 2026 Automation&amp;nbsp;Stack?&lt;/h2&gt;
&lt;h3&gt;From Static Containers to Event-Driven&amp;nbsp;Systems&lt;/h3&gt;
&lt;p&gt;A traditional homelab runs containers defined in&amp;nbsp;a &lt;code&gt;docker-compose.yml&lt;/code&gt; file. They start, they serve, they (hopefully) stay running. This is &lt;strong&gt;static infrastructure&lt;/strong&gt; — it does what you told it to do when you&amp;nbsp;ran &lt;code&gt;docker compose up -d&lt;/code&gt;, and nothing&amp;nbsp;more.&lt;/p&gt;
&lt;p&gt;An event-driven system adds a layer that says: &lt;em&gt;when X happens, do Y&lt;/em&gt;. X could be a service going down, a disk hitting 90% utilization, a new &lt;span class="caps"&gt;CVE&lt;/span&gt; being published for one of your containers, or a backup job completing. Y could be sending a notification, restarting a container, running a cleanup script, or asking an &lt;span class="caps"&gt;LLM&lt;/span&gt; to summarize a log dump and suggest next&amp;nbsp;steps.&lt;/p&gt;
&lt;p&gt;The key architectural shift: your automation stack becomes a &lt;strong&gt;peer to your application stack&lt;/strong&gt;, not a bolt-on. It gets its own &lt;span class="sp-brand docker"&gt;Docker&lt;/span&gt; network, its own resource budget, and its own&amp;nbsp;persistence.&lt;/p&gt;
&lt;h3&gt;The Three Pillars: Orchestration, Intelligence,&amp;nbsp;Observability&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pillar&lt;/th&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;Without It&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Orchestration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;n8n&lt;/td&gt;
&lt;td&gt;Connects services, runs workflows, makes decisions&lt;/td&gt;
&lt;td&gt;Manual intervention for every incident&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Intelligence&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="sp-brand ollama"&gt;Ollama&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Summarizes, classifies, recommends&lt;/td&gt;
&lt;td&gt;Alerts are raw data dumps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Observability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Uptime Kuma&lt;/td&gt;
&lt;td&gt;Detects state changes, fires webhooks&lt;/td&gt;
&lt;td&gt;You don&amp;#8217;t know something broke until you check&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Each pillar feeds the others: Uptime Kuma detects a service outage → fires a webhook to n8n → n8n queries Ollama for log analysis → n8n sends a contextual alert to Discord or Matrix. When it works, you receive a message that says: &lt;em&gt;&amp;#8220;Jellyfin is down. Probable cause: transcode directory full (97%). Action taken: cleared transcode cache, restarted container. Confirmed&amp;nbsp;healthy.&amp;#8221;&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Pillar 1: Workflow Orchestration with&amp;nbsp;n8n&lt;/h2&gt;
&lt;h3&gt;Why n8n Beats Zapier and Make for&amp;nbsp;Homelabs&lt;/h3&gt;
&lt;p&gt;n8n is a fair-code workflow automation platform that you self-host. It connects to hundreds of services through native nodes, supports custom JavaScript and Python execution, and runs entirely on your hardware. For homelab use, three factors make it the clear choice over cloud&amp;nbsp;alternatives:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;n8n (Self-Hosted)&lt;/th&gt;
&lt;th&gt;Zapier&lt;/th&gt;
&lt;th&gt;Make (Integromat)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data residency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Your server&lt;/td&gt;
&lt;td&gt;Zapier&amp;#8217;s cloud&lt;/td&gt;
&lt;td&gt;Make&amp;#8217;s cloud&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Free (unlimited workflows)&lt;/td&gt;
&lt;td&gt;$30+/mo for multi-step&lt;/td&gt;
&lt;td&gt;$9+/mo with operation limits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;API&lt;/span&gt; call limits&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Only limited by your hardware&lt;/td&gt;
&lt;td&gt;Tiered by plan&lt;/td&gt;
&lt;td&gt;1,000–10,000 ops/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Community nodes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;400+ npm packages&lt;/td&gt;
&lt;td&gt;Limited built-in&lt;/td&gt;
&lt;td&gt;Limited built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Custom code&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;JavaScript + Python nodes&lt;/td&gt;
&lt;td&gt;Limited &lt;span class="caps"&gt;JS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;SSH&lt;/span&gt;/on-prem connections&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Native (runs on your &lt;span class="caps"&gt;LAN&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Offline operation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fully functional&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The on-prem nature is the killer feature for homelabs. n8n can reach services&amp;nbsp;on &lt;code&gt;192.168.x.x&lt;/code&gt; addresses, talk to your &lt;span class="sp-brand proxmox"&gt;Proxmox&lt;/span&gt; &lt;span class="caps"&gt;API&lt;/span&gt;, &lt;span class="caps"&gt;SSH&lt;/span&gt; into &lt;span class="caps"&gt;LXC&lt;/span&gt; containers, and read local files — none of which a cloud automation tool can do without exposing your&amp;nbsp;network.&lt;/p&gt;
&lt;h3&gt;Docker Compose Setup for&amp;nbsp;n8n&lt;/h3&gt;
&lt;p&gt;Create a dedicated directory for your automation stack and deploy n8n with PostgreSQL (recommended for production use) and Redis (for queue mode and&amp;nbsp;performance):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# docker-compose.yml — n8n Automation Core&lt;/span&gt;
&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;3.8&amp;#39;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# PostgreSQL — n8n&amp;#39;s database for workflow storage and execution state&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Without this, n8n uses SQLite which is fine for testing but&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# chokes on concurrent workflow executions&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;postgres&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;postgres:16-alpine&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;n8n-postgres&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;POSTGRES_USER=${POSTGRES_USER:-n8n}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;POSTGRES_PASSWORD=${POSTGRES_PASSWORD}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;POSTGRES_DB=${POSTGRES_DB:-n8n}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./postgres-data:/var/lib/postgresql/data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;healthcheck&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;CMD-SHELL&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;pg_isready&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-U&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;n8n&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;10s&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;5s&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;retries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;5&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;automation-net&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Redis — enables queue mode for n8n&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Without Redis, n8n processes workflows in-process. With Redis,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# you get separate workers, retry queues, and better concurrency&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis:7-alpine&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;n8n-redis&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis-server --appendonly yes&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./redis-data:/data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;healthcheck&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;CMD&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;redis-cli&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ping&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;10s&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;5s&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;retries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;5&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;automation-net&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# n8n — the workflow engine itself&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;n8n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;n8nio/n8n:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;n8n&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;5678:5678&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;N8N_HOST=${N8N_HOST:-n8n.yourdomain.com}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;N8N_PORT=5678&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;N8N_PROTOCOL=https&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;NODE_ENV=production&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Database — tells n8n to use PostgreSQL instead of SQLite&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;DB_TYPE=postgresdb&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;DB_POSTGRESDB_HOST=postgres&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;DB_POSTGRESDB_PORT=5432&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;DB_POSTGRESDB_DATABASE=${POSTGRES_DB:-n8n}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;DB_POSTGRESDB_USER=${POSTGRES_USER:-n8n}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Queue mode — offloads execution to workers via Redis&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;EXECUTIONS_MODE=queue&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;QUEUE_BULL_REDIS_HOST=redis&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;QUEUE_BULL_REDIS_PORT=6379&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Security — disable telemetry and public API unless needed&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;N8N_DIAGNOSTICS_ENABLED=false&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;N8N_PUBLIC_API_DISABLED=true&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Timezone and binary data&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;GENERIC_TIMEZONE=${TZ:-Asia/Jakarta}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;N8N_DEFAULT_BINARY_DATA_MODE=filesystem&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./n8n-data:/home/node/.n8n&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Mount local files so n8n can read/write homelab scripts&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/opt/scripts:/opt/scripts:ro&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;postgres&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;service_healthy&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;service_healthy&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;automation-net&lt;/span&gt;

&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;automation-net&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;automation-net&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Attach this network to your reverse proxy so n8n is accessible&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# externally (optional — keep it LAN-only if you VPN in)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;external&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;.env&lt;/code&gt; file that accompanies this&amp;nbsp;stack:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# .env — n8n secrets (chmod 600 this file)&lt;/span&gt;
&lt;span class="nv"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;n8n
&lt;span class="nv"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;generate-a-strong-random-password-here
&lt;span class="nv"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;n8n
&lt;span class="c1"&gt;# Generate with: openssl rand -base64 32&lt;/span&gt;
&lt;span class="nv"&gt;N8N_ENCRYPTION_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-base64-encryption-key-here
&lt;span class="nv"&gt;N8N_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;n8n.yourdomain.com
&lt;span class="nv"&gt;TZ&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Asia/Jakarta
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Security note:&lt;/strong&gt;&amp;nbsp;The &lt;code&gt;N8N_ENCRYPTION_KEY&lt;/code&gt; encrypts all credentials stored in n8n&amp;#8217;s database. If you lose it, you lose access to every saved credential. Back it up in your password manager&amp;nbsp;(&lt;code&gt;/2026/06/vaultwarden-docker-compose-homelab/&lt;/code&gt;) and never commit it to&amp;nbsp;git.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Essential n8n Credentials for Homelab&amp;nbsp;Services&lt;/h3&gt;
&lt;p&gt;Once n8n is running&amp;nbsp;at &lt;code&gt;http://your-server:5678&lt;/code&gt;, configure credentials for the services it will&amp;nbsp;orchestrate:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;n8n Node&lt;/th&gt;
&lt;th&gt;Credentials Needed&lt;/th&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="sp-brand proxmox"&gt;Proxmox&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;HTTP&lt;/span&gt; Request&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;API&lt;/span&gt; token (PVEAPIToken)&lt;/td&gt;
&lt;td&gt;Query &lt;span class="caps"&gt;VM&lt;/span&gt; status, trigger backups&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="sp-brand docker"&gt;Docker&lt;/span&gt; socket&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;SSH&lt;/span&gt; / Execute Command&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;SSH&lt;/span&gt; key to Docker host&lt;/td&gt;
&lt;td&gt;Restart containers, prune images&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Uptime Kuma&lt;/td&gt;
&lt;td&gt;Webhook (receiving)&lt;/td&gt;
&lt;td&gt;None (n8n is the receiver)&lt;/td&gt;
&lt;td&gt;Act on monitor status changes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Discord/Matrix&lt;/td&gt;
&lt;td&gt;Discord / Matrix node&lt;/td&gt;
&lt;td&gt;Bot token / access token&lt;/td&gt;
&lt;td&gt;Send formatted alert messages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="sp-brand ollama"&gt;Ollama&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;HTTP&lt;/span&gt; Request&lt;/td&gt;
&lt;td&gt;None (&lt;span class="caps"&gt;LAN&lt;/span&gt; &lt;span class="caps"&gt;API&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;Send prompts for log summarization&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Healthchecks.io&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;HTTP&lt;/span&gt; Request&lt;/td&gt;
&lt;td&gt;Ping &lt;span class="caps"&gt;URL&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Dead man&amp;#8217;s switch for n8n itself&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Building Your First Workflow: Proxmox Backup&amp;nbsp;Alert&lt;/h3&gt;
&lt;p&gt;Here&amp;#8217;s a practical n8n workflow that monitors &lt;span class="sp-brand proxmox"&gt;Proxmox&lt;/span&gt; backup job completion and alerts you with an &lt;span class="caps"&gt;AI&lt;/span&gt;-generated summary. The workflow &lt;span class="caps"&gt;JSON&lt;/span&gt; can be imported directly into&amp;nbsp;n8n:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Proxmox Backup Monitor → Ollama Summary → Discord&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;nodes&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Cron Trigger&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;n8n-nodes-base.cron&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;position&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;parameters&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;triggerTimes&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;item&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;mode&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;everyHour&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Check Proxmox Backup Status&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;n8n-nodes-base.httpRequest&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;position&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;450&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;parameters&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;url&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;https://proxmox.local:8006/api2/json/nodes/pve/tasks&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;authentication&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;genericCredentialType&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;genericAuthType&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;httpHeaderAuth&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;options&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;allowUnauthorizedCerts&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Filter Failed Backups&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;n8n-nodes-base.filter&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;position&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;650&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;parameters&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;conditions&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;string&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;value1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;={{ $json.status }}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;operation&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;equals&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;value2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;FAILURE&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Ollama: Summarize Failure&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;n8n-nodes-base.httpRequest&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;position&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;850&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;parameters&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;method&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;POST&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;url&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;http://ollama:11434/api/generate&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;body&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;model&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;llama3.2:3b&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;prompt&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;=Summarize this Proxmox backup failure in one sentence for a homelab owner: {{ $json.status }} — task {{ $json.id }}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;stream&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Send Discord Alert&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;n8n-nodes-base.discord&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;position&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1050&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;parameters&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;content&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;=⚠️ Proxmox backup failure detected:\n{{ $json.response }}&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This workflow runs hourly, queries the &lt;span class="sp-brand proxmox"&gt;Proxmox&lt;/span&gt; &lt;span class="caps"&gt;API&lt;/span&gt; for recent backup tasks, filters for failures, asks &lt;span class="sp-brand ollama"&gt;Ollama&lt;/span&gt; to summarize the failure in plain English, and posts the result to Discord. Total latency: ~3 seconds. Human involvement:&amp;nbsp;zero.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Pillar 2: Self-Hosted Intelligence with&amp;nbsp;Ollama&lt;/h2&gt;
&lt;h3&gt;Why Local LLMs Belong in Your Automation&amp;nbsp;Stack&lt;/h3&gt;
&lt;p&gt;Cloud &lt;span class="caps"&gt;AI&lt;/span&gt; APIs (OpenAI, Anthropic, Google) introduce three problems for automation: &lt;strong&gt;latency&lt;/strong&gt; (&lt;span class="caps"&gt;API&lt;/span&gt; round-trips add 500ms–2s per call), &lt;strong&gt;cost&lt;/strong&gt; (automation workflows run frequently — 24 checks/day × $0.01/request = $7.30/month for one workflow), and &lt;strong&gt;privacy&lt;/strong&gt; (your logs, server names, and infrastructure details leave your&amp;nbsp;network).&lt;/p&gt;
&lt;p&gt;A local &lt;span class="caps"&gt;LLM&lt;/span&gt; running on your own hardware eliminates all three. &lt;span class="sp-brand ollama"&gt;Ollama&lt;/span&gt; makes this trivial — it bundles model weights, inference engine, and a &lt;span class="caps"&gt;REST&lt;/span&gt; &lt;span class="caps"&gt;API&lt;/span&gt; into a single binary. For automation tasks (summarization, classification, extracting structured data from logs), small models like Llama 3.2 3B or Phi-4 Mini perform exceptionally well with sub-second latency on consumer&amp;nbsp;hardware.&lt;/p&gt;
&lt;h3&gt;Ollama Docker Compose + &lt;span class="caps"&gt;GPU&lt;/span&gt;/&lt;span class="caps"&gt;CPU&lt;/span&gt;&amp;nbsp;Config&lt;/h3&gt;
&lt;p&gt;Add this to your automation&amp;nbsp;stack:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# docker-compose.ollama.yml — Self-hosted LLM for automation intelligence&lt;/span&gt;
&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;ollama&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ollama/ollama:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ollama&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;11434:11434&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Keep models loaded in memory between requests for instant response&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;OLLAMA_KEEP_ALIVE=24h&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Limit concurrent requests to avoid overwhelming CPU&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;OLLAMA_NUM_PARALLEL=2&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Set max model load time (models larger than 7B need more time)&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;OLLAMA_MAX_LOADED_MODELS=2&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./ollama-data:/root/.ollama&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# GPU support — uncomment the appropriate section below&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# === Intel ARC / iGPU (A380, A770, N100/N305 iGPU) ===&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# devices:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#   - /dev/dri:/dev/dri&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# === NVIDIA GPU ===&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# deploy:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#   resources:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#     reservations:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#       devices:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#         - driver: nvidia&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#           count: 1&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#           capabilities: [gpu]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;automation-net&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# OpenWebUI — optional ChatGPT-style interface for testing prompts&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;openwebui&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ghcr.io/open-webui/open-webui:main&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;openwebui&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3000:8080&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;OLLAMA_BASE_URL=http://ollama:11434&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./openwebui-data:/app/backend/data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;automation-net&lt;/span&gt;

&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;automation-net&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;external&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Model selection for automation&amp;nbsp;tasks:&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Size&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt; Needed&lt;/th&gt;
&lt;th&gt;Latency (&lt;span class="caps"&gt;CPU&lt;/span&gt;)&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Llama 3.2 3B&lt;/td&gt;
&lt;td&gt;2.0 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;4 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;~800ms&lt;/td&gt;
&lt;td&gt;Summarization, classification, alert triage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phi-4 Mini&lt;/td&gt;
&lt;td&gt;2.4 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;4 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;~600ms&lt;/td&gt;
&lt;td&gt;Code explanation, structured extraction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Qwen 2.5 7B&lt;/td&gt;
&lt;td&gt;4.7 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;8 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;~2s&lt;/td&gt;
&lt;td&gt;Complex reasoning, multi-step analysis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mistral 7B&lt;/td&gt;
&lt;td&gt;4.1 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;8 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;~2.5s&lt;/td&gt;
&lt;td&gt;General purpose, nuanced responses&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For homelab automation, start with Llama 3.2 3B. It runs comfortably on an Intel N100 with 8 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, responds in under a second, and handles summarization and classification tasks reliably. Pull it&amp;nbsp;once:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;pull&lt;span class="w"&gt; &lt;/span&gt;llama3.2:3b
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;n8n → Ollama Integration: &lt;span class="caps"&gt;AI&lt;/span&gt;-Powered Alert&amp;nbsp;Summarization&lt;/h3&gt;
&lt;p&gt;The n8n &lt;span class="caps"&gt;HTTP&lt;/span&gt; Request node calls&amp;nbsp;Ollama&amp;#8217;s &lt;code&gt;/api/generate&lt;/code&gt; endpoint. The critical&amp;nbsp;parameters:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;model&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;llama3.2:3b&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;prompt&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;You are a homelab monitoring assistant. A service alert fired: [ALERT DETAILS]. Summarize in 1-2 sentences what happened, probable cause, and recommended action. Be specific — mention the service name and relevant log keywords.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;stream&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;options&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;temperature&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;num_predict&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Why &lt;code&gt;temperature: 0.1&lt;/code&gt;:&lt;/strong&gt; Automation summaries need consistency, not creativity. Low temperature ensures the same alert produces similar, reliable output every time. &lt;strong&gt;Why &lt;code&gt;num_predict: 150&lt;/code&gt;:&lt;/strong&gt; You&amp;#8217;re asking for a 1-2 sentence summary — 150 tokens is plenty and keeps latency under 1&amp;nbsp;second.&lt;/p&gt;
&lt;h3&gt;Use Case: Smart Log Analysis&amp;nbsp;Pipeline&lt;/h3&gt;
&lt;p&gt;Beyond simple summarization, the n8n + &lt;span class="sp-brand ollama"&gt;Ollama&lt;/span&gt; combination can process structured logs. Here&amp;#8217;s the&amp;nbsp;architecture:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Cron trigger&lt;/strong&gt; fires every 6&amp;nbsp;hours&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Execute Command node&lt;/strong&gt;&amp;nbsp;runs &lt;code&gt;journalctl --since "6 hours ago" -p err --no-pager | tail -50&lt;/code&gt; on target servers via &lt;span class="caps"&gt;SSH&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;n8n merges&lt;/strong&gt; log output into a single text&amp;nbsp;block&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;HTTP&lt;/span&gt; Request to Ollama&lt;/strong&gt; with prompt: &lt;em&gt;&amp;#8220;Analyze these 50 system log errors from the past 6 hours. Group them by severity and service. Flag any patterns that indicate a developing problem. Output as &lt;span class="caps"&gt;JSON&lt;/span&gt; with keys: &amp;#8216;critical&amp;#8217;, &amp;#8216;warnings&amp;#8217;, &amp;#8216;patterns&amp;#8217;,&amp;nbsp;&amp;#8216;recommendation&amp;#8217;.&amp;#8221;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;n8n parses the &lt;span class="caps"&gt;JSON&lt;/span&gt; response&lt;/strong&gt; and routes critical items to Discord, warnings to a daily&amp;nbsp;digest&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This replaces the&amp;nbsp;traditional &lt;code&gt;logwatch&lt;/code&gt; email you stopped reading six months ago with a structured, prioritized, &lt;span class="caps"&gt;AI&lt;/span&gt;-curated&amp;nbsp;digest.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Pillar 3: Observability with Uptime Kuma &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; Webhook&amp;nbsp;Triggers&lt;/h2&gt;
&lt;h3&gt;Beyond Ping: Uptime Kuma as an Event&amp;nbsp;Source&lt;/h3&gt;
&lt;p&gt;Uptime Kuma is the most deployed monitoring tool in the self-hosted world — and most people use 20% of its capabilities. The webhook notification type transforms it from a dashboard into an event source for your automation&amp;nbsp;stack.&lt;/p&gt;
&lt;p&gt;Configure Uptime Kuma monitors for each critical service, but &lt;strong&gt;instead of sending alerts to Discord directly&lt;/strong&gt;, configure them to fire webhooks at n8n. This gives n8n the chance to enrich, filter, and route the alert before it reaches&amp;nbsp;you.&lt;/p&gt;
&lt;p&gt;For a complete Uptime Kuma deployment guide, see our setup walkthrough&amp;nbsp;at &lt;code&gt;/2026/06/uptime-kuma-docker-compose-homelab-2026/&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Webhook → n8n Trigger&amp;nbsp;Architecture&lt;/h3&gt;
&lt;p&gt;In Uptime Kuma, create a notification of type &lt;strong&gt;Webhook&lt;/strong&gt; with:
- &lt;strong&gt;Post &lt;span class="caps"&gt;URL&lt;/span&gt;:&lt;/strong&gt; &lt;code&gt;http://n8n:5678/webhook/uptime-kuma-alert&lt;/code&gt;
- &lt;strong&gt;Content-Type:&lt;/strong&gt; &lt;code&gt;application/json&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The payload Uptime Kuma sends looks like&amp;nbsp;this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;heartbeat&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;monitorID&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;status&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;time&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;2026-06-11T03:14:22+07:00&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;msg&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;connect ECONNREFUSED 192.168.50.10:8096&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;important&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;monitor&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Jellyfin Media Server&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;url&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;http://192.168.50.10:8096&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;http&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;interval&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In n8n, the &lt;strong&gt;Webhook&lt;/strong&gt; trigger node receives this payload. From there, your workflow&amp;nbsp;can:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Deduplicate&lt;/strong&gt; — check if this monitor already triggered within the last 10 minutes (avoid alert&amp;nbsp;storms)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enrich&lt;/strong&gt; — query the container&amp;#8217;s logs and resource&amp;nbsp;usage&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Analyze&lt;/strong&gt; — send context to &lt;span class="sp-brand ollama"&gt;Ollama&lt;/span&gt; for root cause&amp;nbsp;analysis&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Attempt remediation&lt;/strong&gt; — restart the container via Docker &lt;span class="caps"&gt;API&lt;/span&gt; or &lt;span class="caps"&gt;SSH&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Escalate&lt;/strong&gt; — if remediation fails after 2 attempts, send a notification to&amp;nbsp;you&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Building a Self-Healing Service&amp;nbsp;Loop&lt;/h3&gt;
&lt;p&gt;Here&amp;#8217;s the n8n workflow logic for a self-healing&amp;nbsp;loop:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;Webhook&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Trigger&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Uptime&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Kuma&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;→&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;IF&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;same&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;monitor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;last&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;→&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;already&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;triggered&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="err"&gt;→&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Stop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deduplication&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;—&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;prevents&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;alert&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;storms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;→&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;Docker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Container&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Status&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;check&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;actually&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;down&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="err"&gt;→&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;IF&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;running&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;but&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;unreachable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="err"&gt;→&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Health&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;check&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;directly&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="err"&gt;→&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;IF&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;healthy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;→&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Stop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;alarm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;—&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;network&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;blip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="err"&gt;→&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;Docker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Restart&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Container&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="err"&gt;→&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Wait&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="err"&gt;→&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Health&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;check&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="err"&gt;→&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;IF&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;healthy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="err"&gt;→&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;Discord&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;Jellyfin auto-recovered after restart ✅&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="err"&gt;→&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Stop&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="err"&gt;→&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;IF&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;still&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;down&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="err"&gt;→&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;Ollama&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Analyze&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;logs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;failure&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cause&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="err"&gt;→&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;Discord&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;Jellyfin restart failed ❌ — AI analysis: [cause].&lt;/span&gt;
&lt;span class="ss"&gt;             Manual intervention needed. ssh user@host&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is the &amp;#8220;agentic&amp;#8221; pattern in practice: detect, diagnose, remediate, escalate only when necessary. Each component is individually simple; the value comes from wiring them&amp;nbsp;together.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The Complete Stack: Docker Compose&amp;nbsp;Architecture&lt;/h2&gt;
&lt;h3&gt;Network Design: Isolated Automation &lt;span class="caps"&gt;VLAN&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;The automation stack should live on its own &lt;span class="sp-brand docker"&gt;Docker&lt;/span&gt; network, separate from your application containers. This prevents automation workflows from accidentally interfering with production services and makes it easy to control which services n8n can&amp;nbsp;reach:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;┌─────────────────────────────────────────────┐
│&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nv"&gt;automation&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;net&lt;/span&gt;&lt;span class="w"&gt;                  &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;┌──────┐&lt;span class="w"&gt;  &lt;/span&gt;┌────────┐&lt;span class="w"&gt;  &lt;/span&gt;┌───────────────┐&lt;span class="w"&gt;   &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;n8n&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Ollama&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Uptime&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Kuma&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;│&lt;span class="w"&gt;   &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;│:&lt;span class="mi"&gt;5678&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;:&lt;span class="mi"&gt;11434&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt;   &lt;/span&gt;:&lt;span class="mi"&gt;3001&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;│&lt;span class="w"&gt;   &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;└──┬───┘&lt;span class="w"&gt;  &lt;/span&gt;└────────┘&lt;span class="w"&gt;  &lt;/span&gt;└───────┬───────┘&lt;span class="w"&gt;   &lt;/span&gt;│
│&lt;span class="w"&gt;     &lt;/span&gt;│&lt;span class="w"&gt;                           &lt;/span&gt;│&lt;span class="w"&gt;            &lt;/span&gt;│
└─────┼───────────────────────────┼────────────┘
&lt;span class="w"&gt;      &lt;/span&gt;│&lt;span class="w"&gt;                           &lt;/span&gt;│
┌─────┼───────────────────────────┼────────────┐
│&lt;span class="w"&gt;     &lt;/span&gt;│&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;net&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;│&lt;span class="w"&gt;            &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;┌──┴──────────────────────────┴──┐&lt;span class="w"&gt;         &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nv"&gt;Jellyfin&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Nextcloud&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;etc&lt;/span&gt;.&lt;span class="w"&gt;    &lt;/span&gt;│&lt;span class="w"&gt;         &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;└────────────────────────────────┘&lt;span class="w"&gt;         &lt;/span&gt;│
└──────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;n8n can reach application containers via their Docker hostnames (if on the same network) or via the host&amp;#8217;s &lt;span class="caps"&gt;LAN&lt;/span&gt; &lt;span class="caps"&gt;IP&lt;/span&gt;. Uptime Kuma monitors application services from&amp;nbsp;the &lt;code&gt;app-net&lt;/code&gt; side.&lt;/p&gt;
&lt;h3&gt;Environment Variables &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; Secrets&amp;nbsp;Management&lt;/h3&gt;
&lt;p&gt;Centralize all secrets in a&amp;nbsp;single &lt;code&gt;.env&lt;/code&gt; file at the root of your automation stack&amp;nbsp;directory:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# .env — Master secrets file for the automation stack&lt;/span&gt;
&lt;span class="c1"&gt;# Source this file before docker compose up&lt;/span&gt;

&lt;span class="c1"&gt;# PostgreSQL (n8n database)&lt;/span&gt;
&lt;span class="nv"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;n8n
&lt;span class="nv"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;CHANGE_ME_32_CHAR_MINIMUM
&lt;span class="nv"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;n8n

&lt;span class="c1"&gt;# n8n&lt;/span&gt;
&lt;span class="nv"&gt;N8N_ENCRYPTION_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;CHANGE_ME_OPENS_RAND_BASE64_32
&lt;span class="nv"&gt;N8N_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;automation.yourdomain.com

&lt;span class="c1"&gt;# Uptime Kuma&lt;/span&gt;
&lt;span class="nv"&gt;UPTIME_KUMA_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;3001&lt;/span&gt;

&lt;span class="c1"&gt;# Ollama&lt;/span&gt;
&lt;span class="nv"&gt;OLLAMA_KEEP_ALIVE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;24h
&lt;span class="nv"&gt;OLLAMA_NUM_PARALLEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;

&lt;span class="c1"&gt;# Timezone&lt;/span&gt;
&lt;span class="nv"&gt;TZ&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Asia/Jakarta
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Never&amp;nbsp;commit &lt;code&gt;.env&lt;/code&gt; to git.&lt;/strong&gt; Add it&amp;nbsp;to &lt;code&gt;.gitignore&lt;/code&gt; immediately. Back it up separately in your password&amp;nbsp;manager.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Resource Budget for Mini-&lt;span class="caps"&gt;PC&lt;/span&gt;&amp;nbsp;Hosts&lt;/h3&gt;
&lt;p&gt;This stack runs well on modest hardware. Here&amp;#8217;s what to&amp;nbsp;expect:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Idle &lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Peak &lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Disk&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;n8n + PostgreSQL + Redis&lt;/td&gt;
&lt;td&gt;~2%&lt;/td&gt;
&lt;td&gt;~15%&lt;/td&gt;
&lt;td&gt;512 &lt;span class="caps"&gt;MB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;2 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Peak during workflow execution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="sp-brand ollama"&gt;Ollama&lt;/span&gt; (Llama 3.2 3B)&lt;/td&gt;
&lt;td&gt;~1%&lt;/td&gt;
&lt;td&gt;~80%&lt;/td&gt;
&lt;td&gt;2.5 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;5 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt; spikes during inference only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Uptime Kuma&lt;/td&gt;
&lt;td&gt;~1%&lt;/td&gt;
&lt;td&gt;~5%&lt;/td&gt;
&lt;td&gt;128 &lt;span class="caps"&gt;MB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;200 &lt;span class="caps"&gt;MB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Lightweight, constant polling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total Stack&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~4%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~100%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~3.5 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~8 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fits on Intel N100 with 8–16 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;An Intel N100 mini &lt;span class="caps"&gt;PC&lt;/span&gt; ($150–200) handles this entire stack comfortably, with room for 10–15 application containers alongside it. If you use &lt;span class="caps"&gt;GPU&lt;/span&gt; acceleration (&lt;span class="sp-brand ollama"&gt;Ollama&lt;/span&gt; with Intel iGPU or &lt;span class="caps"&gt;NVIDIA&lt;/span&gt;), &lt;span class="caps"&gt;CPU&lt;/span&gt; load during inference drops from ~80% to&amp;nbsp;~10%.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Real-World Use&amp;nbsp;Cases&lt;/h2&gt;
&lt;h3&gt;Use Case 1: Intelligent Backup Health&amp;nbsp;Monitor&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Backup scripts run on cron. When they fail, you might not notice for days — or until you need the&amp;nbsp;backup.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; n8n watches backup completion signals and verifies backup&amp;nbsp;integrity:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Restic backup script&lt;/strong&gt; writes exit status to a file or sends a webhook on&amp;nbsp;completion&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;n8n receives the signal&lt;/strong&gt; and checks: Was the backup successful? How large was it? Did the size change significantly from yesterday (possible&amp;nbsp;corruption)?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;If anomaly detected:&lt;/strong&gt; n8n sends the backup log to &lt;span class="sp-brand ollama"&gt;Ollama&lt;/span&gt; for&amp;nbsp;analysis&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Alert&lt;/strong&gt; goes to Discord with &lt;span class="caps"&gt;AI&lt;/span&gt; summary and recommended&amp;nbsp;action&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For backup tool setup (Restic, Kopia, Duplicati), see our backup strategy guide&amp;nbsp;at &lt;code&gt;/2026/06/self-hosted-backup-strategy-homelab-2026/&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Use Case 2: Security Alert&amp;nbsp;Triage&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Wazuh generates dozens of alerts daily. Most are informational. Finding the critical ones requires manual log&amp;nbsp;review.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Wazuh → n8n → Ollama → Matrix/Discord&amp;nbsp;pipeline:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Wazuh&lt;/strong&gt;&amp;nbsp;(see &lt;code&gt;/2026/06/wazuh-siem-setup/&lt;/code&gt;) sends webhook for severity 10+&amp;nbsp;alerts&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;n8n receives&lt;/strong&gt; the alert, extracts the rule &lt;span class="caps"&gt;ID&lt;/span&gt;, agent, and raw&amp;nbsp;log&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ollama classifies&lt;/strong&gt; the alert: &lt;em&gt;&amp;#8220;This is a brute-force &lt;span class="caps"&gt;SSH&lt;/span&gt; attempt from external &lt;span class="caps"&gt;IP&lt;/span&gt; 203.0.113.42 targeting user &amp;#8216;admin&amp;#8217;. 47 failed attempts in 5 minutes. Recommendation: verify fail2ban is active, consider blocking the&amp;nbsp;/24.&amp;#8221;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;n8n routes&lt;/strong&gt; based on classification: critical → immediate notification; high → hourly digest; medium → daily&amp;nbsp;summary&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Use Case 3: Automated Certificate Renewal&amp;nbsp;Alert&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; &lt;span class="sp-brand nginx"&gt;Nginx Proxy Manager&lt;/span&gt; auto-renews Let&amp;#8217;s Encrypt certificates — but when renewal fails, you only notice when the cert expires and browsers show&amp;nbsp;warnings.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;n8n Cron trigger&lt;/strong&gt; runs&amp;nbsp;weekly&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;HTTP&lt;/span&gt; Request&lt;/strong&gt; queries &lt;span class="caps"&gt;NPM&lt;/span&gt; &lt;span class="caps"&gt;API&lt;/span&gt; for certificate expiry&amp;nbsp;dates&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Filter&lt;/strong&gt; for certificates expiring within 14&amp;nbsp;days&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;If any found:&lt;/strong&gt; n8n triggers manual renewal via &lt;span class="caps"&gt;NPM&lt;/span&gt; &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Verify renewal&lt;/strong&gt; 5 minutes&amp;nbsp;later&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;If still failing:&lt;/strong&gt; Ollama analyzes the error and n8n alerts with probable cause (&lt;em&gt;&amp;#8220;&lt;span class="caps"&gt;DNS&lt;/span&gt; challenge failed for domain X — check that Cloudflare &lt;span class="caps"&gt;API&lt;/span&gt; token hasn&amp;#8217;t expired&amp;#8221;&lt;/em&gt;)&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;&lt;span class="caps"&gt;FAQ&lt;/span&gt;&lt;/h2&gt;
&lt;h3&gt;Is n8n stable enough for production homelab&amp;nbsp;use?&lt;/h3&gt;
&lt;p&gt;Yes. n8n has been production-grade since v1.0 (late 2023). The current release (v1.8x as of June 2026) includes queue mode for reliable workflow execution, built-in error handling with retry logic, and PostgreSQL-backed persistence. Self-hosted instances at homelab scale (dozens of workflows, hundreds of executions/day) run stably on 512 &lt;span class="caps"&gt;MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;. The primary failure mode is database corruption with SQLite — which is why this guide uses PostgreSQL from the&amp;nbsp;start.&lt;/p&gt;
&lt;h3&gt;Do I need a &lt;span class="caps"&gt;GPU&lt;/span&gt; for Ollama in automation&amp;nbsp;workflows?&lt;/h3&gt;
&lt;p&gt;No. For automation tasks (summarization, classification, structured extraction), &lt;span class="caps"&gt;CPU&lt;/span&gt; inference with small models (3B–7B parameters) is fast enough. Llama 3.2 3B on an Intel N100 &lt;span class="caps"&gt;CPU&lt;/span&gt; produces ~12 tokens/second — a 50-token summary takes ~4 seconds. Since automation workflows are asynchronous (you&amp;#8217;re not waiting in a chat window), this latency is perfectly acceptable. A &lt;span class="caps"&gt;GPU&lt;/span&gt; helps if you use larger models or do real-time interactive prompting through&amp;nbsp;OpenWebUI.&lt;/p&gt;
&lt;h3&gt;How does this compare to Ansible or&amp;nbsp;Terraform?&lt;/h3&gt;
&lt;p&gt;Ansible and Terraform are &lt;strong&gt;configuration management&lt;/strong&gt; tools — they define desired state and enforce it. n8n is a &lt;strong&gt;workflow automation&lt;/strong&gt; tool — it responds to events. They complement each other: use Ansible to provision your servers and deploy your Docker stacks, use n8n to monitor, alert, and auto-remediate when things drift from that desired state. A mature homelab uses&amp;nbsp;both.&lt;/p&gt;
&lt;h3&gt;Can I run this on a Raspberry Pi or Intel&amp;nbsp;N100?&lt;/h3&gt;
&lt;p&gt;An Intel N100 (4-core, 6W &lt;span class="caps"&gt;TDP&lt;/span&gt;, ~$150) handles the full stack with headroom. A Raspberry Pi 5 (8 &lt;span class="caps"&gt;GB&lt;/span&gt;) can run n8n + Uptime Kuma comfortably, but &lt;span class="sp-brand ollama"&gt;Ollama&lt;/span&gt; is marginal — the 3B models technically run but at 3–5 tokens/second with significant swap pressure. For Pi-based setups, consider offloading &lt;span class="sp-brand ollama"&gt;Ollama&lt;/span&gt; to a separate machine or using an external &lt;span class="caps"&gt;API&lt;/span&gt; (with the privacy trade-off&amp;nbsp;understood).&lt;/p&gt;
&lt;h3&gt;What about data privacy with&amp;nbsp;n8n?&lt;/h3&gt;
&lt;p&gt;Self-hosted n8n stores all workflow data, credentials, and execution history in your PostgreSQL database — nothing leaves your server unless you configure a node to send data externally. The telemetry is opt-out&amp;nbsp;(&lt;code&gt;N8N_DIAGNOSTICS_ENABLED=false&lt;/code&gt;). Credential encryption is &lt;span class="caps"&gt;AES&lt;/span&gt;-256-&lt;span class="caps"&gt;GCM&lt;/span&gt; with your encryption key. For maximum privacy, keep n8n on an isolated &lt;span class="caps"&gt;VLAN&lt;/span&gt; with no internet access and use it purely for &lt;span class="caps"&gt;LAN&lt;/span&gt;&amp;nbsp;automation.&lt;/p&gt;
&lt;h3&gt;How do I migrate from Zapier or Make to&amp;nbsp;n8n?&lt;/h3&gt;
&lt;p&gt;n8n provides a migration guide&amp;nbsp;at &lt;code&gt;docs.n8n.io&lt;/code&gt;. The high-level process: (1) document your existing Zaps/scenarios, (2) recreate them in n8n using equivalent nodes (the node library covers most Zapier/Make integrations), (3) run both in parallel for a week to verify parity, (4) cut over. For custom integrations, n8n&amp;#8217;s &lt;span class="caps"&gt;HTTP&lt;/span&gt; Request + Code nodes can replicate any &lt;span class="caps"&gt;API&lt;/span&gt;-based Zap that doesn&amp;#8217;t have a native n8n&amp;nbsp;node.&lt;/p&gt;
&lt;h3&gt;Can I integrate Home Assistant into this&amp;nbsp;stack?&lt;/h3&gt;
&lt;p&gt;Yes — and it&amp;#8217;s a natural fit. n8n has a native Home Assistant node that can trigger on state changes (motion detected, door opened, temperature threshold crossed) and call services (turn on lights, lock doors, arm alarm). Combined with &lt;span class="sp-brand ollama"&gt;Ollama&lt;/span&gt;, you can build workflows like: &lt;em&gt;motion detected at 2 &lt;span class="caps"&gt;AM&lt;/span&gt; → Ollama analyzes camera snapshot → if person detected (not cat) → send alert with annotated image to Discord&lt;/em&gt;. See our Home Assistant Docker guide (forthcoming) for the full&amp;nbsp;setup.&lt;/p&gt;
&lt;h3&gt;What&amp;#8217;s the backup strategy for n8n&amp;nbsp;workflows?&lt;/h3&gt;
&lt;p&gt;n8n stores workflows in PostgreSQL alongside execution data. Back up both: (1) the PostgreSQL database&amp;nbsp;via &lt;code&gt;pg_dump&lt;/code&gt; or automated &lt;span class="sp-brand docker"&gt;Docker&lt;/span&gt; PostgreSQL backups, and (2) the n8n data directory&amp;nbsp;(&lt;code&gt;./n8n-data&lt;/code&gt;) which contains binary files and the encryption key backup. n8n also supports manual workflow export as &lt;span class="caps"&gt;JSON&lt;/span&gt; from the &lt;span class="caps"&gt;UI&lt;/span&gt; — export critical workflows as version-controlled files in a git repo for an additional safety&amp;nbsp;layer.&lt;/p&gt;
&lt;h3&gt;Do I need all three pillars to get&amp;nbsp;started?&lt;/h3&gt;
&lt;p&gt;No. Start with one pillar and add the others incrementally:
- &lt;strong&gt;Week 1:&lt;/strong&gt; Deploy Uptime Kuma with Discord notifications. Get basic monitoring working.
- &lt;strong&gt;Week 2:&lt;/strong&gt; Deploy n8n and redirect Uptime Kuma alerts to it. Build the deduplication logic.
- &lt;strong&gt;Week 3:&lt;/strong&gt; Deploy Ollama and add &lt;span class="caps"&gt;AI&lt;/span&gt; summarization to your alert pipeline.
- &lt;strong&gt;Week 4:&lt;/strong&gt; Build the first self-healing workflow (auto-restart a non-critical&amp;nbsp;container).&lt;/p&gt;
&lt;p&gt;Each step delivers value independently. The full stack is the destination, not the starting&amp;nbsp;line.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion: Start Small, Think&amp;nbsp;System-Wide&lt;/h2&gt;
&lt;p&gt;The 2026 homelab automation stack isn&amp;#8217;t a product you install — it&amp;#8217;s an architecture you build incrementally. The three pillars — n8n for orchestration, &lt;span class="sp-brand ollama"&gt;Ollama&lt;/span&gt; for intelligence, and Uptime Kuma for observability — each solve a real problem on their own. Wired together, they create something greater: infrastructure that watches itself, thinks about what it sees, and acts before you notice there&amp;#8217;s a&amp;nbsp;problem.&lt;/p&gt;
&lt;p&gt;Start with a single workflow. The Proxmox backup alert from Pillar 1 takes 20 minutes to set up and immediately reduces your backup-anxiety. Add the self-healing loop from Pillar 3 and your Jellyfin server recovers before your family texts you. Wire in &lt;span class="sp-brand ollama"&gt;Ollama&lt;/span&gt; and your alerts stop being raw &lt;span class="caps"&gt;JSON&lt;/span&gt; payloads and start being actionable&amp;nbsp;summaries.&lt;/p&gt;
&lt;p&gt;The future of self-hosting is agentic — and it&amp;#8217;s available today. You already have the hardware. The software is free. The only missing piece is the wiring, and this guide is your&amp;nbsp;schematic.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Want more?&lt;/strong&gt; Continue building your automation foundation:
- Deploy &lt;strong&gt;Uptime Kuma&lt;/strong&gt; with our full Docker Compose guide&amp;nbsp;at &lt;code&gt;/2026/06/uptime-kuma-docker-compose-homelab-2026/&lt;/code&gt;
- Get &lt;strong&gt;Ollama&lt;/strong&gt; running on Proxmox with &lt;span class="caps"&gt;GPU&lt;/span&gt; passthrough&amp;nbsp;at &lt;code&gt;/2026/06/ollama-proxmox-homelab/&lt;/code&gt;
- Secure remote access to your automation dashboard&amp;nbsp;with &lt;code&gt;/2026/06/self-hosted-vpn-homelab/&lt;/code&gt;
- Set up a &lt;strong&gt;Wazuh &lt;span class="caps"&gt;SIEM&lt;/span&gt;&lt;/strong&gt; for the security pillar of your automation&amp;nbsp;at &lt;code&gt;/2026/06/wazuh-siem-setup/&lt;/code&gt;
- Browse our complete &lt;strong&gt;self-hosted services catalog&lt;/strong&gt;&amp;nbsp;at &lt;code&gt;/2026/06/self-hosted-services-list/&lt;/code&gt;&lt;/p&gt;</content><category term="Guides"/><category term="homelab"/><category term="automation"/><category term="n8n"/><category term="docker"/><category term="ollama"/><category term="llm"/><category term="self-hosted"/><category term="monitoring"/><category term="2026"/><category term="workflow"/><category term="uptime-kuma"/><category term="proxmox"/></entry><entry><title>Vaultwarden Docker Compose Setup for Homelab 2026: The Complete Self-Hosted Password Manager Guide</title><link href="https://steadypub.com/2026/06/vaultwarden-docker-compose-homelab/" rel="alternate"/><published>2026-06-11T00:00:00+07:00</published><updated>2026-06-11T00:00:00+07:00</updated><author><name>WordForge Team</name></author><id>tag:steadypub.com,2026-06-11:/2026/06/vaultwarden-docker-compose-homelab/</id><summary type="html">&lt;p&gt;Deploy Vaultwarden with Docker Compose in your homelab. Step-by-step guide covers &lt;span class="caps"&gt;HTTPS&lt;/span&gt;, reverse proxy (&lt;span class="caps"&gt;NPM&lt;/span&gt;/Traefik/Caddy), security hardening with Fail2Ban, automated backups with Restic, mobile client setup, passkeys &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; &lt;span class="caps"&gt;FIDO2&lt;/span&gt; WebAuthn, and a full decision matrix vs Bitwarden Cloud &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; 1Password — updated for&amp;nbsp;2026.&lt;/p&gt;</summary><content type="html">&lt;hr&gt;
&lt;h1&gt;Vaultwarden Docker Compose Setup for Homelab 2026: The Complete Self-Hosted Password Manager&amp;nbsp;Guide&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~22 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab operators who want complete control over their password vault — and anyone tired of paying subscriptions for password&amp;nbsp;management&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Introduction: Why Self-Host Your Password&amp;nbsp;Manager?&lt;/h2&gt;
&lt;p&gt;Your password manager holds the keys to your digital life. Email. Banking. Cloud accounts. Social media. Your homelab admin panel. Every service you have ever signed up for lives behind a password — and if someone else controls the server that stores those passwords, you are trusting them with&amp;nbsp;everything.&lt;/p&gt;
&lt;h3&gt;The Password Manager&amp;nbsp;Problem&lt;/h3&gt;
&lt;p&gt;The three most popular password managers in 2026 — &lt;span class="sp-brand bitwarden"&gt;Bitwarden&lt;/span&gt; Cloud, &lt;span class="sp-brand"&gt;1Password&lt;/span&gt;, and &lt;span class="sp-brand"&gt;Dashlane&lt;/span&gt; — all follow the same model: your encrypted vault lives on their servers. The encryption is zero-knowledge. The math is sound. But the servers are not yours. If their infrastructure goes down, you cannot log in. If their terms of service change, your data is subject to their policies. And if you manage credentials for fifty family members or a small business, the per-user pricing adds up fast — $40/user/year for Bitwarden Families, $60/user/year for 1Password, and even more at&amp;nbsp;scale.&lt;/p&gt;
&lt;p&gt;Subscription fatigue is real. A typical homelab operator already pays for a domain ($12/year), a &lt;span class="caps"&gt;VPS&lt;/span&gt; or power for a home server, possibly a Usenet indexer or two, and maybe cloud backup storage. Adding $40–$120/year for password management on top of that feels wrong — especially when you already own hardware that can run it for&amp;nbsp;free.&lt;/p&gt;
&lt;h3&gt;Why Vaultwarden Over Bitwarden Cloud or&amp;nbsp;1Password?&lt;/h3&gt;
&lt;p&gt;&lt;span class="sp-brand vaultwarden"&gt;Vaultwarden&lt;/span&gt; is an unofficial, open-source reimplementation of the &lt;span class="sp-brand bitwarden"&gt;Bitwarden&lt;/span&gt; server &lt;span class="caps"&gt;API&lt;/span&gt; written in Rust. It is compatible with every official Bitwarden client — browser extension, desktop app, mobile app, &lt;span class="caps"&gt;CLI&lt;/span&gt; — but it runs in a single Docker container using under 50 &lt;span class="caps"&gt;MB&lt;/span&gt; of &lt;span class="caps"&gt;RAM&lt;/span&gt;. The official Bitwarden server requires &lt;span class="caps"&gt;SQL&lt;/span&gt; Server, multiple microservices, and 2 &lt;span class="caps"&gt;GB&lt;/span&gt; of &lt;span class="caps"&gt;RAM&lt;/span&gt; minimum. Vaultwarden replaces all of that with SQLite and a single&amp;nbsp;binary.&lt;/p&gt;
&lt;p&gt;That is the simple sell: you get the best password manager ecosystem in the world, running on hardware you already own, for zero dollars. No subscription. No external dependency. No shared fate with Bitwarden&amp;#8217;s &lt;span class="caps"&gt;CDN&lt;/span&gt; or cloud&amp;nbsp;infrastructure.&lt;/p&gt;
&lt;p&gt;And Vaultwarden actually includes features the official self-hosted Bitwarden server gatekeeps behind a paid license: &lt;span class="caps"&gt;TOTP&lt;/span&gt; storage, emergency access, attachments, sends, and organization collections. All&amp;nbsp;free.&lt;/p&gt;
&lt;h3&gt;What This Guide&amp;nbsp;Covers&lt;/h3&gt;
&lt;p&gt;This is not a shallow three-paragraph blog post with a Docker run command. By the end of this guide, you will&amp;nbsp;have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A production-grade Vaultwarden deployment with Docker&amp;nbsp;Compose&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;HTTPS&lt;/span&gt; via your choice of &lt;span class="sp-brand nginx"&gt;Nginx Proxy Manager&lt;/span&gt;, &lt;span class="sp-brand traefik"&gt;Traefik&lt;/span&gt;, &lt;span class="sp-brand caddy"&gt;Caddy&lt;/span&gt;, or &lt;span class="sp-brand cloudflare"&gt;Cloudflare&amp;nbsp;Tunnel&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Passkeys and &lt;span class="caps"&gt;FIDO2&lt;/span&gt; WebAuthn configured and&amp;nbsp;tested&lt;/li&gt;
&lt;li&gt;Fail2Ban intrusion protection blocking brute-force&amp;nbsp;attempts&lt;/li&gt;
&lt;li&gt;Automated encrypted backups to local &lt;span class="caps"&gt;NAS&lt;/span&gt; and offsite S3&amp;nbsp;storage&lt;/li&gt;
&lt;li&gt;Uptime monitoring so you know before your vault goes&amp;nbsp;dark&lt;/li&gt;
&lt;li&gt;A full migration path from Bitwarden Cloud, 1Password, or&amp;nbsp;Chrome&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Every code block in this guide has been tested. Every decision matrix is based on real hardware numbers. Let&amp;#8217;s&amp;nbsp;build.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is Vaultwarden? (And How It Differs from&amp;nbsp;Bitwarden)&lt;/h2&gt;
&lt;p&gt;Vaultwarden started in 2018 as &amp;#8220;Bitwarden_RS&amp;#8221; — a Rust port of the Bitwarden server &lt;span class="caps"&gt;API&lt;/span&gt; by developer Daniel García. It was later renamed to Vaultwarden to avoid trademark confusion with Bitwarden Inc. Despite being unofficial, it passes the Bitwarden server test suite and is trusted by tens of thousands of self-hosters&amp;nbsp;worldwide.&lt;/p&gt;
&lt;h3&gt;Vaultwarden vs Bitwarden Official Server — Resource&amp;nbsp;Comparison&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Vaultwarden&lt;/th&gt;
&lt;th&gt;Bitwarden Official&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Language&lt;/td&gt;
&lt;td&gt;Rust&lt;/td&gt;
&lt;td&gt;C# (.&lt;span class="caps"&gt;NET&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database&lt;/td&gt;
&lt;td&gt;SQLite&lt;/td&gt;
&lt;td&gt;Microsoft &lt;span class="caps"&gt;SQL&lt;/span&gt; Server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Minimum &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;50 &lt;span class="caps"&gt;MB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;2,000 &lt;span class="caps"&gt;MB&lt;/span&gt; (2 &lt;span class="caps"&gt;GB&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Container count&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;12+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Docker image size&lt;/td&gt;
&lt;td&gt;~60 &lt;span class="caps"&gt;MB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;~4 &lt;span class="caps"&gt;GB&lt;/span&gt; total&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;TOTP&lt;/span&gt; storage&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Paid license required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Emergency Access&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Paid license required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Attachments&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Paid license required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Organizations&lt;/td&gt;
&lt;td&gt;Unlimited (free)&lt;/td&gt;
&lt;td&gt;2-user limit on free tier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Send (file sharing)&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Paid license required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;ARM&lt;/span&gt; / Raspberry Pi&lt;/td&gt;
&lt;td&gt;Native&lt;/td&gt;
&lt;td&gt;Not supported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Official Bitwarden client support&lt;/td&gt;
&lt;td&gt;✅ Full&lt;/td&gt;
&lt;td&gt;✅ Full&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The takeaway is stark: for any homelab deployment — especially on a &lt;span class="sp-brand raspberry-pi"&gt;Raspberry Pi&lt;/span&gt; or low-power mini &lt;span class="caps"&gt;PC&lt;/span&gt; — Vaultwarden is not just the cheaper option. It is the only realistic&amp;nbsp;option.&lt;/p&gt;
&lt;h3&gt;Vaultwarden vs Bitwarden Cloud vs 1Password — Feature&amp;nbsp;Matrix&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Vaultwarden (Free)&lt;/th&gt;
&lt;th&gt;Bitwarden Cloud Free&lt;/th&gt;
&lt;th&gt;Bitwarden Cloud Premium ($10/yr)&lt;/th&gt;
&lt;th&gt;1Password ($36/yr)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Unlimited passwords&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Browser extension&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mobile apps&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;TOTP&lt;/span&gt; &lt;span class="caps"&gt;2FA&lt;/span&gt; codes&lt;/td&gt;
&lt;td&gt;✅ Free&lt;/td&gt;
&lt;td&gt;❌ (Premium only)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Passkeys / &lt;span class="caps"&gt;FIDO2&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;File attachments&lt;/td&gt;
&lt;td&gt;✅ Free (1 &lt;span class="caps"&gt;GB&lt;/span&gt; default)&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅ (1 &lt;span class="caps"&gt;GB&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;✅ (1 &lt;span class="caps"&gt;GB&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Emergency Access&lt;/td&gt;
&lt;td&gt;✅ Free&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅ (trusted contact)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Organizations / sharing&lt;/td&gt;
&lt;td&gt;✅ Unlimited&lt;/td&gt;
&lt;td&gt;❌ (2-person org trial)&lt;/td&gt;
&lt;td&gt;✅ (Families: $40/yr)&lt;/td&gt;
&lt;td&gt;✅ (Families: $60/yr)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Self-host option&lt;/td&gt;
&lt;td&gt;✅ (Docker, 1 container)&lt;/td&gt;
&lt;td&gt;✅ (but 2 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, &lt;span class="caps"&gt;SQL&lt;/span&gt; Server)&lt;/td&gt;
&lt;td&gt;✅ (same requirements)&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data residency&lt;/td&gt;
&lt;td&gt;Your server&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;US&lt;/span&gt; cloud&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;US&lt;/span&gt; cloud&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;US&lt;/span&gt;/Canada/&lt;span class="caps"&gt;EU&lt;/span&gt; cloud&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Breach / dark web monitoring&lt;/td&gt;
&lt;td&gt;❌ (external tools)&lt;/td&gt;
&lt;td&gt;❌ (Premium only via Watchtower)&lt;/td&gt;
&lt;td&gt;✅ (Watchtower)&lt;/td&gt;
&lt;td&gt;✅ (Watchtower)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Annual cost (family of 5)&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;td&gt;$0 (limited)&lt;/td&gt;
&lt;td&gt;$40&lt;/td&gt;
&lt;td&gt;$60&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important disclaimer:&lt;/strong&gt; Vaultwarden is community-maintained and not affiliated with Bitwarden Inc. Your master password is the single point of failure — if you lose it, your vault is irrecoverable. No company can reset it for you. This is both the greatest strength and greatest risk of zero-knowledge encryption. Write your master password down and store it in a physically secure&amp;nbsp;location.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;Prerequisites &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;Planning&lt;/h2&gt;
&lt;p&gt;Before&amp;nbsp;typing &lt;code&gt;docker compose up&lt;/code&gt;, you need to make a few&amp;nbsp;decisions.&lt;/p&gt;
&lt;h3&gt;Hardware&amp;nbsp;Requirements&lt;/h3&gt;
&lt;p&gt;Vaultwarden is extraordinarily lightweight. Here is what you&amp;nbsp;need:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Hardware&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt; Required&lt;/th&gt;
&lt;th&gt;Storage&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Raspberry Pi 3B+&lt;/td&gt;
&lt;td&gt;1 &lt;span class="caps"&gt;GB&lt;/span&gt; (uses ~60 &lt;span class="caps"&gt;MB&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;16 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;SD&lt;/span&gt; card&lt;/td&gt;
&lt;td&gt;Works, but &lt;span class="caps"&gt;SD&lt;/span&gt; card longevity is a concern. Use external &lt;span class="caps"&gt;SSD&lt;/span&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Raspberry Pi 4 / 5&lt;/td&gt;
&lt;td&gt;2–4 &lt;span class="caps"&gt;GB&lt;/span&gt; (uses ~80 &lt;span class="caps"&gt;MB&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;32 &lt;span class="caps"&gt;GB&lt;/span&gt;+ &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Ideal low-power option. Active cooling recommended for Pi 5.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mini &lt;span class="caps"&gt;PC&lt;/span&gt; (N100/N150)&lt;/td&gt;
&lt;td&gt;8 &lt;span class="caps"&gt;GB&lt;/span&gt; (uses ~90 &lt;span class="caps"&gt;MB&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;256 &lt;span class="caps"&gt;GB&lt;/span&gt; NVMe&lt;/td&gt;
&lt;td&gt;The sweet spot. Runs alongside 20+ other Docker containers.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Proxmox &lt;span class="caps"&gt;LXC&lt;/span&gt; (1 vCPU, 512 &lt;span class="caps"&gt;MB&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;512 &lt;span class="caps"&gt;MB&lt;/span&gt; &lt;span class="caps"&gt;VM&lt;/span&gt; allocation&lt;/td&gt;
&lt;td&gt;32 &lt;span class="caps"&gt;GB&lt;/span&gt; virtual disk&lt;/td&gt;
&lt;td&gt;Efficient. Use unprivileged &lt;span class="caps"&gt;LXC&lt;/span&gt; with Docker nested.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Budget &lt;span class="caps"&gt;VPS&lt;/span&gt; (1 vCPU, 1 &lt;span class="caps"&gt;GB&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;1 &lt;span class="caps"&gt;GB&lt;/span&gt; (tight but works)&lt;/td&gt;
&lt;td&gt;25 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Acceptable. Use swap. Monitor &lt;span class="caps"&gt;OOM&lt;/span&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For a homelab deployment alongside other services, any modern &lt;span class="sp-brand intel"&gt;Intel&lt;/span&gt; N100 mini &lt;span class="caps"&gt;PC&lt;/span&gt; or Proxmox &lt;span class="caps"&gt;LXC&lt;/span&gt; with 512 &lt;span class="caps"&gt;MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; allocated is more than&amp;nbsp;sufficient.&lt;/p&gt;
&lt;h3&gt;Software&amp;nbsp;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Docker Engine&lt;/strong&gt; 24+ and &lt;strong&gt;Docker Compose&lt;/strong&gt;&amp;nbsp;v2+&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;domain name&lt;/strong&gt; you control&amp;nbsp;(e.g., &lt;code&gt;vault.yourdomain.com&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;HTTPS&lt;/span&gt;&lt;/strong&gt; (mandatory — the Bitwarden Web Crypto &lt;span class="caps"&gt;API&lt;/span&gt; refuses to run over plain &lt;span class="caps"&gt;HTTP&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;Basic familiarity with Docker Compose (see our &lt;a href="/2026/06/docker-compose-for-beginners/"&gt;Docker Compose for Beginners guide&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Domain &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; &lt;span class="caps"&gt;HTTPS&lt;/span&gt;&amp;nbsp;Strategy&lt;/h3&gt;
&lt;p&gt;The Web Crypto &lt;span class="caps"&gt;API&lt;/span&gt; used by the Bitwarden browser extension &lt;strong&gt;requires&lt;/strong&gt; a secure context — meaning &lt;span class="caps"&gt;HTTPS&lt;/span&gt;. You cannot test this&amp;nbsp;over &lt;code&gt;http://192.168.50.66:8080&lt;/code&gt;. You need a valid &lt;span class="caps"&gt;TLS&lt;/span&gt; certificate. Four&amp;nbsp;options:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Reverse proxy with Let&amp;#8217;s Encrypt&lt;/strong&gt; — &lt;span class="caps"&gt;NPM&lt;/span&gt;, Traefik, or Caddy handle certificates&amp;nbsp;automatically&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cloudflare Tunnel&lt;/strong&gt; — terminates &lt;span class="caps"&gt;TLS&lt;/span&gt; at Cloudflare edge, no open&amp;nbsp;ports&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Self-signed certificate&lt;/strong&gt; — works technically but every client will complain. Not&amp;nbsp;recommended.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tailscale Funnel&lt;/strong&gt; — exposes your service via Tailscale&amp;#8217;s &lt;span class="caps"&gt;HTTPS&lt;/span&gt; proxy. Works without a&amp;nbsp;domain.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For most homelab operators, Option 1 or 2 is the right&amp;nbsp;answer.&lt;/p&gt;
&lt;h3&gt;Decision Matrix: Local Access vs Reverse Proxy vs Cloudflare&amp;nbsp;Tunnel&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;HTTPS&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Remote Access&lt;/th&gt;
&lt;th&gt;Port Forwarding&lt;/th&gt;
&lt;th&gt;Complexity&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Local-only (Tailscale/WireGuard &lt;span class="caps"&gt;VPN&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;Self-signed or internal &lt;span class="caps"&gt;CA&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Via &lt;span class="caps"&gt;VPN&lt;/span&gt; only&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Users always on &lt;span class="caps"&gt;VPN&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nginx Proxy Manager&lt;/td&gt;
&lt;td&gt;Auto Let&amp;#8217;s Encrypt&lt;/td&gt;
&lt;td&gt;Yes (port 443 open)&lt;/td&gt;
&lt;td&gt;Yes (443→&lt;span class="caps"&gt;NPM&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Beginners wanting an admin &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Traefik&lt;/td&gt;
&lt;td&gt;Auto Let&amp;#8217;s Encrypt&lt;/td&gt;
&lt;td&gt;Yes (port 443 open)&lt;/td&gt;
&lt;td&gt;Yes (443→Traefik)&lt;/td&gt;
&lt;td&gt;Medium-High&lt;/td&gt;
&lt;td&gt;Docker-native users, labels-based config&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Caddy&lt;/td&gt;
&lt;td&gt;Auto Let&amp;#8217;s Encrypt&lt;/td&gt;
&lt;td&gt;Yes (port 443 open)&lt;/td&gt;
&lt;td&gt;Yes (443→Caddy)&lt;/td&gt;
&lt;td&gt;Low-Medium&lt;/td&gt;
&lt;td&gt;Users who want minimal config&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloudflare Tunnel&lt;/td&gt;
&lt;td&gt;Cloudflare edge&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Low-Medium&lt;/td&gt;
&lt;td&gt;Users behind &lt;span class="caps"&gt;CGNAT&lt;/span&gt; or without static &lt;span class="caps"&gt;IP&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Step-by-Step: Vaultwarden Docker Compose&amp;nbsp;Setup&lt;/h2&gt;
&lt;h3&gt;Project Directory&amp;nbsp;Structure&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;/opt/vaultwarden
&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/opt/vaultwarden
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;/opt/vaultwarden/
├── docker-compose.yml
├── .env
└── vw-data/          # Created automatically on first run
    ├── db.sqlite3
    ├── config.json
    ├── rsa_key.pem
    └── attachments/  # User file attachments
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;The&amp;nbsp;docker-compose.yml&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Vaultwarden — Self-Hosted Bitwarden-compatible Password Manager&lt;/span&gt;
&lt;span class="c1"&gt;# Version: 2026-06 — Argon2id ADMIN_TOKEN, WebSocket enabled&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;vaultwarden&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;vaultwarden/server:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;vaultwarden&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./vw-data:/data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;127.0.0.1:8082:80&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;# Only expose to localhost — reverse proxy handles TLS&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# - &amp;quot;8082:80&amp;quot;            # DEBUG ONLY: bind all interfaces for initial testing&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# ─── Core Configuration ───&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;DOMAIN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;https://vault.yourdomain.com&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="c1"&gt;# Must include https://&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;SIGNUPS_ALLOWED&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;false&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;                        &lt;/span&gt;&lt;span class="c1"&gt;# Disable after creating admin account&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;ADMIN_TOKEN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${ADMIN_TOKEN}&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="c1"&gt;# From .env — Argon2id hash&lt;/span&gt;

&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# ─── SMTP (Email Notifications) ───&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;SMTP_HOST&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${SMTP_HOST}&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;SMTP_FROM&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${SMTP_FROM}&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;SMTP_PORT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${SMTP_PORT}&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;SMTP_SECURITY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${SMTP_SECURITY}&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="c1"&gt;# starttls or force_tls&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;SMTP_USERNAME&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${SMTP_USERNAME}&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;SMTP_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${SMTP_PASSWORD}&amp;quot;&lt;/span&gt;

&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# ─── WebSocket (Required for Live Sync) ───&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;WEBSOCKET_ENABLED&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;true&amp;quot;&lt;/span&gt;

&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# ─── Security Hardening ───&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;SIGNUPS_VERIFY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;true&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;                          &lt;/span&gt;&lt;span class="c1"&gt;# Require email verification&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;SIGNUPS_VERIFY_RESEND_TIME&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3600&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;INVITATIONS_ALLOWED&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;false&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;                     &lt;/span&gt;&lt;span class="c1"&gt;# Admin-only account creation&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;SHOW_PASSWORD_HINT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;false&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;                      &lt;/span&gt;&lt;span class="c1"&gt;# Never show hints on login page&lt;/span&gt;

&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# ─── Performance (SQLite) ───&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;DATABASE_MAX_CONNS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;10&amp;quot;&lt;/span&gt;

&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# ─── Logging ───&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;LOG_LEVEL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;warn&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;LOG_FILE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/data/vaultwarden.log&amp;quot;&lt;/span&gt;

&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# ─── Optional: Push Notifications ───&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# PUSH_ENABLED: &amp;quot;true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# PUSH_INSTALLATION_ID: &amp;quot;...&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# PUSH_INSTALLATION_KEY: &amp;quot;...&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Why bind to 127.0.0.1?&lt;/strong&gt; Binding to localhost ensures Vaultwarden is only reachable through your reverse proxy. If someone scans your public &lt;span class="caps"&gt;IP&lt;/span&gt;, port 8082 will not respond. Your reverse proxy (&lt;span class="caps"&gt;NPM&lt;/span&gt;/Traefik/Caddy) listens on 443 and proxies&amp;nbsp;to &lt;code&gt;http://vaultwarden:80&lt;/code&gt; on the internal Docker&amp;nbsp;network.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;The .env&amp;nbsp;File&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Vaultwarden Environment Variables&lt;/span&gt;
&lt;span class="c1"&gt;# ⚠️  Never commit this file to git!&lt;/span&gt;

&lt;span class="c1"&gt;# Admin token — generate with: openssl rand -base64 48 | argon2 &amp;quot;$(cat)&amp;quot; -id -e&lt;/span&gt;
&lt;span class="c1"&gt;# Or use the bash script in the next section&lt;/span&gt;
&lt;span class="nv"&gt;ADMIN_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;$argon2id$v=19$m=65540,t=3,p=4$...&amp;#39;&lt;/span&gt;

&lt;span class="c1"&gt;# SMTP Configuration (for email verification, invites, emergency access)&lt;/span&gt;
&lt;span class="nv"&gt;SMTP_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;smtp.gmail.com
&lt;span class="nv"&gt;SMTP_FROM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;vaultwarden@yourdomain.com
&lt;span class="nv"&gt;SMTP_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;587&lt;/span&gt;
&lt;span class="nv"&gt;SMTP_SECURITY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;starttls
&lt;span class="nv"&gt;SMTP_USERNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-email@gmail.com
&lt;span class="nv"&gt;SMTP_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-app-password&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;# Use Gmail App Password, not your real password&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Generating a Secure ADMIN_TOKEN with Argon2id (2026&amp;nbsp;Standard)&lt;/h3&gt;
&lt;p&gt;The Vaultwarden admin panel is protected by a token hashed with Argon2id — the current password-hashing standard that won the Password Hashing Competition. Here is how to generate&amp;nbsp;one:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c1"&gt;# generate-admin-token.sh — Generate an Argon2id ADMIN_TOKEN for Vaultwarden&lt;/span&gt;
&lt;span class="c1"&gt;# Requires: argon2 CLI (apt install argon2 / brew install argon2)&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Generating Vaultwarden ADMIN_TOKEN...&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Enter your desired admin password (input hidden):&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;read&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;ADMIN_PASSWORD
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;

&lt;span class="c1"&gt;# Generate a random 48-byte salt&lt;/span&gt;
&lt;span class="nv"&gt;SALT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;openssl&lt;span class="w"&gt; &lt;/span&gt;rand&lt;span class="w"&gt; &lt;/span&gt;-base64&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;48&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Hash with Argon2id: 64 MB memory, 3 iterations, 4 parallelism&lt;/span&gt;
&lt;span class="nv"&gt;HASH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$ADMIN_PASSWORD&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;argon2&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$SALT&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-id&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;19&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-e&lt;span class="k"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Add this to your .env file:&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;ADMIN_TOKEN=&amp;#39;&lt;/span&gt;&lt;span class="nv"&gt;$HASH&lt;/span&gt;&lt;span class="s2"&gt;&amp;#39;&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;⚠️  Save your admin password somewhere secure. You cannot recover it.&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you do not&amp;nbsp;have &lt;code&gt;argon2&lt;/code&gt; &lt;span class="caps"&gt;CLI&lt;/span&gt; installed, you can generate the token using the Vaultwarden container&amp;nbsp;itself:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Alternative: Generate using Docker&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;--rm&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;vaultwarden/server&lt;span class="w"&gt; &lt;/span&gt;/vaultwarden&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;hash&lt;/span&gt;
&lt;span class="c1"&gt;# Enter your desired password when prompted&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;First Start &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; Health&amp;nbsp;Check&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Start the stack&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d

&lt;span class="c1"&gt;# Check container health&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;ps
&lt;span class="c1"&gt;# Expected: vaultwarden  Up 10 seconds (healthy)&lt;/span&gt;

&lt;span class="c1"&gt;# Check logs&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;logs&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;vaultwarden
&lt;span class="c1"&gt;# Look for: &amp;quot;Starting Vaultwarden&amp;quot; and &amp;quot;Listening on 0.0.0.0:80&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Creating the First Admin&amp;nbsp;Account&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Navigate&amp;nbsp;to &lt;code&gt;https://vault.yourdomain.com/admin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Enter your ADMIN_TOKEN (the plaintext password, not the&amp;nbsp;hash)&lt;/li&gt;
&lt;li&gt;Go to &lt;strong&gt;Users&lt;/strong&gt; → &lt;strong&gt;Invite&amp;nbsp;User&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Enter your email address and send the&amp;nbsp;invitation&lt;/li&gt;
&lt;li&gt;Open the invitation link and create your master&amp;nbsp;password&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Immediately&lt;/strong&gt; disable open&amp;nbsp;registration:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# In your .env or docker-compose.yml:&lt;/span&gt;
&lt;span class="nv"&gt;SIGNUPS_ALLOWED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;--force-recreate
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then verify by&amp;nbsp;visiting &lt;code&gt;https://vault.yourdomain.com/&lt;/code&gt; — you should see a login page, not a signup&amp;nbsp;form.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Reverse Proxy Integration (Choose Your&amp;nbsp;Path)&lt;/h2&gt;
&lt;p&gt;Vaultwarden requires &lt;span class="caps"&gt;HTTPS&lt;/span&gt;. Choose one of the four options&amp;nbsp;below.&lt;/p&gt;
&lt;h3&gt;Option A: Nginx Proxy Manager (Most&amp;nbsp;Beginner-Friendly)&lt;/h3&gt;
&lt;p&gt;&lt;span class="sp-brand nginx"&gt;Nginx Proxy Manager&lt;/span&gt; (&lt;span class="caps"&gt;NPM&lt;/span&gt;) provides a web &lt;span class="caps"&gt;UI&lt;/span&gt; for managing proxy hosts and &lt;span class="caps"&gt;SSL&lt;/span&gt; certificates. If you already run &lt;span class="caps"&gt;NPM&lt;/span&gt;, add a new proxy&amp;nbsp;host:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Add to your existing docker-compose.yml with NPM&lt;/span&gt;
&lt;span class="c1"&gt;# Ensure vaultwarden and npm share a Docker network&lt;/span&gt;
&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;external&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;# Created by NPM or manually: docker network create proxy&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;vaultwarden&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# ... (same as above) ...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;proxy&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Remove the ports section entirely — NPM will reach it via container name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the &lt;span class="caps"&gt;NPM&lt;/span&gt; web &lt;span class="caps"&gt;UI&lt;/span&gt;:
1. &lt;strong&gt;Proxy Hosts&lt;/strong&gt; → &lt;strong&gt;Add Proxy Host&lt;/strong&gt;
2.&amp;nbsp;Domain: &lt;code&gt;vault.yourdomain.com&lt;/code&gt;
3. Forward&amp;nbsp;Hostname: &lt;code&gt;vaultwarden&lt;/code&gt; (Docker container name)
4. Forward&amp;nbsp;Port: &lt;code&gt;80&lt;/code&gt;
5. &lt;strong&gt;&lt;span class="caps"&gt;SSL&lt;/span&gt;&lt;/strong&gt; tab → Request a new &lt;span class="caps"&gt;SSL&lt;/span&gt; certificate → Force &lt;span class="caps"&gt;SSL&lt;/span&gt;
6. &lt;strong&gt;Advanced&lt;/strong&gt; tab →&amp;nbsp;Paste:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# WebSocket support for live sync&lt;/span&gt;
&lt;span class="k"&gt;location&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/notifications/hub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;proxy_pass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;http://vaultwarden:3012&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;proxy_http_version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s"&gt;.1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;proxy_set_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;Upgrade&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$http_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;proxy_set_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;Connection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;upgrade&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For full &lt;span class="caps"&gt;NPM&lt;/span&gt; setup, see our &lt;a href="/2026/06/nginx-proxy-manager-docker-compose/"&gt;Nginx Proxy Manager Docker Compose guide&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Option B: Traefik (Labels-Based,&amp;nbsp;Modern)&lt;/h3&gt;
&lt;p&gt;&lt;span class="sp-brand traefik"&gt;Traefik&lt;/span&gt; uses Docker labels for configuration — no separate config&amp;nbsp;files:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;vaultwarden&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;vaultwarden/server:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# ... volumes and env as above ...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;traefik&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.enable=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.vaultwarden.rule=Host(`vault.yourdomain.com`)&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.vaultwarden.entrypoints=websecure&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.vaultwarden.tls.certresolver=letsencrypt&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.services.vaultwarden.loadbalancer.server.port=80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# WebSocket&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.vaultwarden-websocket.rule=Host(`vault.yourdomain.com`)&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;PathPrefix(`/notifications/hub`)&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.vaultwarden-websocket.entrypoints=websecure&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.vaultwarden-websocket.tls.certresolver=letsencrypt&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.services.vaultwarden-websocket.loadbalancer.server.port=3012&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;traefik&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;external&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For the full comparison of reverse proxies, see our &lt;a href="/2026/06/traefik-vs-nginx-proxy-manager-vs-caddy-homelab-2026/"&gt;Traefik vs &lt;span class="caps"&gt;NPM&lt;/span&gt; vs Caddy guide&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Option C: Caddy (Simplest&amp;nbsp;Config)&lt;/h3&gt;
&lt;p&gt;&lt;span class="sp-brand caddy"&gt;Caddy&lt;/span&gt; handles &lt;span class="caps"&gt;TLS&lt;/span&gt; automatically with no configuration for the&amp;nbsp;cert:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="gh"&gt;#&lt;/span&gt; Caddyfile
vault.yourdomain.com {
    reverse_proxy vaultwarden:80
    handle_path /notifications/hub {
        reverse_proxy vaultwarden:3012
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That is it. Caddy obtains and renews Let&amp;#8217;s Encrypt certificates with zero additional&amp;nbsp;config.&lt;/p&gt;
&lt;h3&gt;Option D: Cloudflare Tunnel (No Port&amp;nbsp;Forwarding)&lt;/h3&gt;
&lt;p&gt;If you are behind &lt;span class="caps"&gt;CGNAT&lt;/span&gt; or cannot open ports, &lt;span class="sp-brand cloudflare"&gt;Cloudflare Tunnel&lt;/span&gt; is the best&amp;nbsp;option:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Add to your docker-compose.yml&lt;/span&gt;
&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;cloudflared&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;cloudflare/cloudflared:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;tunnel run&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TUNNEL_TOKEN=${CF_TUNNEL_TOKEN}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;proxy&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the Cloudflare Zero Trust dashboard:
1. Create a tunnel →&amp;nbsp;point &lt;code&gt;vault.yourdomain.com&lt;/code&gt; to &lt;code&gt;http://vaultwarden:80&lt;/code&gt;
2. Enable &lt;strong&gt;NoTLSVerify&lt;/strong&gt; (traffic between cloudflared and Vaultwarden is local)
3. Add an Application Policy for email-based access&amp;nbsp;control&lt;/p&gt;
&lt;p&gt;For a complete guide, see our &lt;a href="/2026/06/cloudflare-tunnel-homelab/"&gt;Cloudflare Tunnel Homelab setup&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Comparison Table: Reverse Proxy for&amp;nbsp;Vaultwarden&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;NPM&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Traefik&lt;/th&gt;
&lt;th&gt;Caddy&lt;/th&gt;
&lt;th&gt;Cloudflare Tunnel&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Web &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅ (dashboard)&lt;/td&gt;
&lt;td&gt;❌ (Caddyfile)&lt;/td&gt;
&lt;td&gt;✅ (Zero Trust dash)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Auto &lt;span class="caps"&gt;TLS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;✅ (Let&amp;#8217;s Encrypt)&lt;/td&gt;
&lt;td&gt;✅ (Let&amp;#8217;s Encrypt)&lt;/td&gt;
&lt;td&gt;✅ (Zero-config!)&lt;/td&gt;
&lt;td&gt;✅ (Cloudflare edge)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Config format&lt;/td&gt;
&lt;td&gt;Web form&lt;/td&gt;
&lt;td&gt;Docker labels&lt;/td&gt;
&lt;td&gt;Caddyfile&lt;/td&gt;
&lt;td&gt;Dashboard&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WebSocket support&lt;/td&gt;
&lt;td&gt;Manual config&lt;/td&gt;
&lt;td&gt;Labels&lt;/td&gt;
&lt;td&gt;Caddyfile lines&lt;/td&gt;
&lt;td&gt;Automatic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Port forwarding required&lt;/td&gt;
&lt;td&gt;Yes (80/443)&lt;/td&gt;
&lt;td&gt;Yes (80/443)&lt;/td&gt;
&lt;td&gt;Yes (80/443)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;No&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Works behind &lt;span class="caps"&gt;CGNAT&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Learning curve&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Low-Medium&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Passkeys &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; &lt;span class="caps"&gt;FIDO2&lt;/span&gt; Support (2026&amp;nbsp;Update)&lt;/h2&gt;
&lt;p&gt;Passkeys — the passwordless &lt;span class="caps"&gt;FIDO2&lt;/span&gt;/WebAuthn standard — are now the default authentication method on iOS, Android, and major browsers. Vaultwarden has supported WebAuthn since 2023, and as of 2026, the implementation is&amp;nbsp;production-stable.&lt;/p&gt;
&lt;h3&gt;Enabling WebAuthn in&amp;nbsp;Vaultwarden&lt;/h3&gt;
&lt;p&gt;No special config is needed — WebAuthn is enabled by default. What you&amp;nbsp;need:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A domain with valid &lt;span class="caps"&gt;HTTPS&lt;/span&gt; (WebAuthn requires a secure&amp;nbsp;context)&lt;/li&gt;
&lt;li&gt;A &lt;span class="caps"&gt;FIDO2&lt;/span&gt; security key (YubiKey, Google Titan, Nitrokey) &lt;strong&gt;or&lt;/strong&gt; a platform authenticator (Windows Hello, Apple Touch &lt;span class="caps"&gt;ID&lt;/span&gt; / Face &lt;span class="caps"&gt;ID&lt;/span&gt;, Android&amp;nbsp;biometric)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Registering a YubiKey or&amp;nbsp;Passkey&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Log in to your Vaultwarden web vault&amp;nbsp;at &lt;code&gt;https://vault.yourdomain.com&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Go to &lt;strong&gt;Settings&lt;/strong&gt; → &lt;strong&gt;Security&lt;/strong&gt; → &lt;strong&gt;Two-step&amp;nbsp;Login&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Under &lt;strong&gt;&lt;span class="caps"&gt;FIDO2&lt;/span&gt; WebAuthn&lt;/strong&gt;, click &lt;strong&gt;Manage&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Enter your master password to&amp;nbsp;confirm&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Add Key&lt;/strong&gt; → give it a name (e.g., &amp;#8220;YubiKey 5C &lt;span class="caps"&gt;NFC&lt;/span&gt;&amp;#8221;)&lt;/li&gt;
&lt;li&gt;Insert your security key and tap it when&amp;nbsp;prompted&lt;/li&gt;
&lt;li&gt;Optional: repeat for a backup&amp;nbsp;key&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For platform passkeys (no hardware key needed):
- On macOS: Safari or Chrome → Touch &lt;span class="caps"&gt;ID&lt;/span&gt; will be offered
- On Windows: Edge or Chrome → Windows Hello &lt;span class="caps"&gt;PIN&lt;/span&gt; or fingerprint
- On Android: Chrome → fingerprint or screen lock
- On iOS: Safari → Face &lt;span class="caps"&gt;ID&lt;/span&gt; or Touch &lt;span class="caps"&gt;ID&lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;Backup Codes and Recovery&amp;nbsp;Strategy&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Critical:&lt;/strong&gt; If you lose all your WebAuthn devices, your vault is locked. Vaultwarden generates one-time recovery codes when you enable any &lt;span class="caps"&gt;2FA&lt;/span&gt;&amp;nbsp;method:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;After enabling &lt;span class="caps"&gt;FIDO2&lt;/span&gt;, click &lt;strong&gt;View Recovery&amp;nbsp;Codes&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Print them.&lt;/strong&gt; Do not store them digitally in the same&amp;nbsp;device.&lt;/li&gt;
&lt;li&gt;Store one copy in a fireproof safe, one copy with a trusted family&amp;nbsp;member&lt;/li&gt;
&lt;li&gt;Test one recovery code to verify they&amp;nbsp;work&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Security Hardening (Don&amp;#8217;t Skip&amp;nbsp;This)&lt;/h2&gt;
&lt;p&gt;A password manager that is not hardened is a liability. Follow every&amp;nbsp;step.&lt;/p&gt;
&lt;h3&gt;Disable Open&amp;nbsp;Registration&lt;/h3&gt;
&lt;p&gt;After creating your user account, lock&amp;nbsp;registration:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# In .env:&lt;/span&gt;
&lt;span class="nv"&gt;SIGNUPS_ALLOWED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;
&lt;span class="nv"&gt;INVITATIONS_ALLOWED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Enable &lt;span class="caps"&gt;2FA&lt;/span&gt; / &lt;span class="caps"&gt;TOTP&lt;/span&gt; for&amp;nbsp;Admin&lt;/h3&gt;
&lt;p&gt;Vaultwarden supports &lt;span class="caps"&gt;TOTP&lt;/span&gt; (time-based one-time passwords) natively — and unlike Bitwarden Cloud, it is&amp;nbsp;free:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Web vault → &lt;strong&gt;Settings&lt;/strong&gt; → &lt;strong&gt;Security&lt;/strong&gt; → &lt;strong&gt;Two-step&amp;nbsp;Login&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Under &lt;strong&gt;Authenticator App&lt;/strong&gt;, click &lt;strong&gt;Manage&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Scan the &lt;span class="caps"&gt;QR&lt;/span&gt; code with &lt;span class="sp-brand"&gt;Aegis&lt;/span&gt; (Android), &lt;span class="sp-brand"&gt;Raivo&lt;/span&gt; (iOS), or &lt;span class="sp-brand"&gt;&lt;span class="caps"&gt;2FAS&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Enter the 6-digit code to&amp;nbsp;confirm&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Save recovery&amp;nbsp;codes!&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Fail2Ban Integration (Docker-Aware&amp;nbsp;Config)&lt;/h3&gt;
&lt;p&gt;&lt;span class="sp-brand"&gt;Fail2Ban&lt;/span&gt; blocks IPs after repeated failed login attempts. For a Docker&amp;nbsp;deployment:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# /etc/fail2ban/jail.local — Add this block:&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;vaultwarden&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;enabled&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;span class="nv"&gt;port&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;,443,3012
&lt;span class="nv"&gt;filter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;vaultwarden
&lt;span class="nv"&gt;logpath&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/opt/vaultwarden/vw-data/vaultwarden.log
&lt;span class="nv"&gt;maxretry&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;
&lt;span class="nv"&gt;findtime&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;300&lt;/span&gt;
&lt;span class="nv"&gt;bantime&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3600&lt;/span&gt;
&lt;span class="nv"&gt;chain&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;DOCKER-USER
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# /etc/fail2ban/filter.d/vaultwarden.conf&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;Definition&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;failregex&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;^.*Username&lt;span class="w"&gt; &lt;/span&gt;or&lt;span class="w"&gt; &lt;/span&gt;password&lt;span class="w"&gt; &lt;/span&gt;is&lt;span class="w"&gt; &lt;/span&gt;incorrect&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Try&lt;span class="w"&gt; &lt;/span&gt;again&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;IP:&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;ADDR&amp;gt;.*$
&lt;span class="w"&gt;            &lt;/span&gt;^.*Invalid&lt;span class="w"&gt; &lt;/span&gt;admin&lt;span class="w"&gt; &lt;/span&gt;token&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;IP:&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;ADDR&amp;gt;.*$
&lt;span class="w"&gt;            &lt;/span&gt;^.*2FA&lt;span class="w"&gt; &lt;/span&gt;token&lt;span class="w"&gt; &lt;/span&gt;not&lt;span class="w"&gt; &lt;/span&gt;provided.*&lt;span class="w"&gt; &lt;/span&gt;IP:&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;ADDR&amp;gt;.*$
&lt;span class="nv"&gt;ignoreregex&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Verify the filter works:&lt;/span&gt;
fail2ban-regex&lt;span class="w"&gt; &lt;/span&gt;/opt/vaultwarden/vw-data/vaultwarden.log&lt;span class="w"&gt; &lt;/span&gt;/etc/fail2ban/filter.d/vaultwarden.conf
&lt;span class="c1"&gt;# Restart Fail2Ban:&lt;/span&gt;
systemctl&lt;span class="w"&gt; &lt;/span&gt;restart&lt;span class="w"&gt; &lt;/span&gt;fail2ban
&lt;span class="c1"&gt;# Check status:&lt;/span&gt;
fail2ban-client&lt;span class="w"&gt; &lt;/span&gt;status&lt;span class="w"&gt; &lt;/span&gt;vaultwarden
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Firewall Rules (&lt;span class="caps"&gt;UFW&lt;/span&gt;)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Only allow 443 and 80 from anywhere (for reverse proxy)&lt;/span&gt;
ufw&lt;span class="w"&gt; &lt;/span&gt;allow&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;443&lt;/span&gt;/tcp
ufw&lt;span class="w"&gt; &lt;/span&gt;allow&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;/tcp
&lt;span class="c1"&gt;# Block Vaultwarden&amp;#39;s internal port from external access&lt;/span&gt;
ufw&lt;span class="w"&gt; &lt;/span&gt;deny&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8082&lt;/span&gt;/tcp
&lt;span class="c1"&gt;# Only allow SSH from your local network&lt;/span&gt;
ufw&lt;span class="w"&gt; &lt;/span&gt;allow&lt;span class="w"&gt; &lt;/span&gt;from&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.1.0/24&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;any&lt;span class="w"&gt; &lt;/span&gt;port&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;22&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Disable Unused&amp;nbsp;Features&lt;/h3&gt;
&lt;p&gt;If you do not use certain features, disable them to reduce attack&amp;nbsp;surface:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# In .env:&lt;/span&gt;
&lt;span class="nv"&gt;SENDS_ALLOWED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="c1"&gt;# If you don&amp;#39;t use Bitwarden Send&lt;/span&gt;
&lt;span class="nv"&gt;EMERGENCY_ACCESS_ALLOWED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# If you don&amp;#39;t use emergency contacts&lt;/span&gt;
&lt;span class="nv"&gt;ORG_CREATION_USERS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;none&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="c1"&gt;# If you&amp;#39;re the only user&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Security&amp;nbsp;Checklist&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Done?&lt;/th&gt;
&lt;th&gt;Risk if Skipped&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Disable open registration&lt;/td&gt;
&lt;td&gt;☐&lt;/td&gt;
&lt;td&gt;Anyone can create accounts on your instance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Enable &lt;span class="caps"&gt;TOTP&lt;/span&gt; &lt;span class="caps"&gt;2FA&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;☐&lt;/td&gt;
&lt;td&gt;Master password is the sole authentication factor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Enable &lt;span class="caps"&gt;FIDO2&lt;/span&gt; WebAuthn&lt;/td&gt;
&lt;td&gt;☐&lt;/td&gt;
&lt;td&gt;No phishing-resistant authentication&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Configure Fail2Ban&lt;/td&gt;
&lt;td&gt;☐&lt;/td&gt;
&lt;td&gt;Brute-force attempts go undetected&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Restrict firewall ports&lt;/td&gt;
&lt;td&gt;☐&lt;/td&gt;
&lt;td&gt;Vaultwarden directly exposed to internet&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Save recovery codes offline&lt;/td&gt;
&lt;td&gt;☐&lt;/td&gt;
&lt;td&gt;Locked out of vault permanently&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Disable unused features&lt;/td&gt;
&lt;td&gt;☐&lt;/td&gt;
&lt;td&gt;Larger attack surface&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Disable password hints&lt;/td&gt;
&lt;td&gt;☐&lt;/td&gt;
&lt;td&gt;Hints leak password structure to attackers&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Client Setup &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;Migration&lt;/h2&gt;
&lt;h3&gt;Browser Extension&amp;nbsp;Configuration&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Install the &lt;strong&gt;Bitwarden&lt;/strong&gt; browser extension (Firefox Add-ons / Chrome Web&amp;nbsp;Store)&lt;/li&gt;
&lt;li&gt;Open the extension → &lt;strong&gt;Settings&lt;/strong&gt; (gear icon) → &lt;strong&gt;Self-hosted&amp;nbsp;Environment&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;Server &lt;span class="caps"&gt;URL&lt;/span&gt;&lt;/strong&gt;&amp;nbsp;to &lt;code&gt;https://vault.yourdomain.com&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Enter your email and master password → &lt;strong&gt;Log&amp;nbsp;in&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Desktop&amp;nbsp;App&lt;/h3&gt;
&lt;p&gt;The Bitwarden desktop app (Windows, macOS, Linux) supports custom server URLs:
- &lt;strong&gt;Settings&lt;/strong&gt; → &lt;strong&gt;Self-hosted Environment&lt;/strong&gt; → enter your &lt;span class="caps"&gt;URL&lt;/span&gt;
- The app also supports biometric unlock (Windows Hello, Touch &lt;span class="caps"&gt;ID&lt;/span&gt;) once&amp;nbsp;configured&lt;/p&gt;
&lt;h3&gt;Mobile Apps (iOS,&amp;nbsp;Android)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Download &lt;strong&gt;Bitwarden&lt;/strong&gt; from the App Store or Google&amp;nbsp;Play&lt;/li&gt;
&lt;li&gt;Tap the gear icon on the login screen → &lt;strong&gt;Self-hosted Environment&lt;/strong&gt; → enter your &lt;span class="caps"&gt;URL&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Enable biometric unlock in Settings after&amp;nbsp;login&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Migrating from Bitwarden Cloud / 1Password /&amp;nbsp;Chrome&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;From Bitwarden Cloud:&lt;/strong&gt;
1. Log in to your Bitwarden Cloud vault
2. &lt;strong&gt;Tools&lt;/strong&gt; → &lt;strong&gt;Export Vault&lt;/strong&gt;&amp;nbsp;→ &lt;code&gt;.json&lt;/code&gt; (unencrypted) — do this on a trusted device
3. Log in to your Vaultwarden instance
4. &lt;strong&gt;Tools&lt;/strong&gt; → &lt;strong&gt;Import Data&lt;/strong&gt; → Bitwarden (json) → select&amp;nbsp;file&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;From 1Password:&lt;/strong&gt;
1. 1Password desktop app → &lt;strong&gt;File&lt;/strong&gt; → &lt;strong&gt;Export&lt;/strong&gt;&amp;nbsp;→ &lt;code&gt;.1pux&lt;/code&gt; or &lt;code&gt;.csv&lt;/code&gt;
2. In Vaultwarden: &lt;strong&gt;Tools&lt;/strong&gt; → &lt;strong&gt;Import Data&lt;/strong&gt; → 1Password 1pux or&amp;nbsp;csv&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;From Chrome/Edge password manager:&lt;/strong&gt;&amp;nbsp;1. &lt;code&gt;chrome://password-manager/settings&lt;/code&gt; → &lt;strong&gt;Export passwords&lt;/strong&gt;&amp;nbsp;→ &lt;code&gt;.csv&lt;/code&gt;
2. In Vaultwarden: &lt;strong&gt;Tools&lt;/strong&gt; → &lt;strong&gt;Import Data&lt;/strong&gt; → Chrome&amp;nbsp;(csv)&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Security note:&lt;/strong&gt; After import, &lt;strong&gt;securely delete&lt;/strong&gt; the unencrypted export file. On&amp;nbsp;Linux: &lt;code&gt;shred -u export.json&lt;/code&gt;. On&amp;nbsp;macOS: &lt;code&gt;rm -P export.json&lt;/code&gt;. On Windows:&amp;nbsp;use &lt;code&gt;cipher /w&lt;/code&gt; or a file shredder&amp;nbsp;tool.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;&lt;span class="caps"&gt;CLI&lt;/span&gt; &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; Vaultwarden &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;The official Bitwarden &lt;span class="caps"&gt;CLI&lt;/span&gt;&amp;nbsp;(&lt;code&gt;bw&lt;/code&gt;) works with&amp;nbsp;Vaultwarden:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Install&lt;/span&gt;
npm&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-g&lt;span class="w"&gt; &lt;/span&gt;@bitwarden/cli
&lt;span class="c1"&gt;# Or: brew install bitwarden-cli&lt;/span&gt;

&lt;span class="c1"&gt;# Configure custom server&lt;/span&gt;
bw&lt;span class="w"&gt; &lt;/span&gt;config&lt;span class="w"&gt; &lt;/span&gt;server&lt;span class="w"&gt; &lt;/span&gt;https://vault.yourdomain.com

&lt;span class="c1"&gt;# Login&lt;/span&gt;
bw&lt;span class="w"&gt; &lt;/span&gt;login
&lt;span class="c1"&gt;# Enter email and master password&lt;/span&gt;

&lt;span class="c1"&gt;# Unlock session&lt;/span&gt;
&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;BW_SESSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;bw&lt;span class="w"&gt; &lt;/span&gt;unlock&lt;span class="w"&gt; &lt;/span&gt;--raw&lt;span class="k"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# List all items&lt;/span&gt;
bw&lt;span class="w"&gt; &lt;/span&gt;list&lt;span class="w"&gt; &lt;/span&gt;items&lt;span class="w"&gt; &lt;/span&gt;--session&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$BW_SESSION&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Backup &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; Disaster&amp;nbsp;Recovery&lt;/h2&gt;
&lt;p&gt;Your password vault is the single most important dataset in your homelab. Back it&amp;nbsp;up.&lt;/p&gt;
&lt;h3&gt;What to Back&amp;nbsp;Up&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Data&lt;/th&gt;
&lt;th&gt;Location&lt;/th&gt;
&lt;th&gt;Criticality&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SQLite database&lt;/td&gt;
&lt;td&gt;&lt;code&gt;vw-data/db.sqlite3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;🔴 Critical — all vault data, users, orgs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Attachments&lt;/td&gt;
&lt;td&gt;&lt;code&gt;vw-data/attachments/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;🟡 Important — user-uploaded files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Config&lt;/td&gt;
&lt;td&gt;&lt;code&gt;vw-data/config.json&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;🟡 Important — server config, org keys&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RSA&lt;/span&gt; key pair&lt;/td&gt;
&lt;td&gt;&lt;code&gt;vw-data/rsa_key.pem&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;🟡 Important — used for token signing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Icon cache&lt;/td&gt;
&lt;td&gt;&lt;code&gt;vw-data/icon_cache/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;🟢 Optional — regenerates automatically&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Docker Compose&lt;/td&gt;
&lt;td&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;🟡 Important — your deployment config&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;.env file&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.env&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;🔴 Critical — contains ADMIN_TOKEN hash&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fail2Ban configs&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/etc/fail2ban/jail.local&lt;/code&gt;, &lt;code&gt;filter.d/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;🟢 Optional — rebuildable&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Minimum viable&amp;nbsp;backup:&lt;/strong&gt; &lt;code&gt;vw-data/db.sqlite3&lt;/code&gt; + &lt;code&gt;vw-data/attachments/&lt;/code&gt; + &lt;code&gt;docker-compose.yml&lt;/code&gt; + &lt;code&gt;.env&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;Automated Backup with&amp;nbsp;Restic&lt;/h3&gt;
&lt;p&gt;&lt;span class="sp-brand restic"&gt;Restic&lt;/span&gt; is our recommended backup tool for Vaultwarden. Here is a Docker Compose&amp;nbsp;sidecar:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Add to your docker-compose.yml&lt;/span&gt;
&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;vaultwarden-backup&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;restic/restic:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;vaultwarden-backup&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./vw-data:/data:ro&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="c1"&gt;# Read-only mount — Vaultwarden data&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./restic-cache:/cache&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./restic-password:/password:ro&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;RESTIC_REPOSITORY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;s3:s3.amazonaws.com/your-bucket/vaultwarden&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;RESTIC_PASSWORD_FILE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/password/restic-password.txt&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;AWS_ACCESS_KEY_ID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${AWS_ACCESS_KEY_ID}&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;AWS_SECRET_ACCESS_KEY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${AWS_SECRET_ACCESS_KEY}&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;entrypoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="no"&gt;/bin/sh -c &amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="no"&gt;while true; do&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="no"&gt;restic backup /data \&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="no"&gt;--exclude &amp;#39;icon_cache&amp;#39; \&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="no"&gt;--host vaultwarden \&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="no"&gt;--tag automated \&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="no"&gt;&amp;amp;&amp;amp; restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune \&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="no"&gt;&amp;amp;&amp;amp; restic check;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="no"&gt;sleep 86400;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="no"&gt;done&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="no"&gt;&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Offsite Backup&amp;nbsp;Strategy&lt;/h3&gt;
&lt;p&gt;A backup on the same physical machine is not a backup. Follow at minimum a 3-copy&amp;nbsp;strategy:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tier&lt;/th&gt;
&lt;th&gt;Destination&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;th&gt;Latency&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Local &lt;span class="caps"&gt;NAS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Synology / TrueNAS / Unraid &lt;span class="caps"&gt;SMB&lt;/span&gt; share&lt;/td&gt;
&lt;td&gt;$0 (existing hardware)&lt;/td&gt;
&lt;td&gt;&amp;lt;1 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Offsite S3&lt;/td&gt;
&lt;td&gt;Backblaze B2, Cloudflare R2, Hetzner Storage Box&lt;/td&gt;
&lt;td&gt;$0–$5/mo&lt;/td&gt;
&lt;td&gt;20–80 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cold storage&lt;/td&gt;
&lt;td&gt;External &lt;span class="caps"&gt;USB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt; rotated monthly&lt;/td&gt;
&lt;td&gt;$30 one-time&lt;/td&gt;
&lt;td&gt;Manual&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For a complete 3-2-1 backup framework, see our &lt;a href="/2026/06/self-hosted-backup-strategy-homelab-2026/"&gt;Self-Hosted Backup Strategy guide&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Restore&amp;nbsp;Procedure&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# 1. Stop Vaultwarden&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;stop&lt;span class="w"&gt; &lt;/span&gt;vaultwarden

&lt;span class="c1"&gt;# 2. Restore from latest Restic snapshot&lt;/span&gt;
restic&lt;span class="w"&gt; &lt;/span&gt;restore&lt;span class="w"&gt; &lt;/span&gt;latest&lt;span class="w"&gt; &lt;/span&gt;--target&lt;span class="w"&gt; &lt;/span&gt;/tmp/vaultwarden-restore

&lt;span class="c1"&gt;# 3. Copy restored data&lt;/span&gt;
cp&lt;span class="w"&gt; &lt;/span&gt;/tmp/vaultwarden-restore/db.sqlite3&lt;span class="w"&gt; &lt;/span&gt;./vw-data/
cp&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="w"&gt; &lt;/span&gt;/tmp/vaultwarden-restore/attachments/&lt;span class="w"&gt; &lt;/span&gt;./vw-data/
cp&lt;span class="w"&gt; &lt;/span&gt;/tmp/vaultwarden-restore/config.json&lt;span class="w"&gt; &lt;/span&gt;./vw-data/
cp&lt;span class="w"&gt; &lt;/span&gt;/tmp/vaultwarden-restore/rsa_key.pem&lt;span class="w"&gt; &lt;/span&gt;./vw-data/

&lt;span class="c1"&gt;# 4. Fix permissions&lt;/span&gt;
chown&lt;span class="w"&gt; &lt;/span&gt;-R&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;:1000&lt;span class="w"&gt; &lt;/span&gt;./vw-data/

&lt;span class="c1"&gt;# 5. Start Vaultwarden&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;vaultwarden

&lt;span class="c1"&gt;# 6. Verify&lt;/span&gt;
curl&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;https://vault.yourdomain.com&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Vaultwarden&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Backup&amp;nbsp;Verification&lt;/h3&gt;
&lt;p&gt;A backup you have never restored is Schrödinger&amp;#8217;s backup — it is both working and not working until you test it. At&amp;nbsp;minimum:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Monthly: restore to a test directory and verify SQLite integrity&lt;/span&gt;
restic&lt;span class="w"&gt; &lt;/span&gt;restore&lt;span class="w"&gt; &lt;/span&gt;latest&lt;span class="w"&gt; &lt;/span&gt;--target&lt;span class="w"&gt; &lt;/span&gt;/tmp/vw-test
sqlite3&lt;span class="w"&gt; &lt;/span&gt;/tmp/vw-test/db.sqlite3&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;PRAGMA integrity_check;&amp;quot;&lt;/span&gt;
&lt;span class="c1"&gt;# Expected: &amp;quot;ok&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Monitoring &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;Alerts&lt;/h2&gt;
&lt;p&gt;If Vaultwarden goes down, you need to know before you need a&amp;nbsp;password.&lt;/p&gt;
&lt;h3&gt;Uptime Kuma Push&amp;nbsp;Monitor&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Add to Uptime Kuma: Push monitor → Push URL&lt;/span&gt;
&lt;span class="c1"&gt;# Then add to Vaultwarden&amp;#39;s health check:&lt;/span&gt;
curl&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;https://uptime.yourdomain.com/api/push/YOUR_PUSH_TOKEN?status&lt;span class="o"&gt;=&lt;/span&gt;up&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Vaultwarden+OK
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Or use Uptime Kuma&amp;#8217;s &lt;span class="caps"&gt;HTTP&lt;/span&gt;(s) monitor to&amp;nbsp;check &lt;code&gt;https://vault.yourdomain.com&lt;/code&gt; every 60 seconds. See our &lt;a href="/2026/06/uptime-kuma-docker-compose-homelab-2026/"&gt;Uptime Kuma Docker Compose guide&lt;/a&gt; for full&amp;nbsp;setup.&lt;/p&gt;
&lt;h3&gt;Prometheus&amp;nbsp;Metrics&lt;/h3&gt;
&lt;p&gt;Vaultwarden can expose a Prometheus metrics&amp;nbsp;endpoint:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# .env:&lt;/span&gt;
&lt;span class="nv"&gt;EXPERIMENTAL_CLIENT_FEATURE_FLAGS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;fido2-vault-credentials
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For a full monitoring stack, see our &lt;a href="/2026/06/grafana-prometheus-setup/"&gt;Grafana + Prometheus setup&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Upgrading&amp;nbsp;Vaultwarden&lt;/h2&gt;
&lt;h3&gt;Safe Update&amp;nbsp;Procedure&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# 1. Backup (always)&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;stop&lt;span class="w"&gt; &lt;/span&gt;vaultwarden
cp&lt;span class="w"&gt; &lt;/span&gt;./vw-data/db.sqlite3&lt;span class="w"&gt; &lt;/span&gt;./vw-data/db.sqlite3.backup-&lt;span class="k"&gt;$(&lt;/span&gt;date&lt;span class="w"&gt; &lt;/span&gt;+%Y%m%d&lt;span class="k"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 2. Pull and recreate&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;pull&lt;span class="w"&gt; &lt;/span&gt;vaultwarden
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;vaultwarden

&lt;span class="c1"&gt;# 3. Check logs for migration messages&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;logs&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;vaultwarden
&lt;span class="c1"&gt;# Watch for: &amp;quot;Running migrations&amp;quot; and &amp;quot;Migration complete&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Rollback&amp;nbsp;Strategy&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# If something breaks after update:&lt;/span&gt;
&lt;span class="c1"&gt;# 1. Check the release notes — was there a breaking change?&lt;/span&gt;
&lt;span class="c1"&gt;# 2. Pin to previous version in docker-compose.yml:&lt;/span&gt;
&lt;span class="c1"&gt;#    image: vaultwarden/server:1.32.0  (instead of :latest)&lt;/span&gt;
&lt;span class="c1"&gt;# 3. Restore the pre-update database:&lt;/span&gt;
cp&lt;span class="w"&gt; &lt;/span&gt;./vw-data/db.sqlite3.backup-YYYYMMDD&lt;span class="w"&gt; &lt;/span&gt;./vw-data/db.sqlite3
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;vaultwarden
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Troubleshooting Common&amp;nbsp;Issues&lt;/h2&gt;
&lt;h3&gt;&lt;span class="caps"&gt;HTTPS&lt;/span&gt; Errors &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; Web Crypto &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; Browser extension says &amp;#8220;An error has occurred. Failed to&amp;nbsp;fetch.&amp;#8221;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Root cause:&lt;/strong&gt; The Web Crypto &lt;span class="caps"&gt;API&lt;/span&gt; requires &lt;span class="caps"&gt;HTTPS&lt;/span&gt;. You are accessing Vaultwarden over plain &lt;span class="caps"&gt;HTTP&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Configure a reverse proxy with &lt;span class="caps"&gt;TLS&lt;/span&gt;. Even a self-signed certificate on&amp;nbsp;a &lt;code&gt;.local&lt;/code&gt; domain can work, but Let&amp;#8217;s Encrypt via &lt;span class="caps"&gt;NPM&lt;/span&gt;/Traefik/Caddy is the proper&amp;nbsp;solution.&lt;/p&gt;
&lt;h3&gt;Admin Token Not&amp;nbsp;Working&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; &amp;#8220;Invalid admin token&amp;#8221; when accessing&amp;nbsp;/admin.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fixes:&lt;/strong&gt;
1. Ensure you are using the &lt;strong&gt;plaintext password&lt;/strong&gt;, not the Argon2id hash
2.&amp;nbsp;Regenerate: &lt;code&gt;docker compose exec vaultwarden /vaultwarden hash&lt;/code&gt;
3. Check for trailing whitespace&amp;nbsp;in &lt;code&gt;.env&lt;/code&gt; — &lt;code&gt;ADMIN_TOKEN='$argon2...'&lt;/code&gt; not &lt;code&gt;ADMIN_TOKEN='$argon2... '&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;&lt;span class="caps"&gt;SMTP&lt;/span&gt; / Email Not&amp;nbsp;Sending&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; No invitation emails, no verification&amp;nbsp;emails.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fixes:&lt;/strong&gt;
1. Check SMTP_PORT matches security: 587 for &lt;span class="caps"&gt;STARTTLS&lt;/span&gt;, 465 for force_tls
2. For Gmail: you must use an &lt;strong&gt;App Password&lt;/strong&gt;, not your account password
3. Test&amp;nbsp;connectivity: &lt;code&gt;docker compose exec vaultwarden nc -zv smtp.gmail.com 587&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;Mobile Sync&amp;nbsp;Issues&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; Passwords added on desktop don&amp;#8217;t appear on&amp;nbsp;mobile.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fixes:&lt;/strong&gt;
1. Ensure WebSocket is enabled&amp;nbsp;(&lt;code&gt;WEBSOCKET_ENABLED=true&lt;/code&gt;)
2. Verify your reverse proxy passes WebSocket connections (port 3012)
3. Force sync: mobile app → Settings → Sync vault&amp;nbsp;now&lt;/p&gt;
&lt;h3&gt;Database Locked /&amp;nbsp;Corruption&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; Vaultwarden starts but logs &amp;#8220;database is&amp;nbsp;locked.&amp;#8221;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fixes:&lt;/strong&gt;
1. Stop all Vaultwarden&amp;nbsp;processes: &lt;code&gt;docker compose stop&lt;/code&gt;
2. Check SQLite&amp;nbsp;integrity: &lt;code&gt;sqlite3 vw-data/db.sqlite3 "PRAGMA integrity_check;"&lt;/code&gt;
3. If corrupted, restore from backup (you did back up,&amp;nbsp;right?)&lt;/p&gt;
&lt;h3&gt;Passkey Registration&amp;nbsp;Fails&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; WebAuthn registration returns &amp;#8220;The operation failed for an unknown&amp;nbsp;reason.&amp;#8221;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fixes:&lt;/strong&gt;
1. Verify the domain has valid &lt;span class="caps"&gt;HTTPS&lt;/span&gt; (self-signed certs cause WebAuthn failures)
2. The domain&amp;nbsp;in &lt;code&gt;DOMAIN&lt;/code&gt; env var must exactly match the &lt;span class="caps"&gt;URL&lt;/span&gt; in your browser&amp;nbsp;(include &lt;code&gt;https://&lt;/code&gt;)
3. Some browsers require user gesture — click explicitly, do not use auto-focus
4. Safari requires the domain to have a valid certificate in the&amp;nbsp;Keychain&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;&lt;span class="caps"&gt;FAQ&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Is Vaultwarden safe for&amp;nbsp;production?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Yes, with caveats. Vaultwarden is used by tens of thousands of self-hosters. It passes the Bitwarden server test suite. The cryptography is identical — all encryption/decryption happens client-side in the Bitwarden apps. Vaultwarden never sees your master password or decrypted vault. However, it is community-maintained and not officially supported by Bitwarden. For enterprises with compliance requirements (&lt;span class="caps"&gt;SOC2&lt;/span&gt;, &lt;span class="caps"&gt;HIPAA&lt;/span&gt;), use Bitwarden&amp;#8217;s official self-hosted&amp;nbsp;server.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Can I use official Bitwarden apps with&amp;nbsp;Vaultwarden?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Yes. Every official Bitwarden client — browser extension, desktop app (Windows/macOS/Linux), mobile apps (iOS/Android), and &lt;span class="caps"&gt;CLI&lt;/span&gt; — works with Vaultwarden by changing one setting: Server &lt;span class="caps"&gt;URL&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How do I reset the admin&amp;nbsp;token?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you lose your admin password, regenerate the token&amp;nbsp;hash:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;vaultwarden&lt;span class="w"&gt; &lt;/span&gt;/vaultwarden&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;hash&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then&amp;nbsp;update &lt;code&gt;ADMIN_TOKEN&lt;/code&gt; in&amp;nbsp;your &lt;code&gt;.env&lt;/code&gt; and&amp;nbsp;run &lt;code&gt;docker compose up -d&lt;/code&gt;. You do not need the old&amp;nbsp;password.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Does Vaultwarden support&amp;nbsp;passkeys?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Yes. &lt;span class="caps"&gt;FIDO2&lt;/span&gt; WebAuthn (passkeys) is fully supported and enabled by default. You can use hardware security keys (YubiKey, Titan) or platform authenticators (Windows Hello, Touch &lt;span class="caps"&gt;ID&lt;/span&gt;). This is a 2026 strength — many competitors&amp;#8217; self-hosted options still lack passkey&amp;nbsp;support.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Can I run Vaultwarden on a Raspberry&amp;nbsp;Pi?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Yes. Vaultwarden runs comfortably on a &lt;span class="sp-brand raspberry-pi"&gt;Raspberry Pi 4&lt;/span&gt; with 2 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, using approximately 80 &lt;span class="caps"&gt;MB&lt;/span&gt; of memory. For a Pi 3B+, it works but use an external &lt;span class="caps"&gt;SSD&lt;/span&gt; rather than an &lt;span class="caps"&gt;SD&lt;/span&gt; card — SQLite writes will destroy an &lt;span class="caps"&gt;SD&lt;/span&gt; card within&amp;nbsp;months.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How do I migrate from Bitwarden&amp;nbsp;Cloud?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Export your vault&amp;nbsp;as &lt;code&gt;.json&lt;/code&gt; from Bitwarden Cloud (Tools → Export Vault), then import into Vaultwarden (Tools → Import Data). The process takes under two minutes. Securely delete the export file&amp;nbsp;afterward.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What happens if my server&amp;nbsp;dies?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you have a backup&amp;nbsp;of &lt;code&gt;db.sqlite3&lt;/code&gt; and &lt;code&gt;attachments/&lt;/code&gt;, you can restore to any Docker host and be back online in minutes. If you do not have a backup, your data is gone permanently. Zero-knowledge encryption means nobody can recover it — not Vaultwarden&amp;#8217;s developers, not Bitwarden Inc., not your &lt;span class="caps"&gt;VPS&lt;/span&gt; provider. &lt;strong&gt;This is why backup is not&amp;nbsp;optional.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Is &lt;span class="caps"&gt;SSO&lt;/span&gt;&amp;nbsp;supported?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Vaultwarden does not natively support &lt;span class="caps"&gt;SAML&lt;/span&gt; or &lt;span class="caps"&gt;OIDC&lt;/span&gt;. However, you can put &lt;span class="sp-brand authelia"&gt;Authelia&lt;/span&gt; or &lt;span class="sp-brand authentik"&gt;Authentik&lt;/span&gt; in front of Vaultwarden as a reverse proxy middleware for &lt;span class="caps"&gt;SSO&lt;/span&gt;. This protects the login page but does not replace the master password — you still need it to decrypt the vault. For the admin panel specifically, Authelia can gate access behind &lt;span class="caps"&gt;SSO&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Can I share passwords with&amp;nbsp;family?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Yes. Vaultwarden supports Organizations and Collections — the same sharing model as Bitwarden. Create an organization, invite family members by email, and assign passwords to shared collections. Unlike Bitwarden Cloud, there is no per-user fee for&amp;nbsp;organizations.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How do I enable Dark Web&amp;nbsp;monitoring?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Vaultwarden does not have native breach monitoring. Use external tools:
- &lt;strong&gt;Have I Been Pwned&lt;/strong&gt; &lt;span class="caps"&gt;API&lt;/span&gt; (free for individual checks)
- &lt;strong&gt;Bitwarden Watchtower&lt;/strong&gt; (built into clients, works with Vaultwarden)
- &lt;strong&gt;Firefox Monitor&lt;/strong&gt; (free)
- &lt;strong&gt;Google Password Checkup&lt;/strong&gt; (works with exported &lt;span class="caps"&gt;CSV&lt;/span&gt;)&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; Next&amp;nbsp;Steps&lt;/h2&gt;
&lt;p&gt;You now have a production-grade, self-hosted password manager running in your homelab — with &lt;span class="caps"&gt;HTTPS&lt;/span&gt;, two-factor authentication, passkeys, automated backups, intrusion detection, and monitoring. You are no longer paying a subscription for password management, and your vault lives on hardware you&amp;nbsp;control.&lt;/p&gt;
&lt;h3&gt;When to Choose Vaultwarden vs Bitwarden&amp;nbsp;Cloud&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Choose Vaultwarden if&amp;#8230;&lt;/th&gt;
&lt;th&gt;Choose Bitwarden Cloud if&amp;#8230;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;You already run a homelab with Docker&lt;/td&gt;
&lt;td&gt;You want zero maintenance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;You want full data residency control&lt;/td&gt;
&lt;td&gt;You need &lt;span class="caps"&gt;SOC2&lt;/span&gt;/&lt;span class="caps"&gt;HIPAA&lt;/span&gt; compliance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;You manage passwords for 5+ family members&lt;/td&gt;
&lt;td&gt;You don&amp;#8217;t have reliable home internet&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;You want &lt;span class="caps"&gt;TOTP&lt;/span&gt; and attachments for free&lt;/td&gt;
&lt;td&gt;You need official support channels&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;You enjoy self-hosting as a hobby&lt;/td&gt;
&lt;td&gt;You want breach monitoring built in&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Recommended Next&amp;nbsp;Articles&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="/2026/06/self-hosted-backup-strategy-homelab-2026/"&gt;Self-Hosted Backup Strategy for Homelab 2026&lt;/a&gt;&lt;/strong&gt; — The 3-2-1 backup guide. Pair with this article for a complete data safety&amp;nbsp;plan.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="/2026/06/uptime-kuma-docker-compose-homelab-2026/"&gt;Uptime Kuma Docker Compose Setup&lt;/a&gt;&lt;/strong&gt; — Monitor Vaultwarden and every other service from one&amp;nbsp;dashboard.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="/2026/06/traefik-vs-nginx-proxy-manager-vs-caddy-homelab-2026/"&gt;Traefik vs Nginx Proxy Manager vs Caddy&lt;/a&gt;&lt;/strong&gt; — Not sure which reverse proxy? This comparison walks through all three with Docker Compose&amp;nbsp;examples.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="/2026/06/cloudflare-tunnel-homelab/"&gt;Cloudflare Tunnel Homelab Setup&lt;/a&gt;&lt;/strong&gt; — Access Vaultwarden from anywhere without opening a single&amp;nbsp;port.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="/2026/06/self-hosted-password-manager-comparison/"&gt;Self-Hosted Password Manager Comparison&lt;/a&gt;&lt;/strong&gt; — Vaultwarden vs Bitwarden vs KeePassXC vs Passbolt — full feature&amp;nbsp;matrix.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="/2026/06/proxmox-beginner-guide/"&gt;Proxmox Beginner Guide&lt;/a&gt;&lt;/strong&gt; — Run Vaultwarden in a Proxmox &lt;span class="caps"&gt;LXC&lt;/span&gt; container for efficient resource&amp;nbsp;isolation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="/2026/06/docker-compose-for-beginners/"&gt;Docker Compose for Beginners&lt;/a&gt;&lt;/strong&gt; — Master the Compose fundamentals if you are new to&amp;nbsp;Docker.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Guides"/><category term="vaultwarden"/><category term="bitwarden"/><category term="password-manager"/><category term="docker"/><category term="docker-compose"/><category term="homelab"/><category term="self-hosted"/><category term="security"/><category term="nginx-proxy-manager"/><category term="traefik"/><category term="caddy"/><category term="cloudflare-tunnel"/><category term="backup"/><category term="fail2ban"/><category term="raspberry-pi"/><category term="proxmox"/><category term="lxc"/><category term="encryption"/><category term="2fa"/><category term="totp"/><category term="passkeys"/><category term="webauthn"/><category term="fido2"/><category term="sso"/><category term="authelia"/></entry><entry><title>Docker Compose vs. K3S for Homelab: Which Orchestration Level Do You Actually Need in 2026?</title><link href="https://steadypub.com/2026/06/docker-compose-vs-k3s-2026/" rel="alternate"/><published>2026-06-10T00:00:00+07:00</published><updated>2026-06-10T00:00:00+07:00</updated><author><name>WordForge Team</name></author><id>tag:steadypub.com,2026-06-10:/2026/06/docker-compose-vs-k3s-2026/</id><summary type="html">&lt;p&gt;Building a homelab in 2026 means choosing the right orchestration layer early. Here&amp;#8217;s the practical comparison between Docker Compose and &lt;span class="caps"&gt;K3S&lt;/span&gt; — with real deployment examples, a decision framework, and honest maintenance cost&amp;nbsp;analysis.&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Docker Compose vs. &lt;span class="caps"&gt;K3S&lt;/span&gt; for Homelab: Which Orchestration Level Do You Actually Need in&amp;nbsp;2026?&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~11 minutes | &lt;strong&gt;Audience:&lt;/strong&gt; Intermediate homelab users managing 3–20+ services who feel they&amp;#8217;re outgrowing basic&amp;nbsp;Docker&lt;/p&gt;
&lt;p&gt;The homelab ecosystem has evolved dramatically. In 2026, the question is no longer &amp;#8220;should I run self-hosted services&amp;#8221; — it&amp;#8217;s &amp;#8220;how do I manage them without losing my mind?&amp;#8221; As your library of services grows from a few containers on a Raspberry Pi to a full rack of infrastructure, you inevitably face the orchestration divide: the battle-tested simplicity of &lt;span class="sp-brand docker"&gt;Docker Compose&lt;/span&gt; versus the sophisticated scalability of &lt;span class="sp-brand kubernetes"&gt;&lt;span class="caps"&gt;K3S&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;This isn&amp;#8217;t a theoretical debate. The orchestration layer you choose today determines how much time you spend maintaining your homelab versus actually using it. Let&amp;#8217;s break this down with real deployment examples, not marketing bullet&amp;nbsp;points.&lt;/p&gt;
&lt;h2&gt;1. The Evolution of Homelab Orchestration — and Why It Matters&amp;nbsp;Now&lt;/h2&gt;
&lt;p&gt;In the early days of a homelab journey, almost everyone starts with raw &lt;span class="sp-brand docker"&gt;Docker&lt;/span&gt; commands. You pull an image, map a port, and you&amp;#8217;re off. But as your services multiply, you begin to experience &amp;#8220;container fatigue.&amp;#8221; You have dozens of&amp;nbsp;individual &lt;code&gt;docker run&lt;/code&gt; commands scattered across text files, configuration drift is common, and updating an entire suite of applications feels like a part-time&amp;nbsp;job.&lt;/p&gt;
&lt;p&gt;This is the precise moment when orchestrators become tempting. You are no longer just running services; you are building an &lt;em&gt;environment&lt;/em&gt;. The question is: do you need the simple, declarative orchestration of &lt;span class="sp-brand docker"&gt;Docker Compose&lt;/span&gt;, or is your infrastructure ready for the clustered, self-healing power of &lt;span class="sp-brand kubernetes"&gt;&lt;span class="caps"&gt;K3S&lt;/span&gt;&lt;/span&gt;?&lt;/p&gt;
&lt;p&gt;Most homelabbers reach this crossroads somewhere between 10 and 30 services. If you&amp;#8217;ve already set up a &lt;a href="/nginx-proxy-manager-docker-compose/"&gt;reverse proxy with Nginx Proxy Manager&lt;/a&gt; and have a handful of services behind it, you&amp;#8217;re exactly at this inflection&amp;nbsp;point.&lt;/p&gt;
&lt;h2&gt;2. The Case for Docker Compose: Simple, Proven, and&amp;nbsp;Battle-Tested&lt;/h2&gt;
&lt;p&gt;For the vast majority of self-hosters, &lt;span class="sp-brand docker"&gt;Docker Compose&lt;/span&gt; is the sweet spot. It was purpose-built to define and run multi-container applications, and it excels at exactly&amp;nbsp;that.&lt;/p&gt;
&lt;h3&gt;What Docker Compose Gets&amp;nbsp;Right&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Dead-simple syntax.&lt;/strong&gt;&amp;nbsp;A &lt;code&gt;docker-compose.yml&lt;/code&gt; file is human-readable and takes minutes to learn. Here&amp;#8217;s a real-world example — a typical homelab stack with &lt;span class="sp-brand portainer"&gt;Portainer&lt;/span&gt; for management and &lt;span class="sp-brand pihole"&gt;Pi-hole&lt;/span&gt; for &lt;span class="caps"&gt;DNS&lt;/span&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;
&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;portainer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;portainer/portainer-ce:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;portainer&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/var/run/docker.sock:/var/run/docker.sock&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./portainer-data:/data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;9443:9443&amp;quot;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;pihole&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pihole/pihole:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pihole&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;TZ&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Asia/Jakarta&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;WEBPASSWORD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${PIHOLE_PASSWORD}&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./pihole/etc-pihole:/etc/pihole&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./pihole/etc-dnsmasq.d:/etc/dnsmasq.d&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;53:53/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;53:53/udp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8080:80/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;cap_add&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;NET_ADMIN&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;One command&amp;nbsp;— &lt;code&gt;docker compose up -d&lt;/code&gt; — brings the entire stack online. No cluster setup, no control plane, no certificates to manage. It just&amp;nbsp;works.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Near-zero overhead.&lt;/strong&gt; &lt;span class="sp-brand docker"&gt;Docker&lt;/span&gt; is a lean engine. It doesn&amp;#8217;t require a master node, an etcd database, or complex networking overlays. On a &lt;a href="/proxmox-beginner-guide/"&gt;Proxmox beginner setup&lt;/a&gt;, you can run Docker Compose on an &lt;span class="caps"&gt;LXC&lt;/span&gt; container with 2 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; and still have room for 10+ lightweight&amp;nbsp;services.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Infrastructure-as-code, practically.&lt;/strong&gt; Store&amp;nbsp;your &lt;code&gt;docker-compose.yml&lt;/code&gt; files in a &lt;a href="/self-hosted-services-list/"&gt;self-hosted Git forge&lt;/a&gt; and you&amp;#8217;ve got version-controlled infrastructure without touching &lt;span class="caps"&gt;YAML&lt;/span&gt; indentation hell. For most home labs, this is the sweet spot between&amp;nbsp;manual &lt;code&gt;docker run&lt;/code&gt; and full-blown&amp;nbsp;GitOps.&lt;/p&gt;
&lt;h3&gt;When Docker Compose Hits Its&amp;nbsp;Limits&lt;/h3&gt;
&lt;p&gt;Docker Compose shines on a single host, but it wasn&amp;#8217;t designed for:
- &lt;strong&gt;Multi-node deployments.&lt;/strong&gt; Spreading services across 3 physical servers requires manual port mapping, shared storage, and a lot of hope.
- &lt;strong&gt;Self-healing.&lt;/strong&gt; If a container crashes, Compose restarts it. If a &lt;em&gt;server&lt;/em&gt; crashes, you&amp;#8217;re waking up at 3 &lt;span class="caps"&gt;AM&lt;/span&gt;.
- &lt;strong&gt;Rolling updates with zero downtime.&lt;/strong&gt; Compose can restart containers, but it can&amp;#8217;t drain traffic&amp;nbsp;first.&lt;/p&gt;
&lt;p&gt;For most homelabbers with 1–3 nodes, these limitations are academic. But if you&amp;#8217;ve already got a &lt;a href="/prometheus-monitoring-homelab/"&gt;monitoring stack with Prometheus&lt;/a&gt; tracking uptime across multiple machines, you&amp;#8217;re edging into &lt;span class="caps"&gt;K3S&lt;/span&gt;&amp;nbsp;territory.&lt;/p&gt;
&lt;h3&gt;Stick with Docker Compose&amp;nbsp;If&amp;#8230;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;You have 1–3 physical&amp;nbsp;servers.&lt;/li&gt;
&lt;li&gt;Your primary goal is &lt;em&gt;using&lt;/em&gt; your services, not managing&amp;nbsp;infrastructure.&lt;/li&gt;
&lt;li&gt;You prefer the &amp;#8220;set it and forget it&amp;#8221; approach to&amp;nbsp;maintenance.&lt;/li&gt;
&lt;li&gt;You&amp;#8217;re comfortable with &lt;a href="/portainer-docker-management/"&gt;Portainer for visual management&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;3. The Leap to &lt;span class="caps"&gt;K3S&lt;/span&gt;: Lightweight Kubernetes for the&amp;nbsp;Homelab&lt;/h2&gt;
&lt;p&gt;When your homelab grows to include multiple physical nodes, high-availability requirements, or a genuine need to learn industry-standard orchestration, &lt;span class="sp-brand kubernetes"&gt;&lt;span class="caps"&gt;K3S&lt;/span&gt;&lt;/span&gt; enters the&amp;nbsp;discussion.&lt;/p&gt;
&lt;h3&gt;What Exactly Is &lt;span class="caps"&gt;K3S&lt;/span&gt;?&lt;/h3&gt;
&lt;p&gt;&lt;span class="sp-brand kubernetes"&gt;&lt;span class="caps"&gt;K3S&lt;/span&gt;&lt;/span&gt; is a &lt;span class="caps"&gt;CNCF&lt;/span&gt;-certified &lt;span class="sp-brand kubernetes"&gt;Kubernetes&lt;/span&gt; distribution built by Rancher Labs (now &lt;span class="caps"&gt;SUSE&lt;/span&gt;). It&amp;#8217;s packaged as a single binary under 100 &lt;span class="caps"&gt;MB&lt;/span&gt;, strips out legacy cloud-provider plugins, and replaces etcd with an embedded SQLite database — all optimizations that make it runnable on hardware that would choke on a full &lt;span class="sp-brand kubernetes"&gt;Kubernetes&lt;/span&gt;&amp;nbsp;install.&lt;/p&gt;
&lt;p&gt;Installation on a master node is almost comically&amp;nbsp;simple:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-sfL&lt;span class="w"&gt; &lt;/span&gt;https://get.k3s.io&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sh&lt;span class="w"&gt; &lt;/span&gt;-
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That&amp;#8217;s it. Your control plane is running. Joining a worker node takes one&amp;nbsp;command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-sfL&lt;span class="w"&gt; &lt;/span&gt;https://get.k3s.io&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;K3S_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://&amp;lt;master-ip&amp;gt;:6443&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;K3S_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;node-token&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;sh&lt;span class="w"&gt; &lt;/span&gt;-
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;What &lt;span class="caps"&gt;K3S&lt;/span&gt; Unlocks That Compose&amp;nbsp;Cannot&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Declarative desired state.&lt;/strong&gt; You define your entire application stack in &lt;span class="caps"&gt;YAML&lt;/span&gt; manifests, and &lt;span class="sp-brand kubernetes"&gt;&lt;span class="caps"&gt;K3S&lt;/span&gt;&lt;/span&gt; continuously reconciles reality against that definition. If a pod dies, it&amp;#8217;s recreated. If a node goes offline, workloads reschedule. Here&amp;#8217;s that same Pi-hole stack, expressed as a Kubernetes&amp;nbsp;Deployment:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;apps/v1&lt;/span&gt;
&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Deployment&lt;/span&gt;
&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pihole&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;networking&lt;/span&gt;
&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;replicas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;matchLabels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pihole&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pihole&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pihole&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pihole/pihole:latest&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TZ&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Asia/Jakarta&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;containerPort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;53&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TCP&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;containerPort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;53&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;UDP&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;containerPort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;80&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;volumeMounts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;etc-pihole&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;mountPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/etc/pihole&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;etc-pihole&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;persistentVolumeClaim&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;claimName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pihole-config-pvc&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;v1&lt;/span&gt;
&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Service&lt;/span&gt;
&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pihole-dns&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;networking&lt;/span&gt;
&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;LoadBalancer&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;53&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;targetPort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;53&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;UDP&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pihole&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Yes, it&amp;#8217;s more &lt;span class="caps"&gt;YAML&lt;/span&gt;. But you&amp;#8217;re buying: automatic rescheduling on node failure, rolling updates&amp;nbsp;with &lt;code&gt;kubectl rollout&lt;/code&gt;, and the ability&amp;nbsp;to &lt;code&gt;kubectl apply -f&lt;/code&gt; the same manifest to any&amp;nbsp;cluster.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Native high availability.&lt;/strong&gt; With three &lt;span class="caps"&gt;K3S&lt;/span&gt; master nodes (or two masters + an external database), your control plane survives node failures. Services&amp;nbsp;with &lt;code&gt;replicas: 2&lt;/code&gt; or more stay available even if a worker node goes down. For critical services like &lt;a href="/self-hosted-password-manager-comparison/"&gt;Vaultwarden for password management&lt;/a&gt; or &lt;a href="/home-assistant-docker-compose-homelab/"&gt;Home Assistant&lt;/a&gt;, this isn&amp;#8217;t a luxury — it&amp;#8217;s peace of&amp;nbsp;mind.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Industry-standard skills.&lt;/strong&gt; Every hour you spend learning &lt;span class="sp-brand kubernetes"&gt;&lt;span class="caps"&gt;K3S&lt;/span&gt;&lt;/span&gt; is an hour invested in the technology that runs most of the&amp;nbsp;internet. &lt;code&gt;kubectl&lt;/code&gt;, Helm charts, and Ingress controllers aren&amp;#8217;t just homelab toys — they&amp;#8217;re resume line&amp;nbsp;items.&lt;/p&gt;
&lt;h3&gt;Upgrade to &lt;span class="caps"&gt;K3S&lt;/span&gt;&amp;nbsp;If&amp;#8230;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;You&amp;#8217;re managing 4+ physical nodes and want a unified cluster&amp;nbsp;view.&lt;/li&gt;
&lt;li&gt;You run services that &lt;em&gt;require&lt;/em&gt; uptime — family photo storage, home automation, your partner&amp;#8217;s Plex&amp;nbsp;server.&lt;/li&gt;
&lt;li&gt;You&amp;#8217;re actively building DevOps skills for your&amp;nbsp;career.&lt;/li&gt;
&lt;li&gt;You&amp;#8217;ve already automated your Compose deployments and want the next&amp;nbsp;challenge.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;4. Comparison Matrix: Docker Compose vs. &lt;span class="caps"&gt;K3S&lt;/span&gt; — All the Factors That&amp;nbsp;Matter&lt;/h2&gt;
&lt;p&gt;Talking about orchestration without a comparison table is like describing a server rack without listing specs. Here&amp;#8217;s the honest&amp;nbsp;breakdown:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: left;"&gt;Factor&lt;/th&gt;
&lt;th style="text-align: left;"&gt;Docker Compose&lt;/th&gt;
&lt;th style="text-align: left;"&gt;&lt;span class="caps"&gt;K3S&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;&lt;strong&gt;Learning Curve&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Hours&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Weeks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;&lt;strong&gt;Setup Time (first deploy)&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;5 minutes&lt;/td&gt;
&lt;td style="text-align: left;"&gt;30–60 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;&lt;strong&gt;Single-Node Simplicity&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Excellent&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Overkill&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;&lt;strong&gt;Multi-Node Clustering&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Manual / &lt;span class="caps"&gt;DIY&lt;/span&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Native, automatic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;&lt;strong&gt;High Availability&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Manual (keepalived, shared storage)&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Built-in (pod rescheduling)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;&lt;strong&gt;Rolling Updates&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;code&gt;docker compose up -d&lt;/code&gt; (brief downtime)&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;code&gt;kubectl rollout&lt;/code&gt; (zero-downtime)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;&lt;strong&gt;Secrets Management&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;code&gt;.env&lt;/code&gt; files (manual)&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Kubernetes Secrets (built-in)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;&lt;strong&gt;Ingress / Reverse Proxy&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Separate (&lt;span class="sp-brand nginx"&gt;Nginx&lt;/span&gt;, &lt;span class="sp-brand traefik"&gt;Traefik&lt;/span&gt;)&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Built-in Ingress controllers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;&lt;strong&gt;Monitoring Integration&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Docker stats + external tools&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Native metrics &lt;span class="caps"&gt;API&lt;/span&gt;, &lt;span class="sp-brand grafana"&gt;Grafana&lt;/span&gt;-ready&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Bind mounts (simple, fragile)&lt;/td&gt;
&lt;td style="text-align: left;"&gt;PersistentVolumeClaims (abstraction layer)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;&lt;strong&gt;Resource Overhead (per node)&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;~200 &lt;span class="caps"&gt;MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; overhead&lt;/td&gt;
&lt;td style="text-align: left;"&gt;~500 &lt;span class="caps"&gt;MB&lt;/span&gt;–1 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; overhead&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;&lt;strong&gt;Backup Strategy&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Rsync volumes + compose files&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Velero, etcd snapshots, or &lt;span class="caps"&gt;PVC&lt;/span&gt; backups&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;&lt;strong&gt;Update Cadence&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;You decide (manual)&lt;/td&gt;
&lt;td style="text-align: left;"&gt;GitOps-friendly (ArgoCD, Flux)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;&lt;strong&gt;Community Size (Homelab)&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Massive&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Growing, smaller pool of guides&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;&lt;strong&gt;&amp;#8220;Spouse Approval Factor&amp;#8221;&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;High (infrequent tinkering)&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Variable (initial setup is real work)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;The Hidden Cost: Maintenance&amp;nbsp;Burden&lt;/h3&gt;
&lt;p&gt;This is where most comparisons miss the point. The real cost of an orchestrator isn&amp;#8217;t the &lt;span class="caps"&gt;RAM&lt;/span&gt; it consumes — it&amp;#8217;s the &lt;em&gt;hours you spend keeping it healthy&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;With &lt;span class="sp-brand docker"&gt;Docker Compose&lt;/span&gt;, maintenance looks&amp;nbsp;like: &lt;code&gt;docker compose pull &amp;amp;&amp;amp; docker compose up -d&lt;/code&gt; once a week. You might need to fix a broken volume mount once every few&amp;nbsp;months.&lt;/p&gt;
&lt;p&gt;With &lt;span class="sp-brand kubernetes"&gt;&lt;span class="caps"&gt;K3S&lt;/span&gt;&lt;/span&gt;, maintenance includes: certificate rotation (automatic but worth monitoring), etcd backups (you &lt;em&gt;are&lt;/em&gt; backing these up, right?), Ingress controller updates, &lt;span class="caps"&gt;CNI&lt;/span&gt; plugin compatibility checks, and the&amp;nbsp;occasional &lt;code&gt;kubectl describe pod&lt;/code&gt; rabbit hole at 11 &lt;span class="caps"&gt;PM&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;One homelabber&amp;#8217;s rule of thumb:&lt;/strong&gt; If you spend more than 2 hours per week on infrastructure maintenance, your orchestrator is too complex for your actual&amp;nbsp;needs.&lt;/p&gt;
&lt;h2&gt;5. The 2026 Decision Framework: What Should You Actually&amp;nbsp;Run?&lt;/h2&gt;
&lt;p&gt;Forget the hype. Here&amp;#8217;s a practical decision tree based on what homelabbers are actually running in&amp;nbsp;2026:&lt;/p&gt;
&lt;h3&gt;Path A: Start with Docker Compose (Recommended for ~85% of&amp;nbsp;homelabbers)&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Your setup:&lt;/strong&gt; 1–3 nodes (mix of &lt;a href="/mini-pc-home-server-2025/"&gt;mini PCs&lt;/a&gt; or &lt;a href="/used-server-hardware-for-homelab/"&gt;used enterprise gear&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Your goal:&lt;/strong&gt; Running services, not managing&amp;nbsp;infrastructure.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Your stack:&lt;/strong&gt; &lt;span class="sp-brand portainer"&gt;Portainer&lt;/span&gt; or Dockge for visual management, &lt;span class="sp-brand nginx"&gt;Nginx Proxy Manager&lt;/span&gt; for reverse proxy, and a Git repo for compose file backup. See this pattern in action with our &lt;a href="/uptime-kuma-docker-compose-homelab-2026/"&gt;Uptime Kuma monitoring guide&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;When to reconsider:&lt;/strong&gt; If you hit 3+ nodes and your compose files are scattered across machines, or if you&amp;#8217;re manually &lt;span class="caps"&gt;SSH&lt;/span&gt;-ing to restart services more than once a&amp;nbsp;week.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Path B: Go &lt;span class="caps"&gt;K3S&lt;/span&gt; (For the ~15% who&amp;#8217;ve outgrown&amp;nbsp;Compose)&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Your setup:&lt;/strong&gt; 4+ nodes, at least one with 8+ &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; for the control&amp;nbsp;plane.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Your goal:&lt;/strong&gt; Learn production-grade orchestration or run services that genuinely need &lt;span class="caps"&gt;HA&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Your stack:&lt;/strong&gt; &lt;span class="sp-brand kubernetes"&gt;&lt;span class="caps"&gt;K3S&lt;/span&gt;&lt;/span&gt; + MetalLB for load balancing + &lt;span class="sp-brand traefik"&gt;Traefik&lt;/span&gt; Ingress + Longhorn for storage. Expect to invest 10–20 hours&amp;nbsp;upfront.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The hybrid approach:&lt;/strong&gt; Some homelabbers run &lt;span class="sp-brand docker"&gt;Docker Compose&lt;/span&gt; on their &amp;#8220;production&amp;#8221; node (services the family uses) while maintaining a separate &lt;span class="sp-brand kubernetes"&gt;&lt;span class="caps"&gt;K3S&lt;/span&gt;&lt;/span&gt; cluster for learning and experimentation. This is a valid middle ground that avoids the &amp;#8220;my spouse can&amp;#8217;t reach &lt;span class="sp-brand jellyfin"&gt;Jellyfin&lt;/span&gt; because I broke the &lt;span class="caps"&gt;CNI&lt;/span&gt; plugin&amp;#8221;&amp;nbsp;scenario.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;The &amp;#8220;Gateway Drug&amp;#8221;&amp;nbsp;Pattern&lt;/h3&gt;
&lt;p&gt;Many successful homelabbers follow this&amp;nbsp;progression:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Phase 1:&lt;/strong&gt;&amp;nbsp;Raw &lt;code&gt;docker run&lt;/code&gt; commands → realize this doesn&amp;#8217;t&amp;nbsp;scale&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Phase 2:&lt;/strong&gt; &lt;span class="sp-brand docker"&gt;Docker Compose&lt;/span&gt; + &lt;span class="sp-brand portainer"&gt;Portainer&lt;/span&gt; → smooth sailing for 1–2&amp;nbsp;years&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Phase 3:&lt;/strong&gt; Curiosity piqued → spin up a &lt;span class="sp-brand kubernetes"&gt;&lt;span class="caps"&gt;K3S&lt;/span&gt;&lt;/span&gt; cluster on spare&amp;nbsp;hardware&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Phase 4:&lt;/strong&gt; Migrate non-critical services to &lt;span class="sp-brand kubernetes"&gt;&lt;span class="caps"&gt;K3S&lt;/span&gt;&lt;/span&gt; for&amp;nbsp;learning&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Phase 5:&lt;/strong&gt; Either go all-in on &lt;span class="sp-brand kubernetes"&gt;&lt;span class="caps"&gt;K3S&lt;/span&gt;&lt;/span&gt; or settle into a hybrid&amp;nbsp;setup&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The key insight: &lt;strong&gt;you don&amp;#8217;t have to jump from Phase 2 to Phase 5 in one weekend.&lt;/strong&gt; The hybrid approach — running both simultaneously on separate hardware — is the most common (and least stressful) pattern in&amp;nbsp;2026.&lt;/p&gt;
&lt;h2&gt;6. The Hybrid Reality: Running Both in&amp;nbsp;2026&lt;/h2&gt;
&lt;p&gt;Here&amp;#8217;s a real scenario from the WordForge homelab: we run &lt;span class="sp-brand docker"&gt;Docker Compose&lt;/span&gt; on our primary &lt;span class="sp-brand proxmox"&gt;Proxmox&lt;/span&gt; node (where family-critical services like &lt;span class="sp-brand pihole"&gt;Pi-hole&lt;/span&gt; &lt;span class="caps"&gt;DNS&lt;/span&gt; and the reverse proxy live) while maintaining a separate 3-node &lt;span class="sp-brand kubernetes"&gt;&lt;span class="caps"&gt;K3S&lt;/span&gt;&lt;/span&gt; cluster on repurposed hardware for&amp;nbsp;experimentation. &lt;/p&gt;
&lt;p&gt;The Compose node runs 15+ services with near-zero weekly maintenance. The &lt;span class="sp-brand kubernetes"&gt;&lt;span class="caps"&gt;K3S&lt;/span&gt;&lt;/span&gt; cluster runs test deployments, &lt;span class="caps"&gt;CI&lt;/span&gt;/&lt;span class="caps"&gt;CD&lt;/span&gt; pipelines, and services we&amp;#8217;re evaluating before promoting to the &amp;#8220;production&amp;#8221; Compose node. When the &lt;span class="sp-brand kubernetes"&gt;&lt;span class="caps"&gt;K3S&lt;/span&gt;&lt;/span&gt; cluster breaks (and it will — that&amp;#8217;s the point of a learning environment), nobody notices except&amp;nbsp;you.&lt;/p&gt;
&lt;p&gt;This pattern turns the &amp;#8220;Compose vs. &lt;span class="caps"&gt;K3S&lt;/span&gt;&amp;#8221; debate from a binary choice into a spectrum. You&amp;#8217;re not choosing one forever — you&amp;#8217;re choosing what&amp;#8217;s right for &lt;em&gt;this phase&lt;/em&gt; of your&amp;nbsp;homelab.&lt;/p&gt;
&lt;h3&gt;When the Hybrid Pattern Makes&amp;nbsp;Sense&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;You want to learn &lt;span class="sp-brand kubernetes"&gt;Kubernetes&lt;/span&gt; without risking family-critical&amp;nbsp;services.&lt;/li&gt;
&lt;li&gt;You have spare hardware (old mini PCs, retired laptops) that can run &lt;span class="sp-brand kubernetes"&gt;&lt;span class="caps"&gt;K3S&lt;/span&gt;&lt;/span&gt;&amp;nbsp;agents.&lt;/li&gt;
&lt;li&gt;You want to test infrastructure changes in &lt;span class="sp-brand kubernetes"&gt;&lt;span class="caps"&gt;K3S&lt;/span&gt;&lt;/span&gt; before applying equivalent changes to your Compose&amp;nbsp;setup.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;7. Conclusion: Orchestration Is a Spectrum, Not a Binary&amp;nbsp;Choice&lt;/h2&gt;
&lt;p&gt;There is no universally &amp;#8220;better&amp;#8221; orchestrator — only the one that matches your current infrastructure, time budget, and tolerance for complexity. &lt;span class="sp-brand docker"&gt;Docker Compose&lt;/span&gt; remains the undisputed champion for single-node and small multi-node homelabs in 2026. &lt;span class="sp-brand kubernetes"&gt;&lt;span class="caps"&gt;K3S&lt;/span&gt;&lt;/span&gt; is the logical next step when you&amp;#8217;ve genuinely outgrown Compose&amp;#8217;s single-host model and are ready to invest real time in platform&amp;nbsp;management.&lt;/p&gt;
&lt;p&gt;The most common mistake? Jumping to &lt;span class="sp-brand kubernetes"&gt;&lt;span class="caps"&gt;K3S&lt;/span&gt;&lt;/span&gt; too early. If you&amp;#8217;re still learning how reverse proxies work or troubleshooting volume permissions, &lt;span class="sp-brand kubernetes"&gt;Kubernetes&lt;/span&gt; will multiply your problems, not solve them. Master &lt;span class="sp-brand docker"&gt;Docker Compose&lt;/span&gt; first — &lt;a href="/portainer-setup-guide/"&gt;our Portainer guide&lt;/a&gt; is a good place to start if you want visual container management — and only graduate to &lt;span class="sp-brand kubernetes"&gt;&lt;span class="caps"&gt;K3S&lt;/span&gt;&lt;/span&gt; when the limitations of single-host orchestration are &lt;em&gt;actually blocking you&lt;/em&gt;, not because a Reddit thread made you feel like you&amp;#8217;re missing&amp;nbsp;out.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Want more homelab architecture guidance?&lt;/strong&gt; Check out our &lt;a href="/proxmox-beginner-guide/"&gt;Proxmox Beginner Guide 2026&lt;/a&gt; for the foundation layer, our &lt;a href="/self-hosted-services-list/"&gt;self-hosted services roundup&lt;/a&gt; for what to actually run, and our &lt;a href="/ollama-proxmox-homelab/"&gt;&lt;span class="caps"&gt;AI&lt;/span&gt; on Proxmox guide&lt;/a&gt; if you&amp;#8217;re adding &lt;span class="sp-brand ollama"&gt;Ollama&lt;/span&gt; to the&amp;nbsp;stack.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Frequently Asked&amp;nbsp;Questions&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Q: Can I run Docker Compose and &lt;span class="caps"&gt;K3S&lt;/span&gt; side by side on the same node?&lt;/strong&gt;
A: Technically yes, but we strongly advise against it. Both want to manage containers and networking, and conflicts are inevitable. Use separate physical or virtual machines. If you&amp;#8217;re on &lt;span class="sp-brand proxmox"&gt;Proxmox&lt;/span&gt;, dedicate one &lt;span class="caps"&gt;VM&lt;/span&gt; to Compose and a separate set of VMs/LXCs to your &lt;span class="sp-brand kubernetes"&gt;&lt;span class="caps"&gt;K3S&lt;/span&gt;&lt;/span&gt;&amp;nbsp;cluster.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: Is &lt;span class="caps"&gt;K3S&lt;/span&gt; too resource-heavy for a Raspberry Pi cluster?&lt;/strong&gt;
A: Not at all. &lt;span class="sp-brand kubernetes"&gt;&lt;span class="caps"&gt;K3S&lt;/span&gt;&lt;/span&gt; was designed for &lt;span class="caps"&gt;ARM&lt;/span&gt; and edge devices. A Pi 5 with 8 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; can run the control plane, and Pi 4s make fine worker nodes. Just keep your workload pods lightweight — don&amp;#8217;t expect &lt;span class="sp-brand jellyfin"&gt;Jellyfin&lt;/span&gt; with 4K transcoding to run well on a&amp;nbsp;Pi.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: How do I migrate from Docker Compose to &lt;span class="caps"&gt;K3S&lt;/span&gt;?&lt;/strong&gt;
A: There&amp;#8217;s no automated &amp;#8220;lift and shift&amp;#8221; tool. The migration path is: (1) convert&amp;nbsp;your &lt;code&gt;docker-compose.yml&lt;/code&gt; to Kubernetes manifests (Deployments, Services, ConfigMaps), (2) set up persistent storage with PVCs matching your old bind mounts, (3) test the new deployment on &lt;span class="sp-brand kubernetes"&gt;&lt;span class="caps"&gt;K3S&lt;/span&gt;&lt;/span&gt; in parallel, (4) switch &lt;span class="caps"&gt;DNS&lt;/span&gt;/reverse proxy to point to the &lt;span class="sp-brand kubernetes"&gt;&lt;span class="caps"&gt;K3S&lt;/span&gt;&lt;/span&gt; service IPs, (5) decommission the Compose stack. Budget a full weekend for 10–15&amp;nbsp;services.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: What about Podman or Docker Swarm? Aren&amp;#8217;t those options too?&lt;/strong&gt;
A: Podman is an excellent &lt;span class="sp-brand docker"&gt;Docker&lt;/span&gt; alternative with better security defaults (rootless by design), and it has its own Compose-equivalent&amp;nbsp;(&lt;code&gt;podman-compose&lt;/code&gt;). Docker Swarm is still functional but has been in maintenance mode since Mirantis acquired Docker Enterprise. For new deployments in 2026, choose between Compose and &lt;span class="sp-brand kubernetes"&gt;&lt;span class="caps"&gt;K3S&lt;/span&gt;&lt;/span&gt; — Swarm is a dead&amp;nbsp;end.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: Will learning &lt;span class="caps"&gt;K3S&lt;/span&gt; help my career?&lt;/strong&gt;
A: Absolutely. &lt;span class="sp-brand kubernetes"&gt;Kubernetes&lt;/span&gt; skills — even from a homelab &lt;span class="sp-brand kubernetes"&gt;&lt;span class="caps"&gt;K3S&lt;/span&gt;&lt;/span&gt; cluster — transfer directly to &lt;span class="caps"&gt;EKS&lt;/span&gt;, &lt;span class="caps"&gt;GKE&lt;/span&gt;, and &lt;span class="caps"&gt;AKS&lt;/span&gt; in production environments. Being able to say &amp;#8220;I run &lt;span class="sp-brand kubernetes"&gt;Kubernetes&lt;/span&gt; at home&amp;#8221; in an interview is a strong&amp;nbsp;signal.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: Which reverse proxy should I use with &lt;span class="caps"&gt;K3S&lt;/span&gt;?&lt;/strong&gt;
A: &lt;span class="sp-brand traefik"&gt;Traefik&lt;/span&gt; ships as the default Ingress controller in &lt;span class="sp-brand kubernetes"&gt;&lt;span class="caps"&gt;K3S&lt;/span&gt;&lt;/span&gt; and integrates natively with Kubernetes Ingress resources. If you&amp;#8217;re coming from &lt;span class="sp-brand nginx"&gt;Nginx Proxy Manager&lt;/span&gt;, be prepared for a learning curve — &lt;span class="sp-brand traefik"&gt;Traefik&lt;/span&gt; configuration is &lt;span class="caps"&gt;YAML&lt;/span&gt;-based, not &lt;span class="caps"&gt;GUI&lt;/span&gt;-based. Some homelabbers run &lt;span class="sp-brand nginx"&gt;Nginx&lt;/span&gt; Ingress instead for&amp;nbsp;familiarity.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: How do I back up a &lt;span class="caps"&gt;K3S&lt;/span&gt; cluster vs. a Docker Compose setup?&lt;/strong&gt;
A: For&amp;nbsp;Compose: &lt;code&gt;rsync&lt;/code&gt; your volumes and git-push your compose files. Done in 5 minutes. For &lt;span class="sp-brand kubernetes"&gt;&lt;span class="caps"&gt;K3S&lt;/span&gt;&lt;/span&gt;: you need etcd snapshots&amp;nbsp;(&lt;code&gt;k3s etcd-snapshot&lt;/code&gt;), PersistentVolume backups (Velero, Longhorn snapshots, or good old rsync if using hostPath volumes), and your manifest repo. More moving parts, more diligence&amp;nbsp;required.&lt;/p&gt;</content><category term="Guides"/><category term="homelab"/><category term="docker-compose"/><category term="k3s"/><category term="kubernetes"/><category term="orchestration"/><category term="self-hosting"/></entry><entry><title>Mastering Docker Networking: A Battle-Tested Guide for Homelabbers</title><link href="https://steadypub.com/2026/06/docker-networking-best-practices/" rel="alternate"/><published>2026-06-10T00:00:00+07:00</published><updated>2026-06-10T00:00:00+07:00</updated><author><name>WordForge Team</name></author><id>tag:steadypub.com,2026-06-10:/2026/06/docker-networking-best-practices/</id><summary type="html">&lt;p&gt;Stop fighting Docker container communication. Learn battle-tested network architectures for your homelab — user-defined bridges, &lt;span class="caps"&gt;DNS&lt;/span&gt;-based service discovery, Traefik integration, Macvlan for static IPs, and network segmentation by service&amp;nbsp;role.&lt;/p&gt;</summary><content type="html">&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~15 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelabbers running 5+ Docker containers who are tired of port&amp;nbsp;collisions, &lt;code&gt;localhost&lt;/code&gt; confusion, and containers that can&amp;#8217;t talk to each other
&lt;strong&gt;Last tested:&lt;/strong&gt; June 2026 — Docker 27.x, Docker Compose v2, Traefik&amp;nbsp;3.2&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Introduction: The Docker Networking&amp;nbsp;Trap&lt;/h2&gt;
&lt;p&gt;You started with one Docker container — maybe Pi-hole for ad blocking. You&amp;nbsp;ran &lt;code&gt;docker run -p 53:53 pihole/pihole&lt;/code&gt; and it worked. Then you added Home Assistant&amp;nbsp;(&lt;code&gt;-p 8123:8123&lt;/code&gt;), then Jellyfin&amp;nbsp;(&lt;code&gt;-p 8096:8096&lt;/code&gt;), then Portainer&amp;nbsp;(&lt;code&gt;-p 9443:9443&lt;/code&gt;). Every service got a unique port number, and you memorized them like phone extensions at a small&amp;nbsp;office.&lt;/p&gt;
&lt;p&gt;Then the problems started. Your Jellyfin container couldn&amp;#8217;t reach your Sonarr container. Your Home Assistant couldn&amp;#8217;t discover your &lt;span class="caps"&gt;MQTT&lt;/span&gt; broker. You&amp;nbsp;tried &lt;code&gt;localhost:1883&lt;/code&gt; and got connection refused. You tried the container &lt;span class="caps"&gt;IP&lt;/span&gt;&amp;nbsp;(&lt;code&gt;172.17.0.5:1883&lt;/code&gt;), and it worked — until Docker restarted and assigned a new &lt;span class="caps"&gt;IP&lt;/span&gt;. The&amp;nbsp;default &lt;code&gt;bridge&lt;/code&gt; network that makes Docker feel effortless during your&amp;nbsp;first &lt;code&gt;docker run&lt;/code&gt; becomes the single biggest source of frustration the moment you have more than three&amp;nbsp;containers.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;This guide is about one thing: designing Docker networks that don&amp;#8217;t rot.&lt;/strong&gt; You will learn when to&amp;nbsp;use &lt;code&gt;bridge&lt;/code&gt; vs &lt;code&gt;host&lt;/code&gt; vs &lt;code&gt;macvlan&lt;/code&gt;, why user-defined bridges are the backbone of every clean Docker Compose stack, how to integrate Traefik without tangling your network topology, and how to segment containers by service role so a compromised Plex container cannot reach your Vaultwarden&amp;nbsp;database.&lt;/p&gt;
&lt;p&gt;By the end, you will have a repeatable network architecture pattern that works whether you run 5 containers on a Raspberry Pi or 50 on a Proxmox&amp;nbsp;node.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Understanding Docker Network&amp;nbsp;Drivers&lt;/h2&gt;
&lt;p&gt;Docker ships with five network drivers, but only three matter for a homelab. Here is what they do, when to use them, and — critically — when to avoid&amp;nbsp;them.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Driver&lt;/th&gt;
&lt;th&gt;Scope&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;External Access&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;bridge&lt;/strong&gt; (default)&lt;/td&gt;
&lt;td&gt;Container-to-container on same host&lt;/td&gt;
&lt;td&gt;❌ No automatic &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Via port mapping&amp;nbsp;(&lt;code&gt;-p&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Nothing — avoid for multi-container setups&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;bridge&lt;/strong&gt; (user-defined)&lt;/td&gt;
&lt;td&gt;Container-to-container on same host&lt;/td&gt;
&lt;td&gt;✅ Built-in &lt;span class="caps"&gt;DNS&lt;/span&gt; resolution&lt;/td&gt;
&lt;td&gt;Via port mapping&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;The standard&lt;/strong&gt; — every Docker Compose stack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;host&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Shares host network namespace&lt;/td&gt;
&lt;td&gt;N/A (host&amp;#8217;s &lt;span class="caps"&gt;DNS&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;All ports exposed directly&lt;/td&gt;
&lt;td&gt;High-performance apps (Plex transcoding, game servers)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;macvlan&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Container gets its own &lt;span class="caps"&gt;MAC&lt;/span&gt;/&lt;span class="caps"&gt;IP&lt;/span&gt; on &lt;span class="caps"&gt;LAN&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;N/A (&lt;span class="caps"&gt;LAN&lt;/span&gt; &lt;span class="caps"&gt;DHCP&lt;/span&gt;/&lt;span class="caps"&gt;DNS&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;Direct &lt;span class="caps"&gt;LAN&lt;/span&gt; access&lt;/td&gt;
&lt;td&gt;Containers needing static &lt;span class="caps"&gt;LAN&lt;/span&gt; IPs (Pi-hole, Home Assistant discovery)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;overlay&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Multi-host swarm&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Via routing mesh&lt;/td&gt;
&lt;td&gt;Multi-node Docker Swarm (rare in homelabs)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Default Bridge: The Silent&amp;nbsp;Killer&lt;/h3&gt;
&lt;p&gt;When you&amp;nbsp;run &lt;code&gt;docker run&lt;/code&gt; without explicitly specifying a network, every container lands on the&amp;nbsp;default &lt;code&gt;bridge&lt;/code&gt; network. This network has two fatal flaws for any setup with more than three&amp;nbsp;containers:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;No &lt;span class="caps"&gt;DNS&lt;/span&gt; resolution.&lt;/strong&gt; Containers on the default bridge can only reach each other by &lt;span class="caps"&gt;IP&lt;/span&gt; address — and those IPs change every time a container restarts. This is&amp;nbsp;why &lt;code&gt;ping mysql&lt;/code&gt; fails&amp;nbsp;while &lt;code&gt;ping 172.17.0.3&lt;/code&gt; works, until Docker restarts and MySQL moves&amp;nbsp;to &lt;code&gt;172.17.0.6&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;No isolation.&lt;/strong&gt; Every container on the default bridge can talk to every other container. There is no segmentation, no access control, no way to say &amp;#8220;Jellyfin can talk to Sonarr but not to&amp;nbsp;Vaultwarden.&amp;#8221;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Never use the default bridge for anything. Create a user-defined bridge network for every group of related services. We will cover this pattern in detail&amp;nbsp;below.&lt;/p&gt;
&lt;h3&gt;Host Network: Raw Performance, Zero&amp;nbsp;Isolation&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;host&lt;/code&gt; driver removes Docker&amp;#8217;s network namespace entirely. Your container sees the host&amp;#8217;s network interfaces directly — if the host listens&amp;nbsp;on &lt;code&gt;0.0.0.0:32400&lt;/code&gt;, the container binds&amp;nbsp;to &lt;code&gt;0.0.0.0:32400&lt;/code&gt;. No port mapping. No &lt;span class="caps"&gt;NAT&lt;/span&gt; overhead. No Docker network proxy process sitting between your application and the network&amp;nbsp;card.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;When to use host&amp;nbsp;networking:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Plex Media Server&lt;/strong&gt; — transcoding benefits from direct &lt;span class="caps"&gt;NIC&lt;/span&gt; access and avoids the Docker userland proxy&amp;nbsp;bottleneck.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Game servers&lt;/strong&gt; (Minecraft, Valheim) — lower latency, no port mapping to&amp;nbsp;manage.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Network monitoring tools&lt;/strong&gt; (ntopng, Wireshark in a container) — need raw packet&amp;nbsp;access.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pi-hole with &lt;span class="caps"&gt;DHCP&lt;/span&gt;&lt;/strong&gt; — &lt;span class="caps"&gt;DHCP&lt;/span&gt; requires broadcast traffic Docker bridge filters&amp;nbsp;out.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;When to avoid host&amp;nbsp;networking:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Every other service.&lt;/strong&gt; Host networking is the nuclear option. You lose &lt;span class="caps"&gt;DNS&lt;/span&gt;-based service discovery, container isolation, and port conflict detection. Two containers&amp;nbsp;on &lt;code&gt;host&lt;/code&gt; cannot both bind to port&amp;nbsp;80.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Macvlan: When Your Container Needs a &lt;span class="caps"&gt;LAN&lt;/span&gt;&amp;nbsp;Identity&lt;/h3&gt;
&lt;p&gt;Macvlan gives your container a real &lt;span class="caps"&gt;MAC&lt;/span&gt; address and &lt;span class="caps"&gt;IP&lt;/span&gt; on your physical &lt;span class="caps"&gt;LAN&lt;/span&gt;, indistinguishable from a physical machine. Your router sees it. Your other devices see it. mDNS and broadcast protocols work&amp;nbsp;natively.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Legitimate macvlan use&amp;nbsp;cases:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Home Assistant&lt;/strong&gt; — needs mDNS and &lt;span class="caps"&gt;DHCP&lt;/span&gt; discovery for ESPHome, Apple HomeKit, and&amp;nbsp;Chromecast.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pi-hole as primary &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/strong&gt; — your router expects a static &lt;span class="caps"&gt;LAN&lt;/span&gt; &lt;span class="caps"&gt;IP&lt;/span&gt; for &lt;span class="caps"&gt;DNS&lt;/span&gt;; macvlan gives Pi-hole its&amp;nbsp;own &lt;code&gt;192.168.1.53&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Legacy apps that hardcode &lt;span class="caps"&gt;IP&lt;/span&gt; addresses&lt;/strong&gt; — if some crusty service only connects&amp;nbsp;to &lt;code&gt;192.168.1.100&lt;/code&gt;, macvlan lets you give a container that exact &lt;span class="caps"&gt;IP&lt;/span&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;The macvlan caveat:&lt;/strong&gt; A macvlan container cannot communicate with its Docker host. This is by design — macvlan isolates the container at Layer 2. If you need host-to-container communication over macvlan, you must create a sub-interface or a second macvlan on the host. For most homelabbers, the solution is simpler: only use macvlan for the one or two containers that genuinely require it, and put everything else on user-defined&amp;nbsp;bridges.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The Power of User-Defined Bridge&amp;nbsp;Networks&lt;/h2&gt;
&lt;p&gt;A user-defined bridge is the backbone of every well-architected Docker Compose stack. When you create a new bridge network&amp;nbsp;with &lt;code&gt;docker network create my-net&lt;/code&gt; or define&amp;nbsp;a &lt;code&gt;networks:&lt;/code&gt; block in Compose, you unlock three capabilities the default bridge cannot&amp;nbsp;provide.&lt;/p&gt;
&lt;h3&gt;Automatic &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;Resolution&lt;/h3&gt;
&lt;p&gt;Containers on the same user-defined bridge can reach each other by &lt;strong&gt;service name&lt;/strong&gt; or &lt;strong&gt;container name&lt;/strong&gt;. This is the single feature that makes multi-container Docker&amp;nbsp;viable.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# docker-compose.yml&lt;/span&gt;
&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;my-app&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;backend&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;DATABASE_URL=postgres://db:5432/mydb&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# ← service name, not IP&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;postgres:16&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;backend&lt;/span&gt;

&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;backend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;bridge&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;app&lt;/code&gt; container connects&amp;nbsp;to &lt;code&gt;db:5432&lt;/code&gt;. Docker&amp;#8217;s embedded &lt;span class="caps"&gt;DNS&lt;/span&gt; server&amp;nbsp;resolves &lt;code&gt;db&lt;/code&gt; to the container&amp;#8217;s &lt;span class="caps"&gt;IP&lt;/span&gt;. No hardcoded IPs. No environment variables full&amp;nbsp;of &lt;code&gt;172.x.x.x&lt;/code&gt;. If&amp;nbsp;the &lt;code&gt;db&lt;/code&gt; container restarts and gets a new &lt;span class="caps"&gt;IP&lt;/span&gt;, the &lt;span class="caps"&gt;DNS&lt;/span&gt; entry updates automatically. This is how every professional Docker deployment&amp;nbsp;works.&lt;/p&gt;
&lt;h3&gt;Network-Level&amp;nbsp;Isolation&lt;/h3&gt;
&lt;p&gt;User-defined bridges give you network segmentation at zero cost. Create one bridge per service group, and containers on different bridges cannot reach each other unless you explicitly connect them to multiple&amp;nbsp;networks.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;media&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="c1"&gt;# Jellyfin, Sonarr, Radarr, Prowlarr, qBittorrent&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;bridge&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="c1"&gt;# Traefik, Authelia, CrowdSec&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;bridge&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;# Nextcloud, MariaDB, Redis&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;bridge&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;monitoring&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Grafana, Prometheus, Uptime Kuma&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;bridge&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;dns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="c1"&gt;# Pi-hole, Unbound&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;bridge&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Why segment by service role?&lt;/strong&gt; If a vulnerability in Jellyfin allows remote code execution, the attacker lands on&amp;nbsp;the &lt;code&gt;media&lt;/code&gt; network. From there, they can reach Sonarr and qBittorrent — annoying but not catastrophic. They cannot reach your Vaultwarden database on&amp;nbsp;the &lt;code&gt;storage&lt;/code&gt; network or your Traefik dashboard&amp;nbsp;on &lt;code&gt;proxy&lt;/code&gt;. Network segmentation turns a full-compromise scenario into a contained&amp;nbsp;incident.&lt;/p&gt;
&lt;p&gt;The trade-off: if a container genuinely needs cross-segment access (e.g., Traefik must reach every service it proxies), you attach it to multiple&amp;nbsp;networks:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;traefik&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;proxy&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;media&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;storage&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;monitoring&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;dns&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Traefik is the exception, not the rule. Every other container should live on exactly one&amp;nbsp;network.&lt;/p&gt;
&lt;h3&gt;The Docker Compose Default&amp;nbsp;Network&lt;/h3&gt;
&lt;p&gt;When you&amp;nbsp;run &lt;code&gt;docker compose up&lt;/code&gt;, Compose automatically creates a user-defined bridge&amp;nbsp;named &lt;code&gt;&amp;lt;project&amp;gt;_default&lt;/code&gt;. Every service without an&amp;nbsp;explicit &lt;code&gt;networks:&lt;/code&gt; entry joins this network and gets &lt;span class="caps"&gt;DNS&lt;/span&gt; resolution. This is fine for a single-stack homelab with 5-8 containers. The moment you have multiple Compose files or 10+ containers, switch to explicit named&amp;nbsp;networks.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Related:&lt;/strong&gt; If you are still running containers with&amp;nbsp;raw &lt;code&gt;docker run&lt;/code&gt; commands, read our &lt;a href="/2026/06/docker-compose-for-beginners/"&gt;Docker Compose for Beginners&lt;/a&gt; guide and migrate to Compose today. You are fighting with one hand tied behind your&amp;nbsp;back.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;Integrating Traefik as the Network&amp;nbsp;Gatekeeper&lt;/h2&gt;
&lt;p&gt;In 2026, &lt;span class="sp-brand traefik"&gt;Traefik&lt;/span&gt; is the standard reverse proxy for homelab Docker environments. It discovers containers via Docker socket labels, routes &lt;span class="caps"&gt;HTTP&lt;/span&gt;/&lt;span class="caps"&gt;HTTPS&lt;/span&gt; traffic, and auto-provisions Let&amp;#8217;s Encrypt certificates — all without touching a reverse proxy &lt;span class="caps"&gt;GUI&lt;/span&gt;. But Traefik&amp;#8217;s network architecture has specific requirements that trip up&amp;nbsp;newcomers.&lt;/p&gt;
&lt;h3&gt;The Traefik Network&amp;nbsp;Model&lt;/h3&gt;
&lt;p&gt;Traefik needs to be on the same Docker network as every container it proxies. This is non-negotiable: Traefik routes requests by connecting to the backend container&amp;#8217;s internal &lt;span class="caps"&gt;IP&lt;/span&gt; via the shared Docker bridge. If Traefik is&amp;nbsp;on &lt;code&gt;network-A&lt;/code&gt; and your app is&amp;nbsp;on &lt;code&gt;network-B&lt;/code&gt; with no overlap, Traefik&amp;nbsp;returns &lt;code&gt;502 Bad Gateway&lt;/code&gt; and nothing in the logs tells you&amp;nbsp;why.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The correct&amp;nbsp;pattern:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# traefik/docker-compose.yml&lt;/span&gt;
&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;traefik&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;traefik:v3.2&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;proxy&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# Traefik&amp;#39;s own management network&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;media&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# Connects to Jellyfin/Sonarr&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;storage&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Connects to Nextcloud&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;monitoring&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;# Connects to Grafana/Uptime Kuma&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;80:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;443:443&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/var/run/docker.sock:/var/run/docker.sock:ro&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# ... rest of Traefik config&lt;/span&gt;

&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;external&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Created separately: docker network create proxy&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;media&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;external&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;external&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;monitoring&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;external&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And on the application side, each service joins its functional network plus, optionally,&amp;nbsp;the &lt;code&gt;proxy&lt;/code&gt; network if you want Traefik to route to&amp;nbsp;it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# jellyfin/docker-compose.yml&lt;/span&gt;
&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;jellyfin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;jellyfin/jellyfin:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;media&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;proxy&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="c1"&gt;# Traefik needs this to route traffic&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.enable=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.jellyfin.rule=Host(`media.${DOMAIN}`)&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.services.jellyfin.loadbalancer.server.port=8096&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;media&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;external&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;external&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The golden rule:&lt;/strong&gt; Every service Traefik proxies must either share a network with Traefik, or Traefik must be explicitly attached to that service&amp;#8217;s network. Pick one pattern and stick with it. Most homelabbers prefer attaching Traefik to every network (the &amp;#8220;hub&amp;#8221; model) because it keeps application Compose files&amp;nbsp;simple.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Choosing a reverse proxy?&lt;/strong&gt; Our &lt;a href="/2026/06/traefik-vs-nginx-proxy-manager-vs-caddy-homelab-2026/"&gt;Traefik vs Nginx Proxy Manager vs Caddy&lt;/a&gt; guide breaks down which reverse proxy fits your homelab. For Docker networking specifically, &lt;span class="sp-brand traefik"&gt;Traefik&lt;/span&gt; has the cleanest network model because it natively understands Docker labels and service&amp;nbsp;discovery.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Traefik + External Networks: Avoiding the&amp;nbsp;502&lt;/h3&gt;
&lt;p&gt;The most common Traefik networking error: you define a network in your app&amp;#8217;s Compose file but forget to declare it&amp;nbsp;as &lt;code&gt;external: true&lt;/code&gt;. Docker Compose creates a new network with a project-prefixed name&amp;nbsp;(e.g., &lt;code&gt;jellyfin_media&lt;/code&gt;) instead of joining the&amp;nbsp;existing &lt;code&gt;media&lt;/code&gt; network. Traefik is&amp;nbsp;on &lt;code&gt;media&lt;/code&gt;, Jellyfin is&amp;nbsp;on &lt;code&gt;jellyfin_media&lt;/code&gt;, they cannot communicate, and you&amp;nbsp;get &lt;code&gt;502 Bad Gateway&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Verify&amp;nbsp;with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;network&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;media
&lt;span class="c1"&gt;# Should show ONE network named &amp;quot;media&amp;quot;, not &amp;quot;jellyfin_media&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you see project-prefixed duplicates, fix the Compose file to&amp;nbsp;use &lt;code&gt;external: true&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Network Segmentation: The Homelab &lt;span class="caps"&gt;DMZ&lt;/span&gt;&amp;nbsp;Pattern&lt;/h2&gt;
&lt;p&gt;Security through network segmentation is not just for enterprises. In a homelab, the principle is simple: group containers by trust level and sensitivity, and use Docker networks as the boundary. If one segment gets compromised, the blast radius stops at the network&amp;nbsp;edge.&lt;/p&gt;
&lt;h3&gt;The Five-Zone&amp;nbsp;Model&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Zone&lt;/th&gt;
&lt;th&gt;Trust Level&lt;/th&gt;
&lt;th&gt;Example Services&lt;/th&gt;
&lt;th&gt;Network Name&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Edge&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Exposed to internet&lt;/td&gt;
&lt;td&gt;Traefik, Authelia, CrowdSec&lt;/td&gt;
&lt;td&gt;&lt;code&gt;proxy&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Public&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Internet-facing apps&lt;/td&gt;
&lt;td&gt;Nextcloud, Jellyfin, Immich&lt;/td&gt;
&lt;td&gt;&lt;code&gt;public&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Internal&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;LAN&lt;/span&gt;-only services&lt;/td&gt;
&lt;td&gt;Sonarr, Radarr, Home Assistant, Pi-hole&lt;/td&gt;
&lt;td&gt;&lt;code&gt;internal&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Databases and secrets&lt;/td&gt;
&lt;td&gt;MariaDB, PostgreSQL, Redis, Vaultwarden&lt;/td&gt;
&lt;td&gt;&lt;code&gt;storage&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Admin tools&lt;/td&gt;
&lt;td&gt;Portainer, Uptime Kuma, Grafana, &lt;span class="caps"&gt;SSH&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;mgmt&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Rules of&amp;nbsp;engagement:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Edge can talk to everything&lt;/strong&gt; — Traefik must route to all zones. Accept this risk and harden Traefik with &lt;a href="/2026/06/docker-compose-homelab/"&gt;Authelia &lt;span class="caps"&gt;SSO&lt;/span&gt;&lt;/a&gt; and rate-limiting&amp;nbsp;middleware.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Public apps can talk to Storage&lt;/strong&gt; — Nextcloud needs MariaDB. Jellyfin doesn&amp;#8217;t need Vaultwarden. Be specific: attach only the database that app actually&amp;nbsp;needs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Internal services stay internal&lt;/strong&gt; — Sonarr and Radarr should never be exposed to the internet. They communicate through&amp;nbsp;the &lt;code&gt;internal&lt;/code&gt; network&amp;nbsp;only.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Storage is silent&lt;/strong&gt; — No service on&amp;nbsp;the &lt;code&gt;storage&lt;/code&gt; network should have outbound internet access.&amp;nbsp;Use &lt;code&gt;internal: true&lt;/code&gt; on the network definition to block external&amp;nbsp;connectivity:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;bridge&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;internal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;# Blocks all outbound internet from this network&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Management is separate&lt;/strong&gt; — Portainer and &lt;span class="caps"&gt;SSH&lt;/span&gt; containers should live&amp;nbsp;on &lt;code&gt;mgmt&lt;/code&gt;, accessible only via &lt;span class="caps"&gt;VPN&lt;/span&gt; or local &lt;span class="caps"&gt;LAN&lt;/span&gt;. Never expose Portainer&amp;#8217;s dashboard directly to the internet, even behind Traefik with&amp;nbsp;authentication.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Firewall&amp;nbsp;Considerations&lt;/h3&gt;
&lt;p&gt;Docker manipulates iptables rules directly, which creates a well-known conflict: &lt;span class="caps"&gt;UFW&lt;/span&gt; or firewalld rules you write on the host are silently bypassed by Docker&amp;#8217;s own iptables entries. Docker inserts its rules at a higher priority than user-defined rules, meaning a container bound&amp;nbsp;to &lt;code&gt;-p 8080:8080&lt;/code&gt; is accessible&amp;nbsp;on &lt;code&gt;0.0.0.0:8080&lt;/code&gt; regardless of what &lt;span class="caps"&gt;UFW&lt;/span&gt;&amp;nbsp;says.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The fix for &lt;span class="caps"&gt;UFW&lt;/span&gt;&amp;nbsp;users:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# /etc/docker/daemon.json&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;iptables&amp;quot;&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Setting &lt;code&gt;iptables: false&lt;/code&gt; tells Docker to stop manipulating iptables. You then manage all firewall rules through &lt;span class="caps"&gt;UFW&lt;/span&gt; directly. The downside: Docker&amp;#8217;s inter-container communication and outbound &lt;span class="caps"&gt;NAT&lt;/span&gt; stop working unless you manually configure iptables rules. This is an advanced configuration — for most homelabbers, the simpler approach is binding containers&amp;nbsp;to &lt;code&gt;127.0.0.1&lt;/code&gt; instead&amp;nbsp;of &lt;code&gt;0.0.0.0&lt;/code&gt; and letting Traefik handle external&amp;nbsp;access.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Instead of this:&lt;/span&gt;
&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8080:8080&amp;quot;&lt;/span&gt;

&lt;span class="c1"&gt;# Do this — only Traefik on the Docker network can reach it:&lt;/span&gt;
&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;127.0.0.1:8080:8080&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With port binding restricted&amp;nbsp;to &lt;code&gt;127.0.0.1&lt;/code&gt;, the service is inaccessible from your &lt;span class="caps"&gt;LAN&lt;/span&gt; or the internet. Only Traefik (on the same Docker bridge) can route traffic to it. This is the single highest-impact security change you can make to a Docker&amp;nbsp;homelab.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Real-World Architecture: A Complete Homelab&amp;nbsp;Network&lt;/h2&gt;
&lt;p&gt;Here is a complete five-zone network architecture for a typical homelab running 20+ containers. Study the pattern, adapt it to your&amp;nbsp;stack.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────┐
│&lt;span class="w"&gt;                      &lt;/span&gt;&lt;span class="nv"&gt;INTERNET&lt;/span&gt;&lt;span class="w"&gt;                            &lt;/span&gt;│
│&lt;span class="w"&gt;                         &lt;/span&gt;│&lt;span class="w"&gt;                                &lt;/span&gt;│
│&lt;span class="w"&gt;                   &lt;/span&gt;&lt;span class="nv"&gt;Ports&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;443&lt;/span&gt;&lt;span class="w"&gt;                           &lt;/span&gt;│
│&lt;span class="w"&gt;                         &lt;/span&gt;│&lt;span class="w"&gt;                                &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;┌──────────────────────┼──────────────────────────┐&lt;span class="w"&gt;     &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nv"&gt;EDGE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;proxy&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="w"&gt;                        &lt;/span&gt;│&lt;span class="w"&gt;     &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt;  &lt;/span&gt;┌─────────┐&lt;span class="w"&gt;  &lt;/span&gt;┌──────────┐&lt;span class="w"&gt;  &lt;/span&gt;┌──────────┐&lt;span class="w"&gt;       &lt;/span&gt;│&lt;span class="w"&gt;     &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Traefik&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Authelia&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;CrowdSec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;│&lt;span class="w"&gt;       &lt;/span&gt;│&lt;span class="w"&gt;     &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt;  &lt;/span&gt;└────┬────┘&lt;span class="w"&gt;  &lt;/span&gt;└──────────┘&lt;span class="w"&gt;  &lt;/span&gt;└──────────┘&lt;span class="w"&gt;       &lt;/span&gt;│&lt;span class="w"&gt;     &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;└───────┼─────────────────────────────────────────┘&lt;span class="w"&gt;     &lt;/span&gt;│
│&lt;span class="w"&gt;          &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;routes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;all&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;zones&lt;/span&gt;&lt;span class="w"&gt;                            &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;┌───────┼─────────────────────────────────────────┐&lt;span class="w"&gt;     &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt;       &lt;/span&gt;│&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;PUBLIC&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;public&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="w"&gt;                  &lt;/span&gt;│&lt;span class="w"&gt;     &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt;  &lt;/span&gt;┌────┴────┐&lt;span class="w"&gt;  &lt;/span&gt;┌──────────┐&lt;span class="w"&gt;  &lt;/span&gt;┌────────┐&lt;span class="w"&gt;         &lt;/span&gt;│&lt;span class="w"&gt;     &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="nv"&gt;Nextcloud&lt;/span&gt;│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Jellyfin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Immich&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;│&lt;span class="w"&gt;         &lt;/span&gt;│&lt;span class="w"&gt;     &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt;  &lt;/span&gt;└────┬────┘&lt;span class="w"&gt;  &lt;/span&gt;└──────────┘&lt;span class="w"&gt;  &lt;/span&gt;└───┬────┘&lt;span class="w"&gt;         &lt;/span&gt;│&lt;span class="w"&gt;     &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;└───────┼─────────────────────────┼──────────────┘&lt;span class="w"&gt;     &lt;/span&gt;│
│&lt;span class="w"&gt;          &lt;/span&gt;│&lt;span class="w"&gt;                         &lt;/span&gt;│&lt;span class="w"&gt;                     &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;┌───────┼─────────────────────────┼──────────────┐&lt;span class="w"&gt;     &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt;       &lt;/span&gt;│&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;STORAGE&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;│&lt;span class="w"&gt;              &lt;/span&gt;│&lt;span class="w"&gt;     &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt;  &lt;/span&gt;┌────┴────┐&lt;span class="w"&gt;  &lt;/span&gt;┌──────────┐&lt;span class="w"&gt;  &lt;/span&gt;┌──┴────────┐&lt;span class="w"&gt;    &lt;/span&gt;│&lt;span class="w"&gt;     &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;MariaDB&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;Redis&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;PostgreSQL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;│&lt;span class="w"&gt;    &lt;/span&gt;│&lt;span class="w"&gt;     &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt;  &lt;/span&gt;└─────────┘&lt;span class="w"&gt;  &lt;/span&gt;└──────────┘&lt;span class="w"&gt;  &lt;/span&gt;└───────────┘&lt;span class="w"&gt;    &lt;/span&gt;│&lt;span class="w"&gt;     &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;internal&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;no&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;internet&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;│&lt;span class="w"&gt;     &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;└──────────────────────────────────────────────┘&lt;span class="w"&gt;     &lt;/span&gt;│
│&lt;span class="w"&gt;                                                        &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;┌──────────────────────────────────────────────┐&lt;span class="w"&gt;     &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nv"&gt;INTERNAL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;internal&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;│&lt;span class="w"&gt;     &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt;  &lt;/span&gt;┌────────┐&lt;span class="w"&gt; &lt;/span&gt;┌────────┐&lt;span class="w"&gt; &lt;/span&gt;┌───────┐&lt;span class="w"&gt; &lt;/span&gt;┌────────┐&lt;span class="w"&gt; &lt;/span&gt;│&lt;span class="w"&gt;     &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Sonarr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Radarr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;│&lt;span class="nv"&gt;Pi&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;hole&lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;│&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;HA&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;│&lt;span class="w"&gt;     &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt;  &lt;/span&gt;└────────┘&lt;span class="w"&gt; &lt;/span&gt;└────────┘&lt;span class="w"&gt; &lt;/span&gt;└───────┘&lt;span class="w"&gt; &lt;/span&gt;└────────┘&lt;span class="w"&gt; &lt;/span&gt;│&lt;span class="w"&gt;     &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;└──────────────────────────────────────────────┘&lt;span class="w"&gt;     &lt;/span&gt;│
│&lt;span class="w"&gt;                                                        &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;┌──────────────────────────────────────────────┐&lt;span class="w"&gt;     &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nv"&gt;MANAGEMENT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;mgmt&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="w"&gt;                  &lt;/span&gt;│&lt;span class="w"&gt;     &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt;  &lt;/span&gt;┌──────────┐&lt;span class="w"&gt; &lt;/span&gt;┌───────────┐&lt;span class="w"&gt; &lt;/span&gt;┌────────────┐&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt;     &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Portainer&lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;│&lt;span class="k"&gt;Uptime&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Kuma&lt;/span&gt;│&lt;span class="w"&gt; &lt;/span&gt;│&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;Grafana&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt;     &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt;  &lt;/span&gt;└──────────┘&lt;span class="w"&gt; &lt;/span&gt;└───────────┘&lt;span class="w"&gt; &lt;/span&gt;└────────────┘&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt;     &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;│&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nv"&gt;Access&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;VPN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;LAN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;only&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;│&lt;span class="w"&gt;     &lt;/span&gt;│
│&lt;span class="w"&gt;  &lt;/span&gt;└──────────────────────────────────────────────┘&lt;span class="w"&gt;     &lt;/span&gt;│
└─────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This architecture is not theoretical. It runs in production homelabs and has been &lt;a href="/2026/06/docker-compose-homelab/"&gt;battle-tested across dozens of setups&lt;/a&gt;.&amp;nbsp;The &lt;code&gt;internal: true&lt;/code&gt; flag on&amp;nbsp;the &lt;code&gt;storage&lt;/code&gt; network means even if an attacker escapes a container on&amp;nbsp;the &lt;code&gt;public&lt;/code&gt; zone, they cannot exfiltrate your database contents to the internet — the network simply has no route&amp;nbsp;out.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Common Docker Networking Mistakes (and&amp;nbsp;Fixes)&lt;/h2&gt;
&lt;h3&gt;1.&amp;nbsp;Using &lt;code&gt;localhost&lt;/code&gt; Between&amp;nbsp;Containers&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;The&amp;nbsp;mistake:&lt;/strong&gt; &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;DATABASE_URL=mysql://localhost:3306/mydb&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Why it fails:&lt;/strong&gt; Inside a&amp;nbsp;container, &lt;code&gt;localhost&lt;/code&gt; means the container itself. Unless MySQL is running in the same container (it should not&amp;nbsp;be), &lt;code&gt;localhost:3306&lt;/code&gt; is an empty&amp;nbsp;port.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Use the service name from your Compose file — that is what Docker&amp;#8217;s embedded &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;resolves:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;DATABASE_URL=mysql://db:3306/mydb&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;2. Exposing Ports You Don&amp;#8217;t&amp;nbsp;Need&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;The mistake:&lt;/strong&gt; Every service&amp;nbsp;gets &lt;code&gt;ports: - "XXXX:XXXX"&lt;/code&gt; in&amp;nbsp;Compose.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why it fails:&lt;/strong&gt; Each exposed port is an attack surface. A homelab with 20 services, each exposing its port&amp;nbsp;to &lt;code&gt;0.0.0.0&lt;/code&gt;, has 20 entry points an attacker can scan and probe. Your &lt;span class="caps"&gt;LAN&lt;/span&gt; is not a trusted network — smart TVs, IoT devices, and guest Wi-Fi clients all share&amp;nbsp;it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Only Traefik should expose ports to the host. Every other service communicates over Docker&amp;nbsp;networks:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Good — only Traefik gets host ports&lt;/span&gt;
&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;traefik&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;80:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;443:443&amp;quot;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# No ports block — Traefik routes to it via Docker network&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;proxy&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Need to see every port your homelab is exposing?&lt;/strong&gt;&amp;nbsp;Run &lt;code&gt;docker ps --format 'table {{.Names}}\t{{.Ports}}'&lt;/code&gt; and audit&amp;nbsp;every &lt;code&gt;0.0.0.0:XXXX&lt;/code&gt; entry. For most services, the answer&amp;nbsp;is &lt;code&gt;127.0.0.1:XXXX:XXXX&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;3.&amp;nbsp;Forgetting &lt;code&gt;external: true&lt;/code&gt; on Shared&amp;nbsp;Networks&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;The mistake:&lt;/strong&gt; Multiple Compose files reference the same network name&amp;nbsp;without &lt;code&gt;external: true&lt;/code&gt;. Docker Compose&amp;nbsp;creates &lt;code&gt;&amp;lt;project&amp;gt;_networkname&lt;/code&gt; networks instead of joining the shared&amp;nbsp;one.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Create networks once, then reference them&amp;nbsp;with &lt;code&gt;external: true&lt;/code&gt; everywhere&amp;nbsp;else:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;network&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;proxy
docker&lt;span class="w"&gt; &lt;/span&gt;network&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;media
docker&lt;span class="w"&gt; &lt;/span&gt;network&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;storage&lt;span class="w"&gt; &lt;/span&gt;--internal
docker&lt;span class="w"&gt; &lt;/span&gt;network&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;internal
docker&lt;span class="w"&gt; &lt;/span&gt;network&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;mgmt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then in every Compose&amp;nbsp;file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;external&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;media&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;external&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;4. Macvlan for Every&amp;nbsp;Container&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;The mistake:&lt;/strong&gt; &amp;#8220;I want every container to have its own &lt;span class="caps"&gt;LAN&lt;/span&gt; &lt;span class="caps"&gt;IP&lt;/span&gt; so I can access them&amp;nbsp;directly.&amp;#8221;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why it fails:&lt;/strong&gt; Macvlan is a specialist tool. Using it for every container wastes &lt;span class="caps"&gt;IP&lt;/span&gt; addresses, breaks Docker &lt;span class="caps"&gt;DNS&lt;/span&gt;, and prevents host-container communication. Docker&amp;#8217;s embedded &lt;span class="caps"&gt;DNS&lt;/span&gt; does not work across macvlan networks — you are back to hardcoding&amp;nbsp;IPs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Use macvlan for the one or two containers that genuinely need it (Home Assistant, Pi-hole with &lt;span class="caps"&gt;DHCP&lt;/span&gt;). Put everything else on user-defined bridges with Traefik&amp;nbsp;routing.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;&lt;span class="caps"&gt;FAQ&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Q: Should I put all my containers on one network or split them into multiple&amp;nbsp;networks?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Start with one user-defined bridge for everything (the Compose default). Split into separate networks when: (a) you have more than 10 containers, (b) you need to prevent specific containers from communicating, or (c) you are exposing any container directly to the internet. The five-zone model above is the target state, not the starting&amp;nbsp;point.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: Can Traefik route to a container on a macvlan&amp;nbsp;network?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;No. Traefik communicates over Docker&amp;#8217;s virtual bridge, and macvlan operates at a different layer. If a container is on macvlan, Traefik cannot reach it through Docker networking. Workaround: give the container a second interface on a user-defined bridge (Docker supports multi-network containers) and have Traefik route through&amp;nbsp;that.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: Does Docker&amp;nbsp;Compose&amp;#8217;s &lt;code&gt;network_mode: host&lt;/code&gt; disable all other&amp;nbsp;networking?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Yes. A container&amp;nbsp;with &lt;code&gt;network_mode: host&lt;/code&gt; cannot be attached to any other Docker network. You cannot mix host networking with user-defined bridges. Choose one per&amp;nbsp;container.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: How do I give a container a static &lt;span class="caps"&gt;IP&lt;/span&gt; on a user-defined&amp;nbsp;bridge?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Docker supports static &lt;span class="caps"&gt;IP&lt;/span&gt; assignment on user-defined bridges&amp;nbsp;with &lt;code&gt;--subnet&lt;/code&gt; and&amp;nbsp;per-container &lt;code&gt;ipv4_address&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;custom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;bridge&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ipam&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;subnet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;10.99.0.0/24&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;custom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;ipv4_address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;10.99.0.100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Avoid this unless you have a concrete reason — it defeats Docker&amp;#8217;s dynamic &lt;span class="caps"&gt;IP&lt;/span&gt; management and creates a single point of configuration&amp;nbsp;drift.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: Can containers on different Docker hosts communicate over a&amp;nbsp;bridge?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Not natively. Docker bridge networks are host-local. For cross-host container communication, you need Docker Swarm with overlay networks, or a Layer 3 solution like Tailscale. For most homelabbers running on a single Proxmox node, this is a&amp;nbsp;non-issue.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: What happens when two Compose files define the same&amp;nbsp;network?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If both define it&amp;nbsp;as &lt;code&gt;external: true&lt;/code&gt;, they reference the same pre-existing network. If one defines it inline and the other&amp;nbsp;uses &lt;code&gt;external: true&lt;/code&gt;, they land on different networks and the containers cannot communicate.&amp;nbsp;Consistent &lt;code&gt;external: true&lt;/code&gt; usage across all Compose files is the&amp;nbsp;solution.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: How do I block internet access for a specific&amp;nbsp;container?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Use&amp;nbsp;the &lt;code&gt;internal: true&lt;/code&gt; flag on the&amp;nbsp;network:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;no-internet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;bridge&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;internal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Any container on this network can communicate with other containers on the same network but has no route to the internet. This is ideal for databases and sensitive&amp;nbsp;services.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion: The Clean Setup&amp;nbsp;Checklist&lt;/h2&gt;
&lt;p&gt;Docker networking rewards discipline. Start with the default, then migrate toward segmentation as your homelab grows. Here is the checklist for a network architecture that&amp;nbsp;scales:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;✅ &lt;strong&gt;No containers on the&amp;nbsp;default &lt;code&gt;bridge&lt;/code&gt; network&lt;/strong&gt;&amp;nbsp;— &lt;code&gt;docker network inspect bridge | grep Name&lt;/code&gt; should return only infrastructure containers Docker itself placed&amp;nbsp;there.&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;User-defined bridges for every service group&lt;/strong&gt; — at minimum,&amp;nbsp;separate &lt;code&gt;proxy&lt;/code&gt;, &lt;code&gt;apps&lt;/code&gt;,&amp;nbsp;and &lt;code&gt;storage&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Traefik is the only container exposing host ports&lt;/strong&gt; — everything else communicates over Docker&amp;nbsp;networks.&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Databases bound&amp;nbsp;to &lt;code&gt;internal: true&lt;/code&gt; networks&lt;/strong&gt; — no outbound internet from your storage&amp;nbsp;layer.&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Portainer and admin tools&amp;nbsp;on &lt;code&gt;mgmt&lt;/code&gt;, accessed via &lt;span class="caps"&gt;VPN&lt;/span&gt;&lt;/strong&gt; — never exposed to the&amp;nbsp;internet.&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;&lt;code&gt;127.0.0.1&lt;/code&gt; port bindings where possible&lt;/strong&gt; — only Traefik&amp;nbsp;needs &lt;code&gt;0.0.0.0&lt;/code&gt; exposure.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If your current Docker setup looks nothing like this, do not panic. Move one service group at a time. Start by creating&amp;nbsp;a &lt;code&gt;proxy&lt;/code&gt; network and moving Traefik onto it. Next cycle,&amp;nbsp;create &lt;code&gt;storage&lt;/code&gt; and move your databases. The goal is continuous improvement, not a weekend&amp;nbsp;rewrite.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Next reads to level up your Docker&amp;nbsp;infrastructure:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/2026/06/docker-compose-for-beginners/"&gt;Docker Compose for Beginners: From docker run to Production Stacks&lt;/a&gt; — if you are still using&amp;nbsp;raw &lt;code&gt;docker run&lt;/code&gt; commands, start&amp;nbsp;here.&lt;/li&gt;
&lt;li&gt;&lt;a href="/2026/06/traefik-vs-nginx-proxy-manager-vs-caddy-homelab-2026/"&gt;Traefik vs Nginx Proxy Manager vs Caddy for Homelab 2026&lt;/a&gt; — pick the right reverse proxy for your network&amp;nbsp;architecture.&lt;/li&gt;
&lt;li&gt;&lt;a href="/2026/06/homelab-networking-basics/"&gt;Homelab Networking Basics: VLANs, Subnets, and &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/a&gt; — extend these Docker concepts to your physical&amp;nbsp;network.&lt;/li&gt;
&lt;li&gt;&lt;a href="/2026/06/securing-homelab-zero-trust/"&gt;Securing Your Homelab with Zero Trust Networking&lt;/a&gt; — apply network segmentation beyond&amp;nbsp;Docker.&lt;/li&gt;
&lt;li&gt;&lt;a href="/2026/06/docker-compose-homelab/"&gt;Docker Compose Homelab: The Complete Stack&lt;/a&gt; — see how networking fits into a full homelab Compose&amp;nbsp;setup.&lt;/li&gt;
&lt;li&gt;&lt;a href="/2026/06/self-hosted-backup-strategy-homelab-2026/"&gt;Self-Hosted Backup Strategy for Homelab 2026&lt;/a&gt; — once your networks are solid, make sure your data&amp;nbsp;survives.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Tutorials"/><category term="docker"/><category term="docker-networking"/><category term="docker-compose"/><category term="homelab"/><category term="self-hosted"/><category term="traefik"/><category term="nginx-proxy-manager"/><category term="reverse-proxy"/><category term="network-security"/><category term="bridge"/><category term="macvlan"/><category term="container-isolation"/></entry><entry><title>The Ultimate Guide to Building Your First Homelab Server in 2026</title><link href="https://steadypub.com/2026/06/building-first-homelab-server-2026/" rel="alternate"/><published>2026-06-08T00:00:00+07:00</published><updated>2026-06-17T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-08:/2026/06/building-first-homelab-server-2026/</id><summary type="html">&lt;p&gt;A comprehensive guide to starting your homelab journey, from hardware selection to essential software services with step-by-step setup&amp;nbsp;commands.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Starting a homelab is one of the most rewarding journeys for any tech enthusiast. Whether you are a student, a developer, or just someone who loves tinkering with technology, a homelab provides a safe, sandboxed environment to experiment with networking, server administration, containerization, and data&amp;nbsp;storage.&lt;/p&gt;
&lt;p&gt;In this guide, we will walk through the essential steps to building your first homelab server in 2026 — from choosing hardware to deploying your first Docker service — keeping cost-efficiency and modularity at the&amp;nbsp;forefront.&lt;/p&gt;
&lt;h2&gt;Why Build a&amp;nbsp;Homelab?&lt;/h2&gt;
&lt;p&gt;Before we dive into hardware and software, let&amp;#8217;s define why you would want to spend time and resources on a&amp;nbsp;homelab.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Learning Opportunity:&lt;/strong&gt; There is no better way to master Linux, Docker, or Kubernetes than by running them on your own&amp;nbsp;metal.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Data Privacy:&lt;/strong&gt; By hosting your own cloud storage (Nextcloud), media server (Jellyfin), or password manager (Vaultwarden), you take control of your data away from Big&amp;nbsp;Tech.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sandbox Environment:&lt;/strong&gt; Test new software, configurations, or &lt;span class="caps"&gt;CI&lt;/span&gt;/&lt;span class="caps"&gt;CD&lt;/span&gt; pipelines without fear of breaking your primary&amp;nbsp;workstation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Convenience:&lt;/strong&gt; Host useful services that make your daily life easier, like ad-blockers (Pi-hole) or local dashboard aggregators&amp;nbsp;(Heimdall).&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;1. Hardware Selection: Start Small, Grow&amp;nbsp;Large&lt;/h2&gt;
&lt;p&gt;One of the biggest pitfalls for beginners is &amp;#8220;analysis paralysis&amp;#8221; regarding hardware. You do &lt;em&gt;not&lt;/em&gt; need a rack-mount server to start. In fact, for most, a decommissioned office &lt;span class="caps"&gt;PC&lt;/span&gt; or a low-power Mini &lt;span class="caps"&gt;PC&lt;/span&gt; is the perfect starting&amp;nbsp;point.&lt;/p&gt;
&lt;h3&gt;Recommended Entry-Level&amp;nbsp;Hardware&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Used &lt;span class="caps"&gt;SFF&lt;/span&gt; (Small Form Factor) Office PCs:&lt;/strong&gt; Look for Dell OptiPlex, &lt;span class="caps"&gt;HP&lt;/span&gt; EliteDesk, or Lenovo ThinkCentre units with Intel Core i5 or i7 processors (8th gen or newer). These are power-efficient, quiet, and cost $80–200 on&amp;nbsp;eBay.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mini PCs:&lt;/strong&gt; Devices like the Beelink &lt;span class="caps"&gt;SER5&lt;/span&gt;, Minisforum &lt;span class="caps"&gt;UM690&lt;/span&gt;, or Intel &lt;span class="caps"&gt;NUC&lt;/span&gt; offer high performance in a tiny footprint, often consuming less than 15W at&amp;nbsp;idle.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Old Laptops:&lt;/strong&gt; A laptop with a broken screen is basically a server with a built-in &lt;span class="caps"&gt;UPS&lt;/span&gt; (the battery!) and keyboard. Just keep the lid open for&amp;nbsp;airflow.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Key&amp;nbsp;Considerations&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt; is King:&lt;/strong&gt; In a homelab, &lt;span class="caps"&gt;CPU&lt;/span&gt; is rarely the bottleneck; &lt;span class="caps"&gt;RAM&lt;/span&gt; is. Aim for at least &lt;span class="caps"&gt;16GB&lt;/span&gt;. If you plan to run many virtual machines (VMs), &lt;span class="caps"&gt;32GB&lt;/span&gt;+ is&amp;nbsp;ideal.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Storage:&lt;/strong&gt; Start with a &lt;span class="caps"&gt;256GB&lt;/span&gt;+ &lt;span class="caps"&gt;SSD&lt;/span&gt; for your &lt;span class="caps"&gt;OS&lt;/span&gt; and main apps. Add a large mechanical &lt;span class="caps"&gt;HDD&lt;/span&gt; later for media or&amp;nbsp;backups.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Power Budget:&lt;/strong&gt; Calculate annual electricity&amp;nbsp;cost: &lt;code&gt;watts × 24h × 365 / 1000 × kWh_rate&lt;/code&gt;. A 30W server costs ~$30/year at&amp;nbsp;$0.12/kWh.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;2. Choosing Your Operating System (The&amp;nbsp;Hypervisor)&lt;/h2&gt;
&lt;p&gt;Once you have hardware, you need an &lt;span class="caps"&gt;OS&lt;/span&gt;. For a modern homelab, a hypervisor is highly recommended, allowing you to run multiple virtual machines and containers on a single&amp;nbsp;machine.&lt;/p&gt;
&lt;h3&gt;Option A: Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;&amp;nbsp;(Recommended)&lt;/h3&gt;
&lt;p&gt;Proxmox is based on Debian and provides a web-based interface for managing &lt;span class="caps"&gt;KVM&lt;/span&gt; virtual machines and &lt;span class="caps"&gt;LXC&lt;/span&gt; containers. It&amp;#8217;s free, open-source, and has an incredibly active&amp;nbsp;community.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Install Proxmox on bare&amp;nbsp;metal:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# 1. Download the ISO from proxmox.com&lt;/span&gt;
&lt;span class="c1"&gt;# 2. Write to USB: sudo dd if=proxmox-ve_*.iso of=/dev/sdX bs=4M status=progress&lt;/span&gt;
&lt;span class="c1"&gt;# 3. Boot from USB and follow the installer prompts&lt;/span&gt;
&lt;span class="c1"&gt;# 4. After install, access web UI at https://192.168.1.10:8006&lt;/span&gt;

&lt;span class="c1"&gt;# Switch to no-subscription repo for free updates:&lt;/span&gt;
sed&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;s/^deb/# deb/&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/apt/sources.list.d/pve-enterprise.list
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;deb http://download.proxmox.com/debian/pve bookworm pve-no-subscription&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/apt/sources.list
apt&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;dist-upgrade&lt;span class="w"&gt; &lt;/span&gt;-y
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Option B: Ubuntu Server +&amp;nbsp;Docker&lt;/h3&gt;
&lt;p&gt;If you prefer a simpler setup without full&amp;nbsp;virtualization:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Install Ubuntu Server 24.04 LTS&lt;/span&gt;
&lt;span class="c1"&gt;# Then install Docker:&lt;/span&gt;
curl&lt;span class="w"&gt; &lt;/span&gt;-fsSL&lt;span class="w"&gt; &lt;/span&gt;https://get.docker.com&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sh
sudo&lt;span class="w"&gt; &lt;/span&gt;usermod&lt;span class="w"&gt; &lt;/span&gt;-aG&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$USER&lt;/span&gt;
newgrp&lt;span class="w"&gt; &lt;/span&gt;docker

&lt;span class="c1"&gt;# Test it:&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;hello-world
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;3. Essential Software Services to&amp;nbsp;Install&lt;/h2&gt;
&lt;p&gt;Once your hypervisor or &lt;span class="caps"&gt;OS&lt;/span&gt; is running, here are the must-have&amp;nbsp;services:&lt;/p&gt;
&lt;h3&gt;Step 1: Set Up Docker (Inside Proxmox &lt;span class="caps"&gt;LXC&lt;/span&gt; or&amp;nbsp;Ubuntu)&lt;/h3&gt;
&lt;p&gt;If using Proxmox, create a privileged &lt;span class="caps"&gt;LXC&lt;/span&gt; container for Docker (nesting&amp;nbsp;enabled):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pct&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;local:vztmpl/debian-12-standard_12.7-1_amd64.tar.zst&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--hostname&lt;span class="w"&gt; &lt;/span&gt;docker-host&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--storage&lt;span class="w"&gt; &lt;/span&gt;local-lvm&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--memory&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4096&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--cores&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--net0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;eth0,bridge&lt;span class="o"&gt;=&lt;/span&gt;vmbr0,ip&lt;span class="o"&gt;=&lt;/span&gt;dhcp&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--features&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;nesting&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--rootfs&lt;span class="w"&gt; &lt;/span&gt;local-lvm:20
pct&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;
pct&lt;span class="w"&gt; &lt;/span&gt;enter&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Inside the container, install&amp;nbsp;Docker:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-fsSL&lt;span class="w"&gt; &lt;/span&gt;https://get.docker.com&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Step 2: Deploy Pi-hole for Network-wide Ad&amp;nbsp;Blocking&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;pihole&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;53&lt;/span&gt;:53/tcp&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;53&lt;/span&gt;:53/udp&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8081&lt;/span&gt;:80&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;pihole_etc:/etc/pihole&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;pihole_dnsmasq:/etc/dnsmasq.d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;WEBPASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-admin-password&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;TZ&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Asia/Jakarta&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--restart&lt;span class="w"&gt; &lt;/span&gt;unless-stopped&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;pihole/pihole:latest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; Set your router&amp;#8217;s &lt;span class="caps"&gt;DHCP&lt;/span&gt; to hand out your homelab &lt;span class="caps"&gt;IP&lt;/span&gt; as the primary &lt;span class="caps"&gt;DNS&lt;/span&gt;. All devices will now be&amp;nbsp;ad-free.&lt;/p&gt;
&lt;h3&gt;Step 3: Deploy Jellyfin for Media&amp;nbsp;Streaming&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;~/docker/jellyfin/&lt;span class="o"&gt;{&lt;/span&gt;config,cache&lt;span class="o"&gt;}&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;jellyfin&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8096&lt;/span&gt;:8096&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;~/docker/jellyfin/config:/config&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;~/docker/jellyfin/cache:/cache&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;/path/to/media:/media:ro&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--device&lt;span class="w"&gt; &lt;/span&gt;/dev/dri:/dev/dri&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--restart&lt;span class="w"&gt; &lt;/span&gt;unless-stopped&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;jellyfin/jellyfin:latest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Step 4: Deploy Vaultwarden (Password&amp;nbsp;Manager)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;vaultwarden&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4743&lt;/span&gt;:80&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;~/docker/vaultwarden:/data&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;WEBSOCKET_ENABLED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;SIGNUPS_ALLOWED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--restart&lt;span class="w"&gt; &lt;/span&gt;unless-stopped&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;vaultwarden/server:latest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Step 5: Set Up a Dashboard&amp;nbsp;(Homepage)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;homepage&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3002&lt;/span&gt;:3000&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;~/docker/homepage:/app/config&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--restart&lt;span class="w"&gt; &lt;/span&gt;unless-stopped&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;ghcr.io/gethomepage/homepage:latest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;4. Networking and&amp;nbsp;Security&lt;/h2&gt;
&lt;p&gt;A homelab without proper network hygiene can quickly become a&amp;nbsp;liability.&lt;/p&gt;
&lt;h3&gt;Static &lt;span class="caps"&gt;IP&lt;/span&gt;&amp;nbsp;Configuration&lt;/h3&gt;
&lt;p&gt;Assign your server a static &lt;span class="caps"&gt;IP&lt;/span&gt; in your router&amp;#8217;s &lt;span class="caps"&gt;DHCP&lt;/span&gt; reservation (recommended) or statically configure&amp;nbsp;it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Ubuntu/Debian Netplan&lt;/span&gt;
cat&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/netplan/01-netcfg.yaml&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&amp;lt; &amp;#39;EOF&amp;#39;&lt;/span&gt;
&lt;span class="s"&gt;network:&lt;/span&gt;
&lt;span class="s"&gt;  version: 2&lt;/span&gt;
&lt;span class="s"&gt;  ethernets:&lt;/span&gt;
&lt;span class="s"&gt;    eth0:&lt;/span&gt;
&lt;span class="s"&gt;      addresses:&lt;/span&gt;
&lt;span class="s"&gt;        - 192.168.1.10/24&lt;/span&gt;
&lt;span class="s"&gt;      routes:&lt;/span&gt;
&lt;span class="s"&gt;        - to: default&lt;/span&gt;
&lt;span class="s"&gt;          via: 192.168.1.1&lt;/span&gt;
&lt;span class="s"&gt;      nameservers:&lt;/span&gt;
&lt;span class="s"&gt;        addresses: [1.1.1.1, 8.8.8.8]&lt;/span&gt;
&lt;span class="s"&gt;EOF&lt;/span&gt;
netplan&lt;span class="w"&gt; &lt;/span&gt;apply
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Firewall&amp;nbsp;Basics&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# UFW (Ubuntu)&lt;/span&gt;
ufw&lt;span class="w"&gt; &lt;/span&gt;allow&lt;span class="w"&gt; &lt;/span&gt;OpenSSH
ufw&lt;span class="w"&gt; &lt;/span&gt;allow&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;,443/tcp&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Reverse proxy&lt;/span&gt;
ufw&lt;span class="w"&gt; &lt;/span&gt;allow&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;51820&lt;/span&gt;/udp&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;# WireGuard&lt;/span&gt;
ufw&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;enable&lt;/span&gt;
ufw&lt;span class="w"&gt; &lt;/span&gt;status&lt;span class="w"&gt; &lt;/span&gt;verbose
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Reverse&amp;nbsp;Proxy&lt;/h3&gt;
&lt;p&gt;Use Nginx Proxy Manager (Docker) to route external traffic to your services with automatic &lt;span class="caps"&gt;SSL&lt;/span&gt; via Let&amp;#8217;s&amp;nbsp;Encrypt:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;nginx-proxy-manager&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;:80&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;443&lt;/span&gt;:443&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;81&lt;/span&gt;:81&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;~/docker/nginx-proxy-manager:/data&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--restart&lt;span class="w"&gt; &lt;/span&gt;unless-stopped&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;jc21/nginx-proxy-manager:latest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then in the &lt;span class="caps"&gt;UI&lt;/span&gt;&amp;nbsp;at &lt;code&gt;http://&amp;lt;homelab-ip&amp;gt;:81&lt;/code&gt;, add proxy hosts&amp;nbsp;pointing &lt;code&gt;service.yourdomain.com&lt;/code&gt; to the internal Docker IPs:8096 (Jellyfin), :4743 (Vaultwarden),&amp;nbsp;etc.&lt;/p&gt;
&lt;h3&gt;&lt;span class="caps"&gt;VPN&lt;/span&gt; for Remote&amp;nbsp;Access&lt;/h3&gt;
&lt;p&gt;Never expose admin panels directly. Use Tailscale for zero-config secure&amp;nbsp;access:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Install Tailscale&lt;/span&gt;
curl&lt;span class="w"&gt; &lt;/span&gt;-fsSL&lt;span class="w"&gt; &lt;/span&gt;https://tailscale.com/install.sh&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sh
sudo&lt;span class="w"&gt; &lt;/span&gt;tailscale&lt;span class="w"&gt; &lt;/span&gt;up
&lt;span class="c1"&gt;# Open the URL, authenticate with your Google/GitHub/Microsoft account&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now access your homelab services via the Tailscale &lt;span class="caps"&gt;IP&lt;/span&gt; from any&amp;nbsp;device.&lt;/p&gt;
&lt;h2&gt;5.&amp;nbsp;Backups&lt;/h2&gt;
&lt;p&gt;Configure automatic backups before you need&amp;nbsp;them:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Create backup script&lt;/span&gt;
cat&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;~/backup-homelab.sh&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&amp;lt; &amp;#39;EOF&amp;#39;&lt;/span&gt;
&lt;span class="s"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="s"&gt;BACKUP_DIR=&amp;quot;/mnt/backup&amp;quot;&lt;/span&gt;
&lt;span class="s"&gt;DATE=$(date +%Y%m%d-%H%M%S)&lt;/span&gt;

&lt;span class="s"&gt;# Back up Docker volumes&lt;/span&gt;
&lt;span class="s"&gt;docker run --rm -v homelab_data:/data -v $BACKUP_DIR:/backup \&lt;/span&gt;
&lt;span class="s"&gt;  alpine tar czf /backup/homelab-data-$DATE.tar.gz -C /data .&lt;/span&gt;

&lt;span class="s"&gt;# Keep only last 14 days&lt;/span&gt;
&lt;span class="s"&gt;find $BACKUP_DIR -name &amp;quot;*.tar.gz&amp;quot; -mtime +14 -delete&lt;/span&gt;
&lt;span class="s"&gt;EOF&lt;/span&gt;
chmod&lt;span class="w"&gt; &lt;/span&gt;+x&lt;span class="w"&gt; &lt;/span&gt;~/backup-homelab.sh

&lt;span class="c1"&gt;# Add to crontab (runs daily at 3 AM)&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;crontab&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&amp;gt;/dev/null&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;0 3 * * * /root/backup-homelab.sh&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;crontab&lt;span class="w"&gt; &lt;/span&gt;-
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Building your first homelab is an iterative process. Start with one machine and one service. Learn how it works, how to back it up, and how to keep it updated. As your curiosity grows, so will your&amp;nbsp;lab.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s a quick checklist to get started:
- [ ] Acquire hardware (old desktop, Mini &lt;span class="caps"&gt;PC&lt;/span&gt;, or laptop)
- [ ] Install Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; or Ubuntu Server
- [ ] Set up Docker
- [ ] Deploy Pi-hole (ad blocking)
- [ ] Deploy Jellyfin (media) or Nextcloud (files)
- [ ] Configure reverse proxy (Nginx Proxy Manager)
- [ ] Set up Tailscale for remote access
- [ ] Configure daily backups
- [ ] Join r/homelab and share your&amp;nbsp;setup!&lt;/p&gt;
&lt;p&gt;Remember: the goal is to learn and to enjoy the process. Don&amp;#8217;t worry about having the perfect setup on day one. Happy&amp;nbsp;hosting!&lt;/p&gt;</content><category term="Guides"/><category term="homelab"/><category term="self-hosted"/><category term="server"/><category term="hardware"/><category term="guide"/><category term="pro..."/><category term="docker"/><category term="2026"/></entry><entry><title>Mastering Proxmox Backup Server: The Essential Homelab Guide 2026</title><link href="https://steadypub.com/2026/06/mastering-proxmox-backup-server-2026/" rel="alternate"/><published>2026-06-08T00:00:00+07:00</published><updated>2026-06-08T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-08:/2026/06/mastering-proxmox-backup-server-2026/</id><summary type="html">&lt;p&gt;A deep dive into setting up Proxmox Backup Server (&lt;span class="caps"&gt;PBS&lt;/span&gt;) in 2026 for a robust, deduplicated, and secure homelab backup strategy. Includes step-by-step installation, datastore creation, &lt;span class="caps"&gt;PVE&lt;/span&gt; integration, and restore&amp;nbsp;walkthroughs.&lt;/p&gt;</summary><content type="html">&lt;p&gt;In the evolving landscape of self-hosting and home virtualization, the importance of a reliable backup strategy cannot be overstated. As we progress through 2026, data growth and the complexity of homelab services make simple file copies insufficient. This guide explores setting up and optimizing Proxmox Backup Server (&lt;span class="caps"&gt;PBS&lt;/span&gt;) to ensure your virtualized environment remains resilient against failure — with real commands, not just&amp;nbsp;theory.&lt;/p&gt;
&lt;h2&gt;Why Proxmox Backup Server (&lt;span class="caps"&gt;PBS&lt;/span&gt;)?&lt;/h2&gt;
&lt;p&gt;Traditional backup methods often involve massive full snapshots, consuming storage bandwidth and disk space rapidly. &lt;span class="caps"&gt;PBS&lt;/span&gt; changes the paradigm&amp;nbsp;with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Deduplication:&lt;/strong&gt; Only changed blocks are stored, dramatically reducing storage requirements. A typical 100 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;VM&lt;/span&gt; with 2 &lt;span class="caps"&gt;GB&lt;/span&gt; daily changes uses only ~2 &lt;span class="caps"&gt;GB&lt;/span&gt; per incremental&amp;nbsp;backup.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Incremental Backups:&lt;/strong&gt; Forever-incremental architecture means the first backup is a full, and every subsequent backup is a delta — no periodic fulls&amp;nbsp;needed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Client-Side Encryption:&lt;/strong&gt; Encrypt backups before they leave your &lt;span class="caps"&gt;PVE&lt;/span&gt; host, ensuring data is secure even if the backup storage is&amp;nbsp;compromised.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Native Integration:&lt;/strong&gt; &lt;span class="caps"&gt;PBS&lt;/span&gt; appears as a storage target directly in the Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; &lt;span class="caps"&gt;UI&lt;/span&gt; — no scripts or cron jobs&amp;nbsp;required.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Verification:&lt;/strong&gt; Automatic backup verification (&lt;span class="caps"&gt;CRC&lt;/span&gt; checksums) catches corruption before you need to&amp;nbsp;restore.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Setting Up Your &lt;span class="caps"&gt;PBS&lt;/span&gt;&amp;nbsp;Instance&lt;/h2&gt;
&lt;h3&gt;Hardware&amp;nbsp;Considerations&lt;/h3&gt;
&lt;p&gt;While &lt;span class="caps"&gt;PBS&lt;/span&gt; is resource-efficient, it benefits from fast storage for&amp;nbsp;metadata:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;:&lt;/strong&gt; 2-4 cores. Encryption and deduplication benefit from modern &lt;span class="caps"&gt;CPU&lt;/span&gt; extensions (&lt;span class="caps"&gt;AES&lt;/span&gt;-&lt;span class="caps"&gt;NI&lt;/span&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;:&lt;/strong&gt; 4 &lt;span class="caps"&gt;GB&lt;/span&gt; minimum, 8 &lt;span class="caps"&gt;GB&lt;/span&gt; recommended. Deduplication metadata is&amp;nbsp;memory-resident.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Storage:&lt;/strong&gt; &lt;span class="caps"&gt;ZFS&lt;/span&gt; is highly recommended for data integrity. Use an &lt;span class="caps"&gt;SSD&lt;/span&gt; for the metadata volume and HDDs for bulk&amp;nbsp;data.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Network:&lt;/strong&gt; 1 Gbps minimum; 2.5+ Gbps if backing up multiple hosts&amp;nbsp;simultaneously.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Installation&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Download the &lt;span class="caps"&gt;ISO&lt;/span&gt;&lt;/strong&gt; from the &lt;a href="https://www.proxmox.com/en/downloads/proxmox-backup-server"&gt;Proxmox Backup Server download page&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Write to &lt;span class="caps"&gt;USB&lt;/span&gt;&lt;/strong&gt; and boot the target&amp;nbsp;machine.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Install via the installer&lt;/strong&gt; — the process is identical to &lt;span class="caps"&gt;PVE&lt;/span&gt;:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Select target&amp;nbsp;disk&lt;/li&gt;
&lt;li&gt;Configure timezone and&amp;nbsp;keyboard&lt;/li&gt;
&lt;li&gt;Set root password and&amp;nbsp;email&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Configure static &lt;span class="caps"&gt;IP&lt;/span&gt; with hostname (&lt;span class="caps"&gt;FQDN&lt;/span&gt;&amp;nbsp;format: &lt;code&gt;pbs01.yourdomain.local&lt;/code&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Post-install: Switch to no-subscription&amp;nbsp;repos:&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Comment out enterprise repo&lt;/span&gt;
sed&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;s/^deb/# deb/&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/apt/sources.list.d/pbs-enterprise.list

&lt;span class="c1"&gt;# Add no-subscription repo&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;deb http://download.proxmox.com/debian/pbs bookworm pbs-no-subscription&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/apt/sources.list

&lt;span class="c1"&gt;# Update and reboot&lt;/span&gt;
apt&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;dist-upgrade&lt;span class="w"&gt; &lt;/span&gt;-y
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Creating Your First&amp;nbsp;Datastore&lt;/h3&gt;
&lt;p&gt;A datastore is a directory where &lt;span class="caps"&gt;PBS&lt;/span&gt; stores backup data. Create one via &lt;span class="caps"&gt;CLI&lt;/span&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Create a ZFS pool for the datastore (if using a dedicated disk)&lt;/span&gt;
zpool&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ashift&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;backup-pool&lt;span class="w"&gt; &lt;/span&gt;/dev/sdb
zfs&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;compression&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;lz4&lt;span class="w"&gt; &lt;/span&gt;backup-pool

&lt;span class="c1"&gt;# Create the datastore directory&lt;/span&gt;
mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;/backup-pool/datastore/main-store

&lt;span class="c1"&gt;# Configure it in PBS&lt;/span&gt;
proxmox-backup-manager&lt;span class="w"&gt; &lt;/span&gt;datastore&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;main-store&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--path&lt;span class="w"&gt; &lt;/span&gt;/backup-pool/datastore/main-store&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--gc-schedule&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;daily&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--verify-new&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--verify-existing

&lt;span class="c1"&gt;# Check datastore status&lt;/span&gt;
proxmox-backup-manager&lt;span class="w"&gt; &lt;/span&gt;datastore&lt;span class="w"&gt; &lt;/span&gt;list
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Alternatively, create the datastore via the &lt;span class="caps"&gt;PBS&lt;/span&gt; web &lt;span class="caps"&gt;UI&lt;/span&gt;: &lt;code&gt;Administration → Storage → Datastore → Add&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Creating &lt;span class="caps"&gt;API&lt;/span&gt; Credentials for &lt;span class="caps"&gt;PVE&lt;/span&gt;&amp;nbsp;Integration&lt;/h3&gt;
&lt;p&gt;Before connecting &lt;span class="caps"&gt;PVE&lt;/span&gt; to &lt;span class="caps"&gt;PBS&lt;/span&gt;, generate an &lt;span class="caps"&gt;API&lt;/span&gt;&amp;nbsp;token:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Navigate&amp;nbsp;to &lt;code&gt;Configuration → Access Control → API Tokens&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Create a token for&amp;nbsp;user &lt;code&gt;root@pam&lt;/code&gt; (or a dedicated backup&amp;nbsp;user)&lt;/li&gt;
&lt;li&gt;Assign&amp;nbsp;the &lt;code&gt;Datastore.Read&lt;/code&gt; and &lt;code&gt;Datastore.Backup&lt;/code&gt; permissions&lt;/li&gt;
&lt;li&gt;Copy the token secret immediately — it&amp;#8217;s shown only&amp;nbsp;once&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Integrating &lt;span class="caps"&gt;PBS&lt;/span&gt; with Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;&lt;/h2&gt;
&lt;h3&gt;Add &lt;span class="caps"&gt;PBS&lt;/span&gt; as a Storage&amp;nbsp;Target&lt;/h3&gt;
&lt;p&gt;In the Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; web &lt;span class="caps"&gt;UI&lt;/span&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go&amp;nbsp;to &lt;code&gt;Datacenter → Storage → Add → Proxmox Backup Server&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Fill in the&amp;nbsp;fields:&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;ID&lt;/span&gt;:&lt;/strong&gt; &lt;code&gt;pbs-main&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Server:&lt;/strong&gt; &lt;span class="caps"&gt;IP&lt;/span&gt; or hostname of your &lt;span class="caps"&gt;PBS&lt;/span&gt;&amp;nbsp;instance&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Datastore:&lt;/strong&gt; &lt;code&gt;main-store&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fingerprint:&lt;/strong&gt;&amp;nbsp;Run &lt;code&gt;ssh root@pbs01.example.com "proxmox-backup-manager cert info"&lt;/code&gt; and copy the&amp;nbsp;fingerprint&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Username:&lt;/strong&gt; &lt;code&gt;root@pam&lt;/code&gt; (or your backup&amp;nbsp;user)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Password / &lt;span class="caps"&gt;API&lt;/span&gt; Token:&lt;/strong&gt; Paste the token&amp;nbsp;secret&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;Add&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Verify connectivity: The storage should appear in&amp;nbsp;the &lt;code&gt;Datacenter → Storage&lt;/code&gt; list with green&amp;nbsp;status.&lt;/p&gt;
&lt;h3&gt;Configure Backup&amp;nbsp;Schedule&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Create a backup job for all VMs on this node&lt;/span&gt;
pvesh&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;/cluster/backup&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--id&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;daily-all&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--schedule&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;0 2 * * *&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--mode&lt;span class="w"&gt; &lt;/span&gt;snapshot&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--compress&lt;span class="w"&gt; &lt;/span&gt;zstd&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--storage&lt;span class="w"&gt; &lt;/span&gt;pbs-main&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--all&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--notes&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Daily backup of all VMs to PBS&amp;quot;&lt;/span&gt;

&lt;span class="c1"&gt;# List configured backup jobs&lt;/span&gt;
pvesh&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;/cluster/backup
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Or configure via the &lt;span class="caps"&gt;UI&lt;/span&gt;: &lt;code&gt;Datacenter → Backup → Add&lt;/code&gt;. Set:
- &lt;strong&gt;Schedule:&lt;/strong&gt; &lt;code&gt;0 2 * * *&lt;/code&gt; (daily at 2 &lt;span class="caps"&gt;AM&lt;/span&gt;)
- &lt;strong&gt;Mode:&lt;/strong&gt; Snapshot (no downtime)
- &lt;strong&gt;Compression:&lt;/strong&gt; Zstandard (fastest)
- &lt;strong&gt;Storage:&lt;/strong&gt; Your &lt;span class="caps"&gt;PBS&lt;/span&gt;&amp;nbsp;datastore&lt;/p&gt;
&lt;h2&gt;Restoring from a&amp;nbsp;Backup&lt;/h2&gt;
&lt;h3&gt;Restore a Single &lt;span class="caps"&gt;VM&lt;/span&gt;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# List available backups for a VM&lt;/span&gt;
proxmox-backup-client&lt;span class="w"&gt; &lt;/span&gt;snapshot&lt;span class="w"&gt; &lt;/span&gt;list&lt;span class="w"&gt; &lt;/span&gt;root@pam@store1.example.com:main-store

&lt;span class="c1"&gt;# Restore the entire VM&lt;/span&gt;
&lt;span class="c1"&gt;# (Or do this through the PVE UI: select VM → Backup → Restore)&lt;/span&gt;

&lt;span class="c1"&gt;# Restore a single file from a backup&lt;/span&gt;
proxmox-backup-client&lt;span class="w"&gt; &lt;/span&gt;restore&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;root@pam@pbs01.example.com:main-store/ct/100/2026-06-15T00:00:00Z&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;/var/lib/mysql&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;/tmp/mysql-restore
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Restore via Web &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;In &lt;span class="caps"&gt;PVE&lt;/span&gt;, select the &lt;span class="caps"&gt;VM&lt;/span&gt;/&lt;span class="caps"&gt;CT&lt;/span&gt;&amp;nbsp;→ &lt;code&gt;Backup&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Choose the backup snapshot&amp;nbsp;→ &lt;code&gt;Restore&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Select target storage and&amp;nbsp;node&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;Restore&lt;/code&gt; — the &lt;span class="caps"&gt;VM&lt;/span&gt; will be recreated from the&amp;nbsp;backup&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Remote Backup Sync (Offsite&amp;nbsp;Strategy)&lt;/h2&gt;
&lt;p&gt;&lt;span class="caps"&gt;PBS&lt;/span&gt; supports remote sync to another &lt;span class="caps"&gt;PBS&lt;/span&gt; instance. This is essential for a 3-2-1 backup&amp;nbsp;strategy:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# On the primary PBS, configure a sync job to a remote PBS&lt;/span&gt;
proxmox-backup-manager&lt;span class="w"&gt; &lt;/span&gt;sync-job&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--remote&lt;span class="w"&gt; &lt;/span&gt;pbs-remote.example.com&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--remote-datastore&lt;span class="w"&gt; &lt;/span&gt;remote-store&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--local-datastore&lt;span class="w"&gt; &lt;/span&gt;main-store&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--owner&lt;span class="w"&gt; &lt;/span&gt;root@pam&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--schedule&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;0 4 * * *&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--transfer-last&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This syncs only the last 2 backup snapshots to the remote site, minimizing&amp;nbsp;bandwidth.&lt;/p&gt;
&lt;h2&gt;Pruning and Garbage&amp;nbsp;Collection&lt;/h2&gt;
&lt;p&gt;&lt;span class="caps"&gt;PBS&lt;/span&gt; uses a two-step cleanup&amp;nbsp;process:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pruning:&lt;/strong&gt; Removes old backup snapshots according to retention&amp;nbsp;policy.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;proxmox-backup-manager&lt;span class="w"&gt; &lt;/span&gt;prune-job&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--datastore&lt;span class="w"&gt; &lt;/span&gt;main-store&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--schedule&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;daily&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--keep-last&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--keep-daily&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--keep-weekly&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--keep-monthly&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Garbage Collection:&lt;/strong&gt; Cleans up orphaned chunks from&amp;nbsp;deduplication.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;proxmox-backup-manager&lt;span class="w"&gt; &lt;/span&gt;garbage-collection&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;main-store
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Schedule &lt;span class="caps"&gt;GC&lt;/span&gt; via the &lt;span class="caps"&gt;UI&lt;/span&gt;: &lt;code&gt;Datastore → main-store → Options → Garbage Collection: Daily&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Monitoring and&amp;nbsp;Alerts&lt;/h2&gt;
&lt;p&gt;Track &lt;span class="caps"&gt;PBS&lt;/span&gt; health with the built-in notification&amp;nbsp;system:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Check datastore usage&lt;/span&gt;
proxmox-backup-manager&lt;span class="w"&gt; &lt;/span&gt;datastore&lt;span class="w"&gt; &lt;/span&gt;list

&lt;span class="c1"&gt;# View last verification status&lt;/span&gt;
proxmox-backup-manager&lt;span class="w"&gt; &lt;/span&gt;task&lt;span class="w"&gt; &lt;/span&gt;list

&lt;span class="c1"&gt;# Check systemd status&lt;/span&gt;
systemctl&lt;span class="w"&gt; &lt;/span&gt;status&lt;span class="w"&gt; &lt;/span&gt;proxmox-backup

&lt;span class="c1"&gt;# Monitor backup logs&lt;/span&gt;
journalctl&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="w"&gt; &lt;/span&gt;proxmox-backup&lt;span class="w"&gt; &lt;/span&gt;-f
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Integrate &lt;span class="caps"&gt;PBS&lt;/span&gt; metrics with Grafana by exposing the &lt;span class="caps"&gt;API&lt;/span&gt;&amp;nbsp;(&lt;code&gt;/api2/json/admin/datastore&lt;/code&gt;).&lt;/p&gt;
&lt;h2&gt;Best&amp;nbsp;Practices&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Remote Backups (Offsite):&lt;/strong&gt; Always have a secondary &lt;span class="caps"&gt;PBS&lt;/span&gt; instance at a different&amp;nbsp;location.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Encryption:&lt;/strong&gt; Enable client-side encryption on the &lt;span class="caps"&gt;PVE&lt;/span&gt; side — even if the remote &lt;span class="caps"&gt;PBS&lt;/span&gt; is compromised, your data stays&amp;nbsp;secure.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Verify Backups:&lt;/strong&gt;&amp;nbsp;Configure &lt;code&gt;verify-new&lt;/code&gt; and &lt;code&gt;verify-existing&lt;/code&gt; on your datastore to catch corruption&amp;nbsp;early.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Network Isolation:&lt;/strong&gt; Run &lt;span class="caps"&gt;PBS&lt;/span&gt; in a separate &lt;span class="caps"&gt;VLAN&lt;/span&gt; or subnet. Use WireGuard/Tailscale for remote access — never expose &lt;span class="caps"&gt;PBS&lt;/span&gt; directly to the&amp;nbsp;internet.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Test Restores:&lt;/strong&gt; Schedule a quarterly restore test. A backup you&amp;#8217;ve never restored is not a&amp;nbsp;backup.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Monitor Deduplication Ratio:&lt;/strong&gt; A ratio below 2:1 may indicate the datastore isn&amp;#8217;t deduplicating effectively — check your &lt;span class="caps"&gt;VM&lt;/span&gt;&amp;nbsp;configurations.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Troubleshooting&lt;/h2&gt;
&lt;h3&gt;Backup fails with &amp;#8220;connection&amp;nbsp;refused&amp;#8221;&lt;/h3&gt;
&lt;p&gt;Check that the &lt;span class="caps"&gt;PBS&lt;/span&gt; service is&amp;nbsp;running: &lt;code&gt;systemctl status proxmox-backup&lt;/code&gt; and that port 8007 is&amp;nbsp;accessible: &lt;code&gt;telnet pbs-ip 8007&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Backups are full (not&amp;nbsp;incremental)&lt;/h3&gt;
&lt;p&gt;Ensure the &lt;span class="caps"&gt;VM&lt;/span&gt; has been backed up at least once. &lt;span class="caps"&gt;PBS&lt;/span&gt; is forever-incremental — every backup after the first is a delta. If backups run sequentially on different VMs, each &lt;span class="caps"&gt;VM&lt;/span&gt; independently gets incremental after its first&amp;nbsp;full.&lt;/p&gt;
&lt;h3&gt;Fingerprint&amp;nbsp;mismatch&lt;/h3&gt;
&lt;p&gt;Regenerate and copy the&amp;nbsp;fingerprint:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# On PBS&lt;/span&gt;
openssl&lt;span class="w"&gt; &lt;/span&gt;x509&lt;span class="w"&gt; &lt;/span&gt;-fingerprint&lt;span class="w"&gt; &lt;/span&gt;-sha256&lt;span class="w"&gt; &lt;/span&gt;-noout&lt;span class="w"&gt; &lt;/span&gt;-in&lt;span class="w"&gt; &lt;/span&gt;/etc/proxmox-backup/proxy.pem
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Setting up Proxmox Backup Server is the single most impactful project you can undertake for your homelab. It moves your infrastructure from &amp;#8220;experimental&amp;#8221; to &amp;#8220;reliable production&amp;#8221; status. By leveraging deduplication, encryption, and native &lt;span class="caps"&gt;PVE&lt;/span&gt; integration, you ensure that even the worst data loss scenarios are easily reversible in minutes, not&amp;nbsp;hours.&lt;/p&gt;
&lt;p&gt;Start your &lt;span class="caps"&gt;PBS&lt;/span&gt; journey today, verify your backups (not just schedule them), and enjoy the peace of mind that comes with a professional-grade recovery&amp;nbsp;pipeline.&lt;/p&gt;</content><category term="Proxmox"/><category term="proxmox"/><category term="backup"/><category term="homelab"/><category term="disaster-recovery"/><category term="2026"/></entry><entry><title>The Ultimate Self-Hosted Google Drive Alternative: Nextcloud vs Seafile vs Syncthing</title><link href="https://steadypub.com/2026/06/self-hosted-google-drive-alternatives/" rel="alternate"/><published>2026-06-08T00:00:00+07:00</published><updated>2026-06-08T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-08:/2026/06/self-hosted-google-drive-alternatives/</id><summary type="html">&lt;p&gt;In an era where privacy is increasingly under threat and SaaS subscription costs continue to rise, taking control of your data has never been more important. For many, Google Drive, Dropbox, and OneDrive are convenient, but they come at the cost of your privacy and a monthly&amp;nbsp;fee.&lt;/p&gt;
&lt;p&gt;If you …&lt;/p&gt;</summary><content type="html">&lt;p&gt;In an era where privacy is increasingly under threat and SaaS subscription costs continue to rise, taking control of your data has never been more important. For many, Google Drive, Dropbox, and OneDrive are convenient, but they come at the cost of your privacy and a monthly&amp;nbsp;fee.&lt;/p&gt;
&lt;p&gt;If you have a home server or a &lt;span class="caps"&gt;VPS&lt;/span&gt;, you can host your own file synchronization and storage solution. But with so many options available, which one should you choose? Today, we will dive deep into the three most popular self-hosted alternatives to Google Drive: &lt;strong&gt;Nextcloud&lt;/strong&gt;, &lt;strong&gt;Seafile&lt;/strong&gt;, and &lt;strong&gt;Syncthing&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;Why Self-Host Your File&amp;nbsp;Storage?&lt;/h2&gt;
&lt;p&gt;Before we jump into the comparisons, let’s talk about why you would want to do this in the first&amp;nbsp;place:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Data Sovereignty:&lt;/strong&gt; You are the sole owner of your files. No tech giant can scan your documents for ads or hand them over to third parties without your&amp;nbsp;knowledge.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cost Efficiency:&lt;/strong&gt; While there is an initial cost (server hardware or &lt;span class="caps"&gt;VPS&lt;/span&gt; rent), you don&amp;#8217;t pay a monthly subscription fee for storage capacity. If you have a terabyte of photos, you don&amp;#8217;t need a $10/month plan; you just need a bigger hard&amp;nbsp;drive.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Unlimited Speed:&lt;/strong&gt; On your local network, file transfers can happen at the speed of your &lt;span class="caps"&gt;LAN&lt;/span&gt;—usually Gigabit or 10-Gigabit—making it much faster than downloading from a cloud&amp;nbsp;provider.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;1. Nextcloud: The &amp;#8220;Everything&amp;#8221;&amp;nbsp;Solution&lt;/h2&gt;
&lt;p&gt;Nextcloud is the heavyweight champion of the self-hosting world. It’s not just a file sync solution; it’s a full-blown productivity&amp;nbsp;suite.&lt;/p&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Feature Set:&lt;/strong&gt; Beyond file sync, you get calendars, contacts, Kanban boards, chat, video calling, and an app store with hundreds of&amp;nbsp;plugins.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;User Interface:&lt;/strong&gt; It features one of the most polished web interfaces in the open-source&amp;nbsp;community.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ecosystem:&lt;/strong&gt; There is a mobile app for almost every platform and deep integration with desktop operating&amp;nbsp;systems.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Resource Heavy:&lt;/strong&gt; Nextcloud requires significantly more &lt;span class="caps"&gt;RAM&lt;/span&gt; and &lt;span class="caps"&gt;CPU&lt;/span&gt; to run efficiently compared to the other&amp;nbsp;options.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Complexity:&lt;/strong&gt; Maintenance can be daunting. Updates occasionally break things if not managed&amp;nbsp;properly.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;p&gt;People who want a true &amp;#8220;Google Suite&amp;#8221; replacement. If you want calendars, contacts, and collaborative document editing in one place, Nextcloud is the&amp;nbsp;winner.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;2. Seafile: The Performance&amp;nbsp;King&lt;/h2&gt;
&lt;p&gt;If your primary goal is syncing files reliably and quickly, Seafile is hard to beat. It is engineered for&amp;nbsp;performance.&lt;/p&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Speed:&lt;/strong&gt; Seafile uses a unique file-chunking system that makes it incredibly fast, especially when syncing thousands of small&amp;nbsp;files.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reliability:&lt;/strong&gt; It is remarkably stable. It rarely crashes and handles conflicts much better than&amp;nbsp;Nextcloud.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Low Overhead:&lt;/strong&gt; It is much lighter on system resources than&amp;nbsp;Nextcloud.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Limited Features:&lt;/strong&gt; It’s a file storage solution. You don’t get integrated calendars or office document&amp;nbsp;editing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;UI&lt;/span&gt;:&lt;/strong&gt; The interface is functional, but lacks the &amp;#8220;modern&amp;#8221; feel of&amp;nbsp;Nextcloud.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;p&gt;Users who value speed and reliability above all else. If you are a developer syncing codebases or a professional with huge file directories, Seafile is the superior&amp;nbsp;choice.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;3. Syncthing: The Decentralized&amp;nbsp;Powerhouse&lt;/h2&gt;
&lt;p&gt;Syncthing is different. It doesn&amp;#8217;t rely on a central server. It is a continuous decentralized file synchronization&amp;nbsp;tool.&lt;/p&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No Central Server:&lt;/strong&gt; Files are synced directly between your devices (e.g., &lt;span class="caps"&gt;PC&lt;/span&gt; to Laptop to &lt;span class="caps"&gt;NAS&lt;/span&gt;). There is no &amp;#8220;master&amp;#8221; server&amp;nbsp;required.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security:&lt;/strong&gt; Everything is encrypted in transit and at&amp;nbsp;rest.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zero Config:&lt;/strong&gt; Once set up, it just works in the background without needing a web&amp;nbsp;interface.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No Web Portal:&lt;/strong&gt; You don&amp;#8217;t &amp;#8220;log in&amp;#8221; to your server to see your files. If your &lt;span class="caps"&gt;PC&lt;/span&gt; is off, you can&amp;#8217;t sync from&amp;nbsp;it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Advanced Networking:&lt;/strong&gt; Since it relies on &lt;span class="caps"&gt;P2P&lt;/span&gt;, you might need to handle port forwarding or firewall settings if devices are on different&amp;nbsp;networks.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;p&gt;People who want simple, direct file syncing between their own devices without hosting a &amp;#8220;service&amp;#8221; on a dedicated&amp;nbsp;server.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Comparison&amp;nbsp;Table&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: left;"&gt;Feature&lt;/th&gt;
&lt;th style="text-align: left;"&gt;Nextcloud&lt;/th&gt;
&lt;th style="text-align: left;"&gt;Seafile&lt;/th&gt;
&lt;th style="text-align: left;"&gt;Syncthing&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;&lt;strong&gt;Type&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Suite / Platform&lt;/td&gt;
&lt;td style="text-align: left;"&gt;File Sync&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;span class="caps"&gt;P2P&lt;/span&gt; Sync&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;&lt;strong&gt;Resources&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;High&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Low-Medium&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Very Low&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;&lt;strong&gt;Speed&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Moderate&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Very High&lt;/td&gt;
&lt;td style="text-align: left;"&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;&lt;strong&gt;Remote Access&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Web-based&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Web-based&lt;/td&gt;
&lt;td style="text-align: left;"&gt;&lt;span class="caps"&gt;P2P&lt;/span&gt; / Direct&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;&lt;strong&gt;Extra Features&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Calendar, Contacts, etc&lt;/td&gt;
&lt;td style="text-align: left;"&gt;File versioning&lt;/td&gt;
&lt;td style="text-align: left;"&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion: Which Should You&amp;nbsp;Choose?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Choose Nextcloud&lt;/strong&gt; if you are looking for a comprehensive replacement for Google Workspace or Microsoft&amp;nbsp;365.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Choose Seafile&lt;/strong&gt; if you have heavy file sync needs and want a fast, stable, and server-based&amp;nbsp;solution.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Choose Syncthing&lt;/strong&gt; if you just want to keep folders in sync between your laptop, desktop, and phone without the overhead of maintaining a dedicated&amp;nbsp;server.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ready to start your homelab journey? Check out my guide on &lt;strong&gt;&lt;a href="/homelab-mini-pcs"&gt;Best Mini &lt;span class="caps"&gt;PC&lt;/span&gt; for Homelab in 2025&lt;/a&gt;&lt;/strong&gt; to get the hardware you need to start hosting your own data&amp;nbsp;today.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Disclaimer: Some of the links in this article are affiliate links, which means I may earn a commission if you make a purchase at no extra cost to&amp;nbsp;you.&lt;/em&gt;&lt;/p&gt;</content><category term="Self-Hosting"/><category term="nextcloud"/><category term="seafile"/><category term="syncthing"/><category term="file-sync"/><category term="self-hosted"/><category term="homelab"/></entry><entry><title>Setting Up Your First Proxmox Node: A Practical Guide</title><link href="https://steadypub.com/2026/06/setting-up-proxmox-node/" rel="alternate"/><published>2026-06-08T00:00:00+07:00</published><updated>2026-06-08T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-08:/2026/06/setting-up-proxmox-node/</id><summary type="html">&lt;p&gt;A step-by-step guide to installing and configuring your first Proxmox Virtual Environment (&lt;span class="caps"&gt;PVE&lt;/span&gt;) node. From &lt;span class="caps"&gt;ISO&lt;/span&gt; burning to initial networking and storage setup, learn how to start your virtualization journey safely and&amp;nbsp;efficiently.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Virtualization is the heart of a modern homelab. It allows you to run dozens of services on a single physical machine, turning one server into an entire infrastructure. Proxmox Virtual Environment (&lt;span class="caps"&gt;PVE&lt;/span&gt;) is the industry-standard, open-source platform for this, combining &lt;span class="caps"&gt;KVM&lt;/span&gt;-based virtual machines with lightweight &lt;span class="caps"&gt;LXC&lt;/span&gt;&amp;nbsp;containers.&lt;/p&gt;
&lt;p&gt;This guide covers the journey from bare metal to a fully functional virtualization host with working networking, storage, and firewall&amp;nbsp;configuration.&lt;/p&gt;
&lt;h2&gt;Why&amp;nbsp;Proxmox?&lt;/h2&gt;
&lt;p&gt;Proxmox is built on Debian, which means it is incredibly stable. It offers:
- &lt;strong&gt;Unified Management:&lt;/strong&gt; One dashboard for VMs, containers, backups, and storage.
- &lt;strong&gt;&lt;span class="caps"&gt;KVM&lt;/span&gt; &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; &lt;span class="caps"&gt;LXC&lt;/span&gt;:&lt;/strong&gt; Choose full virtualization (VMs) for &lt;span class="caps"&gt;OS&lt;/span&gt; independence or containerization (&lt;span class="caps"&gt;LXC&lt;/span&gt;) for extreme performance.
- &lt;strong&gt;Built-in Backups:&lt;/strong&gt; Snapshot and backup scheduling without third-party tools.
- &lt;strong&gt;High Availability:&lt;/strong&gt; Easily expand to a cluster as your lab grows.
- &lt;strong&gt;&lt;span class="caps"&gt;ZFS&lt;/span&gt; Support:&lt;/strong&gt; Integrated &lt;span class="caps"&gt;ZFS&lt;/span&gt; for data integrity, compression, and&amp;nbsp;snapshots.&lt;/p&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;p&gt;Before starting, ensure you have:
1. &lt;strong&gt;Hardware:&lt;/strong&gt; A &lt;span class="caps"&gt;PC&lt;/span&gt; or server with at least &lt;span class="caps"&gt;8GB&lt;/span&gt; of &lt;span class="caps"&gt;RAM&lt;/span&gt; and an Intel/&lt;span class="caps"&gt;AMD&lt;/span&gt; &lt;span class="caps"&gt;CPU&lt;/span&gt; supporting virtualization (&lt;span class="caps"&gt;VT&lt;/span&gt;-x or &lt;span class="caps"&gt;AMD&lt;/span&gt;-V).
2. &lt;strong&gt;Connectivity:&lt;/strong&gt; Ethernet cable connected to your main switch.
3. &lt;strong&gt;&lt;span class="caps"&gt;USB&lt;/span&gt; Drive:&lt;/strong&gt; At least &lt;span class="caps"&gt;8GB&lt;/span&gt; to flash the Proxmox &lt;span class="caps"&gt;ISO&lt;/span&gt;.&lt;/p&gt;
&lt;h2&gt;Step 1: Preparing the &lt;span class="caps"&gt;ISO&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;Download the latest Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; &lt;span class="caps"&gt;ISO&lt;/span&gt; from the &lt;a href="https://www.proxmox.com/en/downloads"&gt;official download page&lt;/a&gt;.&amp;nbsp;Use &lt;code&gt;dd&lt;/code&gt; on Linux or a graphical tool like BalenaEtcher on Windows/macOS to write the &lt;span class="caps"&gt;ISO&lt;/span&gt; to your &lt;span class="caps"&gt;USB&lt;/span&gt;&amp;nbsp;drive:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Linux: Find your USB device first&lt;/span&gt;
lsblk
&lt;span class="c1"&gt;# Write the ISO (replace /dev/sdX with your USB device)&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;dd&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;proxmox-ve_*.iso&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/sdX&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4M&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;progress
sync
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Step 2: The Installation&amp;nbsp;Process&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Boot:&lt;/strong&gt; Insert the &lt;span class="caps"&gt;USB&lt;/span&gt; into the target machine and boot from it via &lt;span class="caps"&gt;BIOS&lt;/span&gt;/&lt;span class="caps"&gt;UEFI&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Select &amp;#8220;Install Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;&amp;#8221;&lt;/strong&gt; from the boot&amp;nbsp;menu.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Target Disk:&lt;/strong&gt; Choose the disk for Proxmox. &lt;strong&gt;Warning:&lt;/strong&gt; This wipes all data on the target&amp;nbsp;disk.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Location &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; Time:&lt;/strong&gt; Set your timezone and keyboard&amp;nbsp;layout.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Admin Password:&lt;/strong&gt; Set a&amp;nbsp;strong &lt;code&gt;root&lt;/code&gt; password (use a password&amp;nbsp;manager).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Email:&lt;/strong&gt; Enter a valid email for system&amp;nbsp;notifications.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Management Network:&lt;/strong&gt; Configure your primary&amp;nbsp;interface:&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hostname:&lt;/strong&gt;&amp;nbsp;Use &lt;code&gt;pve01.yourdomain.local&lt;/code&gt; (&lt;span class="caps"&gt;FQDN&lt;/span&gt; format&amp;nbsp;required)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;IP&lt;/span&gt; Address:&lt;/strong&gt; Choose a static &lt;span class="caps"&gt;IP&lt;/span&gt; within your &lt;span class="caps"&gt;LAN&lt;/span&gt; range&amp;nbsp;(e.g., &lt;code&gt;192.168.1.10/24&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Gateway:&lt;/strong&gt; Your router&amp;#8217;s &lt;span class="caps"&gt;IP&lt;/span&gt;&amp;nbsp;(e.g., &lt;code&gt;192.168.1.1&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt;:&lt;/strong&gt; &lt;code&gt;1.1.1.1, 8.8.8.8&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Once installed, the system will reboot. Access the management &lt;span class="caps"&gt;UI&lt;/span&gt;&amp;nbsp;at &lt;code&gt;https://&amp;lt;YOUR_IP&amp;gt;:8006&lt;/code&gt;. Accept the self-signed certificate warning — you can replace it with a Let&amp;#8217;s Encrypt certificate&amp;nbsp;later.&lt;/p&gt;
&lt;h2&gt;Step 3: Initial Post-Install&amp;nbsp;Tweaks&lt;/h2&gt;
&lt;h3&gt;3.1 Configure&amp;nbsp;Repositories&lt;/h3&gt;
&lt;p&gt;Proxmox includes enterprise repos by default. For homelab use, switch to the no-subscription&amp;nbsp;repository:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Comment out enterprise repo&lt;/span&gt;
sed&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;s/^deb/# deb/&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/apt/sources.list.d/pve-enterprise.list

&lt;span class="c1"&gt;# Add no-subscription repo&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;deb http://download.proxmox.com/debian/pve bookworm pve-no-subscription&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/apt/sources.list

&lt;span class="c1"&gt;# Update&lt;/span&gt;
apt&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;dist-upgrade&lt;span class="w"&gt; &lt;/span&gt;-y
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;3.2 Configure&amp;nbsp;Storage&lt;/h3&gt;
&lt;p&gt;By default, Proxmox uses &lt;span class="caps"&gt;LVM&lt;/span&gt;-thin. For a homelab, &lt;span class="caps"&gt;ZFS&lt;/span&gt; is strongly recommended for data integrity, compression, and&amp;nbsp;snapshots:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Check available disks&lt;/span&gt;
lsblk

&lt;span class="c1"&gt;# Create a ZFS pool with a single disk (replace /dev/sda with your data disk)&lt;/span&gt;
zpool&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ashift&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;tank&lt;span class="w"&gt; &lt;/span&gt;/dev/sda

&lt;span class="c1"&gt;# Enable compression&lt;/span&gt;
zfs&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;compression&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;lz4&lt;span class="w"&gt; &lt;/span&gt;tank

&lt;span class="c1"&gt;# Create a dataset for VM storage&lt;/span&gt;
zfs&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;mountpoint&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/tank/vm&lt;span class="w"&gt; &lt;/span&gt;tank/vm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then in the Proxmox Web &lt;span class="caps"&gt;UI&lt;/span&gt;: &lt;code&gt;Datacenter → Storage → Add → ZFS&lt;/code&gt; and point it to your&amp;nbsp;pool.&lt;/p&gt;
&lt;h3&gt;3.3 Network Bridge&amp;nbsp;Configuration&lt;/h3&gt;
&lt;p&gt;Proxmox uses a Linux bridge&amp;nbsp;(&lt;code&gt;vmbr0&lt;/code&gt;) for &lt;span class="caps"&gt;VM&lt;/span&gt; networking. Verify your bridge&amp;nbsp;configuration:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;cat&lt;span class="w"&gt; &lt;/span&gt;/etc/network/interfaces
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A typical config looks&amp;nbsp;like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;auto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;lo&lt;/span&gt;
&lt;span class="nx"&gt;iface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;lo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;inet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;loopback&lt;/span&gt;

&lt;span class="kt"&gt;auto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;enp1s0&lt;/span&gt;
&lt;span class="nx"&gt;iface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;enp1s0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;inet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;manual&lt;/span&gt;

&lt;span class="kt"&gt;auto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;vmbr0&lt;/span&gt;
&lt;span class="nx"&gt;iface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;vmbr0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;inet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;static&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m m-Double"&gt;192.168.1.10&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;gateway&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m m-Double"&gt;192.168.1.1&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;bridge&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;ports&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;enp1s0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;bridge&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;stp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;off&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;bridge&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;fd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;3.4 Firewall&amp;nbsp;Basics&lt;/h3&gt;
&lt;p&gt;Enable the Proxmox firewall at the datacenter&amp;nbsp;level:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Enable firewall on the node&lt;/span&gt;
pve-firewall&lt;span class="w"&gt; &lt;/span&gt;start
systemctl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pve-firewall

&lt;span class="c1"&gt;# Check rules&lt;/span&gt;
pve-firewall&lt;span class="w"&gt; &lt;/span&gt;status
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the Web &lt;span class="caps"&gt;UI&lt;/span&gt;: &lt;code&gt;Datacenter → Firewall → Options → Enable: Yes&lt;/code&gt;. Whitelist your management &lt;span class="caps"&gt;IP&lt;/span&gt;&amp;nbsp;under &lt;code&gt;Datacenter → Firewall → Rules&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;3.5 Remove the Subscription&amp;nbsp;Nag&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Hide the subscription popup in the UI&lt;/span&gt;
sed&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;s/data.status !== &amp;#39;Active&amp;#39;/false/g&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/usr/share/pve-manager/js/pvemanagerlib.js
systemctl&lt;span class="w"&gt; &lt;/span&gt;restart&lt;span class="w"&gt; &lt;/span&gt;pveproxy
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Step 4: Creating Your First&amp;nbsp;Container&lt;/h2&gt;
&lt;p&gt;Before building VMs, &lt;span class="caps"&gt;LXC&lt;/span&gt; containers are lighter and ideal for Docker&amp;nbsp;hosts:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Download a Debian 12 template&lt;/span&gt;
pveam&lt;span class="w"&gt; &lt;/span&gt;update
pveam&lt;span class="w"&gt; &lt;/span&gt;download&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;debian-12-standard_12.7-1_amd64.tar.zst

&lt;span class="c1"&gt;# Create a container (CT 100, 2 cores, 4GB RAM, 20GB disk)&lt;/span&gt;
pct&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;local:vztmpl/debian-12-standard_12.7-1_amd64.tar.zst&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--hostname&lt;span class="w"&gt; &lt;/span&gt;docker-host&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--storage&lt;span class="w"&gt; &lt;/span&gt;local-lvm&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--memory&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4096&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--cores&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--net0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;eth0,bridge&lt;span class="o"&gt;=&lt;/span&gt;vmbr0,ip&lt;span class="o"&gt;=&lt;/span&gt;dhcp&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--rootfs&lt;span class="w"&gt; &lt;/span&gt;local-lvm:20&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--password&lt;span class="w"&gt; &lt;/span&gt;your-secure-password

&lt;span class="c1"&gt;# Start the container&lt;/span&gt;
pct&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;

&lt;span class="c1"&gt;# Attach to its shell&lt;/span&gt;
pct&lt;span class="w"&gt; &lt;/span&gt;enter&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Step 5: Enabling Nested&amp;nbsp;Virtualization&lt;/h2&gt;
&lt;p&gt;To run Docker inside an &lt;span class="caps"&gt;LXC&lt;/span&gt; container (or VMs inside a &lt;span class="caps"&gt;VM&lt;/span&gt;), enable&amp;nbsp;nesting:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# For a specific container&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;features: nesting=1&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/pve/lxc/100.conf

&lt;span class="c1"&gt;# Or via command line&lt;/span&gt;
pct&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--features&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;nesting&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;

&lt;span class="c1"&gt;# Restart the container&lt;/span&gt;
pct&lt;span class="w"&gt; &lt;/span&gt;restart&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Troubleshooting&lt;/h2&gt;
&lt;h3&gt;Web &lt;span class="caps"&gt;UI&lt;/span&gt; not&amp;nbsp;loading&lt;/h3&gt;
&lt;p&gt;Check&amp;nbsp;that &lt;code&gt;pveproxy&lt;/code&gt; is&amp;nbsp;running: &lt;code&gt;systemctl status pveproxy&lt;/code&gt;. Restart&amp;nbsp;with &lt;code&gt;systemctl restart pveproxy&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;VMs fail to start with &amp;#8220;&lt;span class="caps"&gt;KVM&lt;/span&gt; acceleration not&amp;nbsp;available&amp;#8221;&lt;/h3&gt;
&lt;p&gt;Ensure virtualization is enabled in &lt;span class="caps"&gt;BIOS&lt;/span&gt;. Check&amp;nbsp;with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;egrep&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;(vmx|svm)&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/proc/cpuinfo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If it returns 0, reboot into &lt;span class="caps"&gt;BIOS&lt;/span&gt; and enable Intel &lt;span class="caps"&gt;VT&lt;/span&gt;-x or &lt;span class="caps"&gt;AMD&lt;/span&gt; &lt;span class="caps"&gt;SVM&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;No network in&amp;nbsp;container&lt;/h3&gt;
&lt;p&gt;Ensure the bridge is configured correctly and &lt;span class="caps"&gt;STP&lt;/span&gt; is&amp;nbsp;disabled:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;bridge&lt;span class="w"&gt; &lt;/span&gt;link&lt;span class="w"&gt; &lt;/span&gt;show
brctl&lt;span class="w"&gt; &lt;/span&gt;show&lt;span class="w"&gt; &lt;/span&gt;vmbr0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;You now have a fully functional Proxmox node with &lt;span class="caps"&gt;ZFS&lt;/span&gt; storage, firewall protection, and a running &lt;span class="caps"&gt;LXC&lt;/span&gt; container. The next logical steps are:
1. Deploy Docker inside your &lt;span class="caps"&gt;LXC&lt;/span&gt; container
2. Set up a reverse proxy (like Nginx Proxy Manager)
3. Configure automated backups to a Proxmox Backup&amp;nbsp;Server&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Remember: always set up automated backups for your VMs&amp;nbsp;in &lt;code&gt;Datacenter → Backup&lt;/code&gt; before running production&amp;nbsp;workloads.&lt;/em&gt;&lt;/p&gt;</content><category term="Proxmox"/><category term="proxmox"/><category term="homelab"/><category term="virtualization"/><category term="linux"/><category term="self-hosted"/></entry><entry><title>Self-Hosted Backup Strategy for Homelab 2026: The Complete 3-2-1 Guide with Restic, Kopia &amp; Duplicati</title><link href="https://steadypub.com/2026/06/self-hosted-backup-strategy-homelab-2026/" rel="alternate"/><published>2026-06-07T00:00:00+07:00</published><updated>2026-06-07T00:00:00+07:00</updated><author><name>WordForge Team</name></author><id>tag:steadypub.com,2026-06-07:/2026/06/self-hosted-backup-strategy-homelab-2026/</id><summary type="html">&lt;p&gt;Build a bulletproof homelab backup strategy in 2026. Learn the 3-2-1 rule, compare Restic vs Kopia vs Duplicati with a full decision matrix, and deploy automated Docker Compose backups to &lt;span class="caps"&gt;NAS&lt;/span&gt;, S3, and offsite storage. Includes Proxmox Backup Server setup, disaster recovery scenarios, and cost stacks from $0 to&amp;nbsp;$50/month.&lt;/p&gt;</summary><content type="html">&lt;hr&gt;
&lt;h1&gt;Self-Hosted Backup Strategy for Homelab 2026: The Complete 3-2-1 Guide with Restic, Kopia &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;Duplicati&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~18 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab owners who have never tested a restore — and everyone who has data they cannot afford to&amp;nbsp;lose&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Introduction: The Most Common Homelab&amp;nbsp;Regret&lt;/h2&gt;
&lt;p&gt;Go to any r/homelab or r/selfhosted thread titled &amp;#8220;What do you wish you had done sooner?&amp;#8221; and the top-voted answer is always the same: &lt;strong&gt;backups&lt;/strong&gt;. Not &lt;span class="caps"&gt;VLAN&lt;/span&gt; segmentation. Not Kubernetes. Not 10 GbE networking.&amp;nbsp;Backups.&lt;/p&gt;
&lt;p&gt;The pattern is painfully consistent. A self-hoster spends months building a beautiful homelab — Proxmox hypervisor, Docker Compose stacks for Nextcloud, Jellyfin, Home Assistant, Pi-hole, Vaultwarden. Everything hums. Then one morning the boot &lt;span class="caps"&gt;SSD&lt;/span&gt; fails. Or a bad Docker volume mount overwrites a database. Or ransomware encrypts the media share. And there is no backup. Months of configuration, family photos, and carefully curated media libraries —&amp;nbsp;gone.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The goal of this guide is simple:&lt;/strong&gt; make sure that is never you. By the end, you will have a production-ready 3-2-1 backup strategy running in Docker Compose, covering your Docker volumes, Proxmox VMs, databases, and configuration files — with automated scheduling, encrypted offsite copies, and actual restore&amp;nbsp;testing.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Already running Proxmox?&lt;/strong&gt; See our &lt;a href="/2026/06/proxmox-beginner-guide/"&gt;Proxmox Beginner Guide&lt;/a&gt; if you need to set up your hypervisor first. New to Docker? Start with &lt;a href="/2026/06/nginx-proxy-manager-docker-compose/"&gt;Nginx Proxy Manager Docker Compose&lt;/a&gt; for the compose&amp;nbsp;fundamentals.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;Why Every Homelab Needs a Backup Strategy (Now, Not&amp;nbsp;Later)&lt;/h2&gt;
&lt;p&gt;Before we talk tools, let us talk about what failure actually looks like in a&amp;nbsp;homelab:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Failure Scenario&lt;/th&gt;
&lt;th&gt;What You Lose&lt;/th&gt;
&lt;th&gt;Recovery Without Backup&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Boot &lt;span class="caps"&gt;SSD&lt;/span&gt; corruption&lt;/td&gt;
&lt;td&gt;All &lt;span class="caps"&gt;VM&lt;/span&gt; configs, Docker volumes, &lt;span class="caps"&gt;OS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Rebuild from scratch (days to weeks)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RAID&lt;/span&gt; controller failure&lt;/td&gt;
&lt;td&gt;Media library, documents&lt;/td&gt;
&lt;td&gt;Re-rip/re-download (months)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Accidental &lt;code&gt;rm -rf /mnt/data&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Everything on that mount&lt;/td&gt;
&lt;td&gt;Zero — it is gone&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ransomware encrypts &lt;span class="caps"&gt;NFS&lt;/span&gt; share&lt;/td&gt;
&lt;td&gt;All files accessible to compromised container&lt;/td&gt;
&lt;td&gt;Pay ransom or lose everything&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Failed Docker update destroys volume&lt;/td&gt;
&lt;td&gt;Application data, databases&lt;/td&gt;
&lt;td&gt;Rebuild app, lose all state&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Proxmox node hardware failure&lt;/td&gt;
&lt;td&gt;All VMs on that node&lt;/td&gt;
&lt;td&gt;Rebuild every &lt;span class="caps"&gt;VM&lt;/span&gt; manually&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The common thread: &lt;strong&gt;without backups, every one of these scenarios requires a full rebuild&lt;/strong&gt;. With a proper 3-2-1 backup strategy, recovery takes hours — not&amp;nbsp;weeks.&lt;/p&gt;
&lt;h3&gt;The Hidden Cost of &lt;span class="caps"&gt;NOT&lt;/span&gt; Backing&amp;nbsp;Up&lt;/h3&gt;
&lt;p&gt;It is easy to think &amp;#8220;I don&amp;#8217;t have anything worth backing up — I can re-download my media and rebuild my configs.&amp;#8221; Let us quantify&amp;nbsp;that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Configuration files:&lt;/strong&gt; A typical homelab has 20–40 Docker Compose files, each with environment variables, volume mounts, and network configurations tested over weeks. Rebuilding them from scratch takes 10–20&amp;nbsp;hours.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Databases:&lt;/strong&gt; Your Nextcloud database contains file metadata, shares, calendars, and contacts. Your Vaultwarden database holds every password. Rebuilding without a backup means starting&amp;nbsp;over.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Media libraries:&lt;/strong&gt; Even if you can re-download, a 4 &lt;span class="caps"&gt;TB&lt;/span&gt; media library takes weeks on a typical residential connection. And many items may no longer be&amp;nbsp;available.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Family photos and documents:&lt;/strong&gt; These are irreplaceable. A backup is the only insurance&amp;nbsp;policy.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Understanding the 3-2-1 Backup Rule for&amp;nbsp;Homelabs&lt;/h2&gt;
&lt;p&gt;The 3-2-1 rule is the gold standard of backup strategy, and it is deceptively&amp;nbsp;simple:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: center;"&gt;Layer&lt;/th&gt;
&lt;th&gt;Rule&lt;/th&gt;
&lt;th&gt;What It Means for Your Homelab&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: center;"&gt;&lt;strong&gt;3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Three copies of your data&lt;/td&gt;
&lt;td&gt;Primary data + local backup + offsite backup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center;"&gt;&lt;strong&gt;2&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Two different storage media&lt;/td&gt;
&lt;td&gt;Don&amp;#8217;t put both backups on the same &lt;span class="caps"&gt;NAS&lt;/span&gt; or same disk type&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center;"&gt;&lt;strong&gt;1&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;One offsite copy&lt;/td&gt;
&lt;td&gt;Geographically separate — cloud, &lt;span class="caps"&gt;VPS&lt;/span&gt;, or a friend&amp;#8217;s house&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Why Each Layer&amp;nbsp;Matters&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Three copies&lt;/strong&gt; protects against single-point-of-failure. If your primary data lives on one server and your backup lives on another — and both are the only copies — a fire or flood that takes both eliminates your data forever. Three copies gives you a&amp;nbsp;buffer.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Two different media&lt;/strong&gt; protects against correlated failures. If your primary data and backup both live on the same &lt;span class="caps"&gt;NAS&lt;/span&gt; with the same &lt;span class="caps"&gt;RAID&lt;/span&gt; array, a &lt;span class="caps"&gt;RAID&lt;/span&gt; controller failure or filesystem corruption can destroy both simultaneously. Different media means: primary on &lt;span class="caps"&gt;SSD&lt;/span&gt;, backup on &lt;span class="caps"&gt;HDD&lt;/span&gt;; or primary on &lt;span class="caps"&gt;NAS&lt;/span&gt;, backup on external &lt;span class="caps"&gt;USB&lt;/span&gt;&amp;nbsp;drive.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;One offsite copy&lt;/strong&gt; protects against physical disasters. Fire, flood, theft, lightning strike — anything that destroys your physical location. An offsite copy in the cloud, on a &lt;span class="caps"&gt;VPS&lt;/span&gt; in another city, or even at a family member&amp;#8217;s house ensures your data survives a worst-case&amp;nbsp;scenario.&lt;/p&gt;
&lt;h3&gt;Common Mistakes That Break the 3-2-1&amp;nbsp;Rule&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Same-disk &amp;#8220;backup&amp;#8221;:&lt;/strong&gt; Copying files to another folder on the same drive is not a backup. If the drive fails, both copies&amp;nbsp;die.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Live mirroring without versioning:&lt;/strong&gt; A real-time mirror (&lt;span class="caps"&gt;RAID&lt;/span&gt; 1, rsync mirror, &lt;span class="caps"&gt;ZFS&lt;/span&gt; replication) is not a backup — it is redundancy. If ransomware encrypts the primary, it encrypts the mirror too. You need versioned, point-in-time&amp;nbsp;snapshots.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Never testing restores:&lt;/strong&gt; A backup you have never restored is Schrödinger&amp;#8217;s backup — it might work, or it might be a collection of corrupted files. You do not know until you&amp;nbsp;test.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No encryption on offsite copies:&lt;/strong&gt; If your offsite backup lives on a cloud provider or a &lt;span class="caps"&gt;VPS&lt;/span&gt;, and it is not encrypted, anyone with access to that storage can read your data. Always encrypt before it leaves your&amp;nbsp;network.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;What to Back Up in a&amp;nbsp;Homelab&lt;/h2&gt;
&lt;p&gt;Not everything in your homelab needs the same backup frequency or retention. Here is the practical&amp;nbsp;checklist:&lt;/p&gt;
&lt;h3&gt;Backup Priority&amp;nbsp;Checklist&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: center;"&gt;Priority&lt;/th&gt;
&lt;th&gt;Data Type&lt;/th&gt;
&lt;th&gt;Examples&lt;/th&gt;
&lt;th style="text-align: center;"&gt;Frequency&lt;/th&gt;
&lt;th style="text-align: center;"&gt;Retention&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: center;"&gt;🔴 Critical&lt;/td&gt;
&lt;td&gt;Databases, passwords&lt;/td&gt;
&lt;td&gt;Vaultwarden &lt;span class="caps"&gt;DB&lt;/span&gt;, Nextcloud &lt;span class="caps"&gt;DB&lt;/span&gt;, config files&lt;/td&gt;
&lt;td style="text-align: center;"&gt;Daily&lt;/td&gt;
&lt;td style="text-align: center;"&gt;90 days&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center;"&gt;🔴 Critical&lt;/td&gt;
&lt;td&gt;Docker Compose files&lt;/td&gt;
&lt;td&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt;, &lt;code&gt;.env&lt;/code&gt; files&lt;/td&gt;
&lt;td style="text-align: center;"&gt;Daily (git)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;Forever&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center;"&gt;🟡 Important&lt;/td&gt;
&lt;td&gt;Docker volumes&lt;/td&gt;
&lt;td&gt;Nextcloud data, Home Assistant config, Immich uploads&lt;/td&gt;
&lt;td style="text-align: center;"&gt;Daily&lt;/td&gt;
&lt;td style="text-align: center;"&gt;60 days&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center;"&gt;🟡 Important&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;VM&lt;/span&gt; disk images&lt;/td&gt;
&lt;td&gt;Proxmox &lt;span class="caps"&gt;VM&lt;/span&gt; backups (&lt;span class="caps"&gt;PBS&lt;/span&gt;)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;Weekly&lt;/td&gt;
&lt;td style="text-align: center;"&gt;30 days&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center;"&gt;🟢 Nice-to-have&lt;/td&gt;
&lt;td&gt;Media libraries&lt;/td&gt;
&lt;td&gt;Jellyfin/Plex media&lt;/td&gt;
&lt;td style="text-align: center;"&gt;Weekly&lt;/td&gt;
&lt;td style="text-align: center;"&gt;30–60 days&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center;"&gt;🟢 Nice-to-have&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;ISO&lt;/span&gt; images, templates&lt;/td&gt;
&lt;td&gt;Proxmox ISOs, Docker images&lt;/td&gt;
&lt;td style="text-align: center;"&gt;Monthly&lt;/td&gt;
&lt;td style="text-align: center;"&gt;Keep latest&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;What &lt;span class="caps"&gt;NOT&lt;/span&gt; to Back&amp;nbsp;Up&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Docker images:&lt;/strong&gt; These can be re-pulled from registries. Backing them up wastes&amp;nbsp;space.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Transient&amp;nbsp;caches:&lt;/strong&gt; &lt;code&gt;/tmp&lt;/code&gt;, browser caches, thumbnail&amp;nbsp;caches.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Downloadable media:&lt;/strong&gt; If you can re-download it quickly and it is not personal, skip&amp;nbsp;it.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pro tip:&lt;/strong&gt; Store your Docker Compose files in a git repository. Push to Forgejo or GitHub after every change. This gives you infinite version history for free and is your first line of defense against&amp;nbsp;misconfiguration.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;The Big Three Self-Hosted Backup Tools: Restic vs Kopia vs&amp;nbsp;Duplicati&lt;/h2&gt;
&lt;p&gt;The homelab backup tool landscape in 2026 has three clear leaders. Each excels in different scenarios. Here is the objective&amp;nbsp;comparison:&lt;/p&gt;
&lt;h3&gt;Feature Comparison&amp;nbsp;Matrix&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th style="text-align: center;"&gt;Restic&lt;/th&gt;
&lt;th style="text-align: center;"&gt;Kopia&lt;/th&gt;
&lt;th style="text-align: center;"&gt;Duplicati&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;First release&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;2015&lt;/td&gt;
&lt;td style="text-align: center;"&gt;2022&lt;/td&gt;
&lt;td style="text-align: center;"&gt;2014&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Maturity&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;🔵 Very mature&lt;/td&gt;
&lt;td style="text-align: center;"&gt;🟡 Maturing fast&lt;/td&gt;
&lt;td style="text-align: center;"&gt;🔵 Very mature&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Deduplication&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;✅ Excellent (content-defined chunking)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;✅ Excellent (content-defined chunking)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;⚠️ Good (block-level)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Compression&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;✅ &lt;span class="caps"&gt;LZ4&lt;/span&gt;, &lt;span class="caps"&gt;ZSTD&lt;/span&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;✅ &lt;span class="caps"&gt;ZSTD&lt;/span&gt;, S2&lt;/td&gt;
&lt;td style="text-align: center;"&gt;✅ &lt;span class="caps"&gt;ZIP&lt;/span&gt;, 7z&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Encryption&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;✅ &lt;span class="caps"&gt;AES&lt;/span&gt;-256-&lt;span class="caps"&gt;GCM&lt;/span&gt;, ChaCha20-Poly1305&lt;/td&gt;
&lt;td style="text-align: center;"&gt;✅ &lt;span class="caps"&gt;AES&lt;/span&gt;-256-&lt;span class="caps"&gt;GCM&lt;/span&gt;, ChaCha20-Poly1305&lt;/td&gt;
&lt;td style="text-align: center;"&gt;✅ &lt;span class="caps"&gt;AES&lt;/span&gt;-256&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;S3-compatible&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;✅ Native&lt;/td&gt;
&lt;td style="text-align: center;"&gt;✅ Native&lt;/td&gt;
&lt;td style="text-align: center;"&gt;✅ Native&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Web &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;❌ &lt;span class="caps"&gt;CLI&lt;/span&gt; only&lt;/td&gt;
&lt;td style="text-align: center;"&gt;✅ Built-in web &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;✅ Built-in web &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Docker-native&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;✅ Official image&lt;/td&gt;
&lt;td style="text-align: center;"&gt;✅ Official image&lt;/td&gt;
&lt;td style="text-align: center;"&gt;✅ LinuxServer image&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Resource usage&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;🟢 Low (~50 &lt;span class="caps"&gt;MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;🟡 Medium (~200 &lt;span class="caps"&gt;MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;🔴 Higher (~300 &lt;span class="caps"&gt;MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Snapshot browsing&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;span class="caps"&gt;CLI&lt;/span&gt; mount&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;span class="caps"&gt;GUI&lt;/span&gt; file browser&lt;/td&gt;
&lt;td style="text-align: center;"&gt;&lt;span class="caps"&gt;GUI&lt;/span&gt; file browser&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Retention policies&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;✅ Flexible&lt;/td&gt;
&lt;td style="text-align: center;"&gt;✅ Advanced&lt;/td&gt;
&lt;td style="text-align: center;"&gt;✅ Basic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Compression ratio&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;~2:1 typical&lt;/td&gt;
&lt;td style="text-align: center;"&gt;~2:1 typical&lt;/td&gt;
&lt;td style="text-align: center;"&gt;~1.5:1 typical&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Repository repair&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;✅ &lt;code&gt;restic repair&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;✅ Built-in maintenance&lt;/td&gt;
&lt;td style="text-align: center;"&gt;⚠️ Recreate database&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Learning curve&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;🔴 Steep (&lt;span class="caps"&gt;CLI&lt;/span&gt;)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;🟡 Moderate (&lt;span class="caps"&gt;GUI&lt;/span&gt;)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;🟢 Easy (&lt;span class="caps"&gt;GUI&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Restic — The Command-Line&amp;nbsp;Powerhouse&lt;/h3&gt;
&lt;p&gt;Restic is the tool of choice for technical users who want maximum control, efficiency, and reliability. It is written in Go, uses content-defined chunking for excellent deduplication, and supports virtually every storage&amp;nbsp;backend.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Technical users comfortable with &lt;span class="caps"&gt;CLI&lt;/span&gt;, automation via cron, S3/B2 offsite backups, large datasets where deduplication&amp;nbsp;matters.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Docker Compose snippet&lt;/strong&gt; (scheduled backup with&amp;nbsp;prune):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# docker-compose.yml — Restic scheduled backup&lt;/span&gt;
&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;
&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;restic-backup&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;restic/restic:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;restic-backup&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;RESTIC_REPOSITORY=s3:s3.amazonaws.com/bucket-name&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;RESTIC_PASSWORD=${RESTIC_PASSWORD}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/opt/docker:/data:ro&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="c1"&gt;# Docker volumes to back up&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/etc/restic:/restic-config&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Exclude files, policy config&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;entrypoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/bin/sh&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-c&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;|&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="no"&gt;restic backup /data \&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="no"&gt;--exclude-file=/restic-config/excludes.txt \&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="no"&gt;--tag docker-volumes \&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="no"&gt;&amp;amp;&amp;amp; restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 3 --prune \&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="no"&gt;&amp;amp;&amp;amp; restic check&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Kopia — The Modern &lt;span class="caps"&gt;GUI&lt;/span&gt;-Friendly&amp;nbsp;Option&lt;/h3&gt;
&lt;p&gt;Kopia is the newest entrant and has rapidly gained traction because of its polished web &lt;span class="caps"&gt;UI&lt;/span&gt;, advanced snapshot policies, and multi-repository support. If you want a &lt;span class="caps"&gt;GUI&lt;/span&gt; to browse snapshots and restore individual files without remembering &lt;span class="caps"&gt;CLI&lt;/span&gt; flags, Kopia is the&amp;nbsp;answer.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Users who want a web &lt;span class="caps"&gt;UI&lt;/span&gt;, complex retention policies per dataset, graphical snapshot browsing, multi-repo&amp;nbsp;management.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Docker Compose snippet&lt;/strong&gt; (Kopia server mode with web &lt;span class="caps"&gt;UI&lt;/span&gt;):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# docker-compose.yml — Kopia server with web UI&lt;/span&gt;
&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;
&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;kopia&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;kopia/kopia:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;kopia-server&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;kopia&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;KOPIA_PASSWORD=${KOPIA_PASSWORD}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;USER=kopia&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;51515:51515&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./kopia-config:/app/config&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./kopia-cache:/app/cache&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/opt/docker:/data:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/mnt/backup-nas:/backup-local&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;server&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;start&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;--insecure&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;--address=0.0.0.0:51515&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;--server-username=kopia&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;--server-password=${KOPIA_PASSWORD}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Duplicati — The Beginner&amp;#8217;s&amp;nbsp;Choice&lt;/h3&gt;
&lt;p&gt;Duplicati is the easiest to set up: a single Docker container with a web &lt;span class="caps"&gt;UI&lt;/span&gt;, a setup wizard, and support for dozens of backends out of the box. It is the &amp;#8220;install in 5 minutes and forget about it&amp;#8221;&amp;nbsp;option.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Beginners, quick setup, diverse backend support, users who want a familiar &lt;span class="caps"&gt;GUI&lt;/span&gt;&amp;nbsp;wizard.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Docker Compose snippet&lt;/strong&gt; (LinuxServer&amp;nbsp;Duplicati):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# docker-compose.yml — Duplicati with web UI&lt;/span&gt;
&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;
&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;duplicati&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;lscr.io/linuxserver/duplicati:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;duplicati&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;PUID=1000&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;PGID=1000&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TZ=Asia/Jakarta&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;CLI_ARGS=&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./duplicati-config:/config&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/opt/docker:/source:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/mnt/backup-nas:/backup&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8200:8200&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Which one should you choose?&lt;/strong&gt; If you are comfortable with &lt;span class="caps"&gt;CLI&lt;/span&gt;, pick Restic. If you want a &lt;span class="caps"&gt;GUI&lt;/span&gt; without sacrificing performance, pick Kopia. If you are new and want the easiest path, start with Duplicati and consider migrating to Restic or Kopia as your needs&amp;nbsp;grow.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;Building Your 3-2-1 Homelab Backup&amp;nbsp;Stack&lt;/h2&gt;
&lt;p&gt;Now let us assemble the complete stack, layer by&amp;nbsp;layer.&lt;/p&gt;
&lt;h3&gt;Layer 1 — Primary Data (Your Production&amp;nbsp;Environment)&lt;/h3&gt;
&lt;p&gt;This is where your data lives:
- &lt;strong&gt;Docker&amp;nbsp;host:&lt;/strong&gt; &lt;code&gt;/opt/docker&lt;/code&gt; with all Compose files and volumes
- &lt;strong&gt;Proxmox host:&lt;/strong&gt; &lt;span class="caps"&gt;VM&lt;/span&gt; disk images on local-lvm or &lt;span class="caps"&gt;ZFS&lt;/span&gt;
- &lt;strong&gt;&lt;span class="caps"&gt;NAS&lt;/span&gt;:&lt;/strong&gt; Media library, document shares, &lt;span class="caps"&gt;ISO&lt;/span&gt;&amp;nbsp;storage&lt;/p&gt;
&lt;h3&gt;Layer 2 — Local Backup (On-Site, Different&amp;nbsp;Media)&lt;/h3&gt;
&lt;p&gt;Your first backup copy should live on different physical&amp;nbsp;hardware:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th style="text-align: center;"&gt;Cost&lt;/th&gt;
&lt;th style="text-align: center;"&gt;Capacity&lt;/th&gt;
&lt;th style="text-align: center;"&gt;Complexity&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;External &lt;span class="caps"&gt;USB&lt;/span&gt; &lt;span class="caps"&gt;HDD&lt;/span&gt; (8–20 &lt;span class="caps"&gt;TB&lt;/span&gt;)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;$150–$400&lt;/td&gt;
&lt;td style="text-align: center;"&gt;High&lt;/td&gt;
&lt;td style="text-align: center;"&gt;Low&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dedicated backup &lt;span class="caps"&gt;NAS&lt;/span&gt; (used)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;$200–$500&lt;/td&gt;
&lt;td style="text-align: center;"&gt;High&lt;/td&gt;
&lt;td style="text-align: center;"&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Proxmox Backup Server (&lt;span class="caps"&gt;PBS&lt;/span&gt;)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;$0 (software) + &lt;span class="caps"&gt;HW&lt;/span&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;Configurable&lt;/td&gt;
&lt;td style="text-align: center;"&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Old &lt;span class="caps"&gt;PC&lt;/span&gt; with TrueNAS&lt;/td&gt;
&lt;td style="text-align: center;"&gt;$0–$200&lt;/td&gt;
&lt;td style="text-align: center;"&gt;High&lt;/td&gt;
&lt;td style="text-align: center;"&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Raspberry Pi + &lt;span class="caps"&gt;SATA&lt;/span&gt; &lt;span class="caps"&gt;HAT&lt;/span&gt; + &lt;span class="caps"&gt;HDD&lt;/span&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;$80–$200&lt;/td&gt;
&lt;td style="text-align: center;"&gt;1–8 &lt;span class="caps"&gt;TB&lt;/span&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;NFS&lt;/span&gt; mount for &lt;span class="caps"&gt;NAS&lt;/span&gt; backup target&lt;/strong&gt; (add&amp;nbsp;to &lt;code&gt;/etc/fstab&lt;/code&gt;):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# /etc/fstab — Mount NAS share for backup target&lt;/span&gt;
&lt;span class="m"&gt;192&lt;/span&gt;.168.50.100:/mnt/tank/backups&lt;span class="w"&gt;  &lt;/span&gt;/mnt/backup-nas&lt;span class="w"&gt;  &lt;/span&gt;nfs&lt;span class="w"&gt;  &lt;/span&gt;rw,hard,intr,noatime&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Layer 3 — Offsite Backup (Geographically&amp;nbsp;Separate)&lt;/h3&gt;
&lt;p&gt;Your third copy must be physically separate from your homelab. Here are the best options for self-hosters in&amp;nbsp;2026:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th style="text-align: center;"&gt;Free Tier&lt;/th&gt;
&lt;th style="text-align: center;"&gt;Paid From&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Backblaze B2&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;S3-compatible object storage&lt;/td&gt;
&lt;td style="text-align: center;"&gt;10 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;$6/&lt;span class="caps"&gt;TB&lt;/span&gt;/month&lt;/td&gt;
&lt;td&gt;Restic/Kopia S3 target&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cloudflare R2&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;S3-compatible object storage&lt;/td&gt;
&lt;td style="text-align: center;"&gt;10 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;$0.015/&lt;span class="caps"&gt;GB&lt;/span&gt;/month&lt;/td&gt;
&lt;td&gt;Zero egress fees&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hetzner StorageBox&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;SFTP&lt;/span&gt;/rsync/Borg&lt;/td&gt;
&lt;td style="text-align: center;"&gt;—&lt;/td&gt;
&lt;td style="text-align: center;"&gt;€3.81/month for 1 &lt;span class="caps"&gt;TB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Simple rsync target&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;BuyVM + Slab&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt; + attached storage&lt;/td&gt;
&lt;td style="text-align: center;"&gt;—&lt;/td&gt;
&lt;td style="text-align: center;"&gt;$5/month for 256 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Self-hosted offsite node&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hetzner &lt;span class="caps"&gt;CX22&lt;/span&gt; &lt;span class="caps"&gt;VPS&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt; with 1 &lt;span class="caps"&gt;TB&lt;/span&gt; block storage&lt;/td&gt;
&lt;td style="text-align: center;"&gt;—&lt;/td&gt;
&lt;td style="text-align: center;"&gt;~€6/month&lt;/td&gt;
&lt;td&gt;Self-hosted backup server&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Restic S3 repository configuration&lt;/strong&gt; (Backblaze B2&amp;nbsp;example):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Set up a new Restic repository on Backblaze B2&lt;/span&gt;
&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;RESTIC_REPOSITORY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;s3:s3.us-west-004.backblazeb2.com/homelab-backups&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;RESTIC_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;your-strong-password-here&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;AWS_ACCESS_KEY_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;your-b2-key-id&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;AWS_SECRET_ACCESS_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;your-b2-application-key&amp;quot;&lt;/span&gt;

restic&lt;span class="w"&gt; &lt;/span&gt;init
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Rsync to Hetzner StorageBox&amp;nbsp;script:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c1"&gt;# rsync-backup.sh — Backup docker volumes to Hetzner StorageBox via rsync&lt;/span&gt;
&lt;span class="nv"&gt;STORAGEBOX&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;u123456@u123456.your-storagebox.de&amp;quot;&lt;/span&gt;
&lt;span class="nv"&gt;REMOTE_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/home/backups/docker&amp;quot;&lt;/span&gt;
&lt;span class="nv"&gt;LOCAL_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/opt/docker&amp;quot;&lt;/span&gt;
&lt;span class="nv"&gt;LOG_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/var/log/backup-rsync.log&amp;quot;&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;[&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;date&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;] Starting rsync backup to StorageBox...&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$LOG_FILE&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
rsync&lt;span class="w"&gt; &lt;/span&gt;-avz&lt;span class="w"&gt; &lt;/span&gt;--delete&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;--exclude&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;*.log&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;--exclude&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;cache/&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$LOCAL_PATH&lt;/span&gt;&lt;span class="s2"&gt;/&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$STORAGEBOX&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;$REMOTE_PATH&lt;/span&gt;&lt;span class="s2"&gt;/&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$LOG_FILE&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-eq&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;[&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;date&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;] Backup completed successfully.&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$LOG_FILE&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;[&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;date&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;] Backup failed with exit code &lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$LOG_FILE&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Send notification (ntfy, Discord, email — see monitoring section)&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Proxmox-Specific Backup&amp;nbsp;Strategy&lt;/h2&gt;
&lt;p&gt;If you run Proxmox as your hypervisor, you have two additional backup&amp;nbsp;paths:&lt;/p&gt;
&lt;h3&gt;Proxmox Backup Server (&lt;span class="caps"&gt;PBS&lt;/span&gt;)&lt;/h3&gt;
&lt;p&gt;&lt;span class="caps"&gt;PBS&lt;/span&gt; is a dedicated backup appliance (free, open-source) that provides incremental, deduplicated &lt;span class="caps"&gt;VM&lt;/span&gt; and container backups with a web &lt;span class="caps"&gt;UI&lt;/span&gt;. It is purpose-built for Proxmox and handles dirty-bitmap incremental backups — meaning after the first full backup, subsequent backups only transfer changed&amp;nbsp;blocks.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;PBS&lt;/span&gt; Docker Compose&lt;/strong&gt; (for running &lt;span class="caps"&gt;PBS&lt;/span&gt; as a container on a backup&amp;nbsp;node):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# docker-compose.yml — Proxmox Backup Server&lt;/span&gt;
&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;
&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;pbs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ayufan/proxmox-backup-server:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pbs&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pbs&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;network_mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;host&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;privileged&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./pbs-config:/etc/proxmox-backup&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./pbs-datastore:/backup-datastore&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./pbs-logs:/var/log/proxmox-backup&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;&lt;span class="caps"&gt;VM&lt;/span&gt; Backup Schedule&amp;nbsp;Recommendations&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;span class="caps"&gt;VM&lt;/span&gt; Type&lt;/th&gt;
&lt;th&gt;Backup Method&lt;/th&gt;
&lt;th style="text-align: center;"&gt;Frequency&lt;/th&gt;
&lt;th style="text-align: center;"&gt;Retention&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Critical VMs (firewall, &lt;span class="caps"&gt;DNS&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;PBS&lt;/span&gt; + Restic to offsite&lt;/td&gt;
&lt;td style="text-align: center;"&gt;Daily&lt;/td&gt;
&lt;td style="text-align: center;"&gt;30 days&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Application VMs (Nextcloud, Vaultwarden)&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;PBS&lt;/span&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;Daily&lt;/td&gt;
&lt;td style="text-align: center;"&gt;30 days&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Development VMs&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;PBS&lt;/span&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;Weekly&lt;/td&gt;
&lt;td style="text-align: center;"&gt;14 days&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Media server VMs&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;PBS&lt;/span&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;Weekly&lt;/td&gt;
&lt;td style="text-align: center;"&gt;14 days&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Testing Your Backups (The Step Everyone&amp;nbsp;Skips)&lt;/h2&gt;
&lt;p&gt;A backup you have never restored is not a backup — it is a hope. Every backup tool can produce corrupted output if disk errors, memory faults, or software bugs&amp;nbsp;intervene.&lt;/p&gt;
&lt;h3&gt;The Quarterly Backup Fire&amp;nbsp;Drill&lt;/h3&gt;
&lt;p&gt;Once every three months, run this&amp;nbsp;checklist:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Pick a random backup snapshot&lt;/strong&gt; — do not pick the most recent one, pick one from 30 days ago. This tests your retention policies and ensures older snapshots are not silently&amp;nbsp;corrupted.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Restore to a test directory&lt;/strong&gt; — never restore over production&amp;nbsp;data.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Verify file integrity&lt;/strong&gt; — compare checksums with the original if&amp;nbsp;possible.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Start the restored application&lt;/strong&gt; — spin up a Docker container from the restored config and verify it&amp;nbsp;works.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Document the result&lt;/strong&gt; — a simple log entry: &amp;#8220;2026-06-07: restored Nextcloud backup from 2026-05-07. All files verified. Database started&amp;nbsp;successfully.&amp;#8221;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Restic restore test&amp;nbsp;script:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c1"&gt;# test-restore.sh — Restore a random snapshot to /tmp and verify&lt;/span&gt;
&lt;span class="nv"&gt;SNAPSHOT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;restic&lt;span class="w"&gt; &lt;/span&gt;snapshots&lt;span class="w"&gt; &lt;/span&gt;--json&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;jq&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;.[-5].id&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# 5th newest&lt;/span&gt;
&lt;span class="nv"&gt;RESTORE_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/tmp/restic-restore-test-&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;date&lt;span class="w"&gt; &lt;/span&gt;+%Y%m%d&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Testing restore of snapshot: &lt;/span&gt;&lt;span class="nv"&gt;$SNAPSHOT&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$RESTORE_DIR&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
restic&lt;span class="w"&gt; &lt;/span&gt;restore&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$SNAPSHOT&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--target&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$RESTORE_DIR&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-eq&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;✅ Restore successful. Files in: &lt;/span&gt;&lt;span class="nv"&gt;$RESTORE_DIR&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;📊 File count: &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;find&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$RESTORE_DIR&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-type&lt;span class="w"&gt; &lt;/span&gt;f&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;wc&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;📊 Total size: &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;du&lt;span class="w"&gt; &lt;/span&gt;-sh&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$RESTORE_DIR&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cut&lt;span class="w"&gt; &lt;/span&gt;-f1&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;❌ Restore FAILED. Check restic logs immediately.&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Disaster Recovery&amp;nbsp;Scenarios&lt;/h2&gt;
&lt;p&gt;Let us walk through five real disaster scenarios and how your 3-2-1 strategy handles&amp;nbsp;each:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th style="text-align: center;"&gt;&lt;span class="caps"&gt;RTO&lt;/span&gt; (Recovery Time)&lt;/th&gt;
&lt;th style="text-align: center;"&gt;&lt;span class="caps"&gt;RPO&lt;/span&gt; (Data Loss)&lt;/th&gt;
&lt;th&gt;Recovery Path&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary server &lt;span class="caps"&gt;SSD&lt;/span&gt; failure&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;2–4 hours&lt;/td&gt;
&lt;td style="text-align: center;"&gt;0–24 hours&lt;/td&gt;
&lt;td&gt;Restore Docker volumes from local &lt;span class="caps"&gt;NAS&lt;/span&gt; backup. Rebuild &lt;span class="caps"&gt;OS&lt;/span&gt; from Ansible/Terraform.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ransomware encrypts everything&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;4–8 hours&lt;/td&gt;
&lt;td style="text-align: center;"&gt;0–24 hours&lt;/td&gt;
&lt;td&gt;Wipe infected systems. Restore from air-gapped or versioned backup. Offsite copy must be immutable or pull-only.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;NAS&lt;/span&gt; hardware failure&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;1–2 days (if replacing &lt;span class="caps"&gt;HW&lt;/span&gt;)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;0 hours&lt;/td&gt;
&lt;td&gt;All primary data on Docker host unaffected. Restore &lt;span class="caps"&gt;NAS&lt;/span&gt; from offsite backup or &lt;span class="caps"&gt;PBS&lt;/span&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Offsite provider goes down&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;0 hours (no data loss)&lt;/td&gt;
&lt;td style="text-align: center;"&gt;N/A&lt;/td&gt;
&lt;td&gt;Set up new offsite target. Push fresh backup. Meanwhile, local backup still protects you.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Accidental deletion (30 days ago)&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;1–2 hours&lt;/td&gt;
&lt;td style="text-align: center;"&gt;0 (if versioned)&lt;/td&gt;
&lt;td&gt;Browse versioned snapshots. Restore the specific file or directory from before the deletion.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;RTO&lt;/span&gt; (Recovery Time Objective):&lt;/strong&gt; How long it takes to recover. &lt;strong&gt;&lt;span class="caps"&gt;RPO&lt;/span&gt; (Recovery Point Objective):&lt;/strong&gt; How much data you can afford to lose (measured in&amp;nbsp;time).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;Security &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; Encryption Best&amp;nbsp;Practices&lt;/h2&gt;
&lt;p&gt;Backups contain your most sensitive data — passwords, personal documents, family photos. Every backup copy, especially offsite copies, must be&amp;nbsp;encrypted.&lt;/p&gt;
&lt;h3&gt;Encryption&amp;nbsp;Checklist&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Requirement&lt;/th&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;At rest (local)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Encrypt backup target disk&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;LUKS&lt;/span&gt;, &lt;span class="caps"&gt;ZFS&lt;/span&gt; native encryption&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;In transit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Encrypt network traffic&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;TLS&lt;/span&gt; (Restic/Kopia), &lt;span class="caps"&gt;SSH&lt;/span&gt; (rsync), WireGuard/Tailscale&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;At rest (offsite)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Encrypt backup data before it leaves&lt;/td&gt;
&lt;td&gt;Restic/Kopia built-in encryption&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Key management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Store encryption keys separately from data&lt;/td&gt;
&lt;td&gt;Password manager, offline paper backup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Key backup&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Ensure keys are recoverable&lt;/td&gt;
&lt;td&gt;Printed &lt;span class="caps"&gt;QR&lt;/span&gt; code of encryption key in a safe deposit box or with a trusted person&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Immutable Backups for Ransomware&amp;nbsp;Protection&lt;/h3&gt;
&lt;p&gt;Restic supports append-only repositories when using the &lt;span class="caps"&gt;REST&lt;/span&gt; server backend. Kopia supports object lock with S3-compatible storage. This means even if an attacker compromises your backup server, they cannot delete or modify existing snapshots — they can only add new ones, and only until the lock&amp;nbsp;expires.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Cost Comparison: Building a Backup Stack on a&amp;nbsp;Budget&lt;/h2&gt;
&lt;p&gt;You can build a working 3-2-1 backup strategy at almost any budget&amp;nbsp;level:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: center;"&gt;Tier&lt;/th&gt;
&lt;th style="text-align: center;"&gt;Monthly Cost&lt;/th&gt;
&lt;th&gt;What You Get&lt;/th&gt;
&lt;th style="text-align: center;"&gt;Safety Level&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: center;"&gt;&lt;strong&gt;$0&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;Free&lt;/td&gt;
&lt;td&gt;Local backup to spare &lt;span class="caps"&gt;USB&lt;/span&gt; &lt;span class="caps"&gt;HDD&lt;/span&gt;. Manual offsite rotation to a drive stored at work/family.&lt;/td&gt;
&lt;td style="text-align: center;"&gt;🟡 Low (manual, no automation)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center;"&gt;&lt;strong&gt;$5&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;~$5/month&lt;/td&gt;
&lt;td&gt;Hetzner StorageBox 1 &lt;span class="caps"&gt;TB&lt;/span&gt; + local &lt;span class="caps"&gt;USB&lt;/span&gt; &lt;span class="caps"&gt;HDD&lt;/span&gt;. Automated rsync or Restic.&lt;/td&gt;
&lt;td style="text-align: center;"&gt;🟢 Good for configs + databases&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center;"&gt;&lt;strong&gt;$15&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;~$15/month&lt;/td&gt;
&lt;td&gt;Backblaze B2 2 &lt;span class="caps"&gt;TB&lt;/span&gt; + local backup + &lt;span class="caps"&gt;PBS&lt;/span&gt;. Fully automated 3-2-1.&lt;/td&gt;
&lt;td style="text-align: center;"&gt;🟢 Excellent for most homelabs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center;"&gt;&lt;strong&gt;$50&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;~$50/month&lt;/td&gt;
&lt;td&gt;Dedicated backup &lt;span class="caps"&gt;VPS&lt;/span&gt; + cloud storage + local &lt;span class="caps"&gt;NAS&lt;/span&gt;. Multi-site automated.&lt;/td&gt;
&lt;td style="text-align: center;"&gt;🔵 Enterprise-grade redundancy&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;The sweet spot for most homelabs:&lt;/strong&gt; &lt;strong&gt;$5–$15/month&lt;/strong&gt;. A Hetzner StorageBox (€3.81 for 1 &lt;span class="caps"&gt;TB&lt;/span&gt;) for offsite, a spare &lt;span class="caps"&gt;USB&lt;/span&gt; &lt;span class="caps"&gt;HDD&lt;/span&gt; for local backup, and Restic (free) for automation gives you a fully automated 3-2-1 setup for under&amp;nbsp;$5/month.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Maintenance &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;Monitoring&lt;/h2&gt;
&lt;p&gt;A backup strategy is not &amp;#8220;set and forget.&amp;#8221; It requires monitoring to catch failures before you need a&amp;nbsp;restore.&lt;/p&gt;
&lt;h3&gt;Backup Health Dashboard with Uptime&amp;nbsp;Kuma&lt;/h3&gt;
&lt;p&gt;Monitor each backup job with Uptime Kuma push monitors. If a job does not report in within its expected window, you get an&amp;nbsp;alert:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c1"&gt;# backup-health-check.sh — Run after each backup job&lt;/span&gt;
&lt;span class="nv"&gt;BACKUP_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;docker-restic-daily&amp;quot;&lt;/span&gt;
&lt;span class="nv"&gt;KUMA_PUSH_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;https://uptime.yourdomain.com/api/push/abc123?status=up&amp;amp;msg=OK&amp;quot;&lt;/span&gt;

&lt;span class="c1"&gt;# ... backup commands here ...&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-eq&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$KUMA_PUSH_URL&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;msg=Backup+&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BACKUP_NAME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;+completed+successfully&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;KUMA_PUSH_URL&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;status=down&amp;amp;msg=Backup+&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BACKUP_NAME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;+FAILED&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Full monitoring setup:&lt;/strong&gt; See our &lt;a href="/2026/06/uptime-kuma-docker-compose-homelab-2026/"&gt;Uptime Kuma Docker Compose guide&lt;/a&gt; for the complete deployment and notification&amp;nbsp;configuration.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Monthly Backup Health Check&amp;nbsp;Routine&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;[ ] Review backup logs for errors and&amp;nbsp;warnings&lt;/li&gt;
&lt;li&gt;[ ] Check disk usage trends (are backups growing&amp;nbsp;unexpectedly?)&lt;/li&gt;
&lt;li&gt;[ ] Verify retention policies are pruning old&amp;nbsp;snapshots&lt;/li&gt;
&lt;li&gt;[ ] Run a spot restore test on one random&amp;nbsp;file&lt;/li&gt;
&lt;li&gt;[ ] Verify offsite copy is reachable and up to&amp;nbsp;date&lt;/li&gt;
&lt;li&gt;[ ] Rotate encryption key backup if keys have&amp;nbsp;changed&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Which Backup Tool Should You Choose? Decision&amp;nbsp;Matrix&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Your Profile&lt;/th&gt;
&lt;th style="text-align: center;"&gt;Recommended Tool&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&amp;#8220;I just want it to work — I&amp;#8217;m new&amp;#8221;&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;Duplicati&lt;/td&gt;
&lt;td&gt;Web &lt;span class="caps"&gt;UI&lt;/span&gt; wizard, 5-minute setup, broad backend support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&amp;#8220;I live in the terminal&amp;#8221;&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;Restic&lt;/td&gt;
&lt;td&gt;Fastest, most mature, best S3 support, excellent dedup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&amp;#8220;I want a &lt;span class="caps"&gt;GUI&lt;/span&gt; + power&amp;#8221;&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;Kopia&lt;/td&gt;
&lt;td&gt;Web &lt;span class="caps"&gt;UI&lt;/span&gt; with advanced policies, snapshot browsing, multi-repo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&amp;#8220;I only backup Proxmox VMs&amp;#8221;&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;Proxmox Backup Server&lt;/td&gt;
&lt;td&gt;Purpose-built, dirty-bitmap incremental, web &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&amp;#8220;I need versioned file-level backup with dedup&amp;#8221;&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;Restic or BorgBackup&lt;/td&gt;
&lt;td&gt;Both excellent; Restic has better cloud/S3 support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&amp;#8220;I backup to &lt;span class="caps"&gt;NAS&lt;/span&gt; only, no cloud&amp;#8221;&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;Kopia (server mode)&lt;/td&gt;
&lt;td&gt;Web &lt;span class="caps"&gt;UI&lt;/span&gt;, local repository, snapshot policies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&amp;#8220;I want zero-knowledge cloud backup&amp;#8221;&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: center;"&gt;Restic&lt;/td&gt;
&lt;td&gt;Client-side encryption, all cloud providers supported&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;The Beginner&amp;nbsp;Path&lt;/h3&gt;
&lt;p&gt;Start with &lt;strong&gt;Duplicati&lt;/strong&gt; (easiest setup, web &lt;span class="caps"&gt;UI&lt;/span&gt; wizard). Once you understand backup concepts — snapshots, retention, deduplication — migrate to &lt;strong&gt;Kopia&lt;/strong&gt; or &lt;strong&gt;Restic&lt;/strong&gt; for better performance and&amp;nbsp;reliability.&lt;/p&gt;
&lt;h3&gt;The Power User&amp;nbsp;Path&lt;/h3&gt;
&lt;p&gt;Start with &lt;strong&gt;Restic&lt;/strong&gt; from day one. The &lt;span class="caps"&gt;CLI&lt;/span&gt; learning curve is worth it for the performance, reliability, and flexibility. Use the shell scripts in this guide as&amp;nbsp;templates.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion: Start With &lt;span class="caps"&gt;ONE&lt;/span&gt; Backup&amp;nbsp;Today&lt;/h2&gt;
&lt;p&gt;The most important backup is the one you actually run. Do not let analysis paralysis stop you from taking the first step. Here is a concrete 15-minute action&amp;nbsp;plan:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Right now:&lt;/strong&gt; Copy your Docker Compose files to a git repository and push. This is zero-cost and protects your most valuable configuration data&amp;nbsp;immediately.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Today:&lt;/strong&gt; Plug in a spare external &lt;span class="caps"&gt;HDD&lt;/span&gt; and run a manual restic backup&amp;nbsp;of &lt;code&gt;/opt/docker&lt;/code&gt;. One&amp;nbsp;command: &lt;code&gt;restic init --repo /mnt/backup &amp;amp;&amp;amp; restic backup /opt/docker&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;This week:&lt;/strong&gt; Set up the Docker Compose configuration from this guide (Restic, Kopia, or Duplicati — pick one). Schedule it via cron or the tool&amp;#8217;s built-in&amp;nbsp;scheduler.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;This month:&lt;/strong&gt; Add an offsite target. A Hetzner StorageBox costs €3.81/month and gives you a true 3-2-1&amp;nbsp;strategy.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;This quarter:&lt;/strong&gt; Run your first restore test. Pick a random snapshot and restore it&amp;nbsp;to &lt;code&gt;/tmp&lt;/code&gt;. Verify the files are&amp;nbsp;intact.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Your future self — the one who accidentally deletes the wrong directory, survives a hardware failure, or faces a ransomware attack — will thank&amp;nbsp;you.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;Related&amp;nbsp;Articles&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/2026/06/proxmox-beginner-guide/"&gt;Proxmox Beginner Guide 2026&lt;/a&gt; — Set up your hypervisor the right&amp;nbsp;way&lt;/li&gt;
&lt;li&gt;&lt;a href="/2026/06/best-nas-os-homelab-2026/"&gt;Best &lt;span class="caps"&gt;NAS&lt;/span&gt; &lt;span class="caps"&gt;OS&lt;/span&gt; for Homelab 2026&lt;/a&gt; — Choose the right storage&amp;nbsp;foundation&lt;/li&gt;
&lt;li&gt;&lt;a href="/2026/06/uptime-kuma-docker-compose-homelab-2026/"&gt;Uptime Kuma Docker Compose Setup&lt;/a&gt; — Monitor your backup&amp;nbsp;jobs&lt;/li&gt;
&lt;li&gt;&lt;a href="/2026/06/nextcloud-docker-compose/"&gt;Nextcloud Docker Compose Setup&lt;/a&gt; — Back up your self-hosted&amp;nbsp;cloud&lt;/li&gt;
&lt;li&gt;&lt;a href="/2026/06/cloudflare-tunnel-homelab/"&gt;Cloudflare Tunnel for Homelab&lt;/a&gt; — Securely access backup dashboards&amp;nbsp;remotely&lt;/li&gt;
&lt;li&gt;&lt;a href="/2026/06/cheap-vps-for-self-hosting/"&gt;Cheap &lt;span class="caps"&gt;VPS&lt;/span&gt; for Self-Hosting&lt;/a&gt; — Host an offsite backup node on a&amp;nbsp;budget&lt;/li&gt;
&lt;li&gt;&lt;a href="/2026/06/best-vps-for-homelab/"&gt;Best &lt;span class="caps"&gt;VPS&lt;/span&gt; for Homelab&lt;/a&gt; — Best &lt;span class="caps"&gt;VPS&lt;/span&gt; providers for offsite&amp;nbsp;backups&lt;/li&gt;
&lt;li&gt;&lt;a href="/2026/06/portainer-setup-guide/"&gt;Portainer Setup Guide&lt;/a&gt; — Manage backup containers with&amp;nbsp;Portainer&lt;/li&gt;
&lt;li&gt;&lt;a href="/2026/06/homelab-security-monitoring/"&gt;Homelab Security Monitoring&lt;/a&gt; — Protect backups from&amp;nbsp;ransomware&lt;/li&gt;
&lt;li&gt;&lt;a href="/2026/06/home-assistant-docker-compose-homelab/"&gt;Home Assistant Docker Compose&lt;/a&gt; — Back up your smart home&amp;nbsp;config&lt;/li&gt;
&lt;li&gt;&lt;a href="/2026/06/traefik-vs-nginx-proxy-manager-vs-caddy-homelab-2026/"&gt;Traefik vs &lt;span class="caps"&gt;NPM&lt;/span&gt; vs Caddy&lt;/a&gt; — Reverse proxy for backup web&amp;nbsp;UIs&lt;/li&gt;
&lt;/ul&gt;</content><category term="Guides"/><category term="backup"/><category term="restic"/><category term="kopia"/><category term="duplicati"/><category term="docker"/><category term="docker-compose"/><category term="homelab"/><category term="self-hosted"/><category term="disaster-recovery"/><category term="3-2-1-rule"/><category term="nas"/><category term="proxmox"/><category term="proxmox-backup-server"/><category term="offsite-backup"/><category term="backblaze"/><category term="hetzner"/><category term="cloudflare-r2"/><category term="s3"/><category term="encryption"/><category term="ransomware"/><category term="monitoring"/><category term="uptime-kuma"/><category term="truenas"/><category term="synology"/><category term="rsync"/><category term="borgbackup"/></entry><entry><title>Traefik vs Nginx Proxy Manager vs Caddy for Homelab 2026: The Reverse Proxy Decision Guide</title><link href="https://steadypub.com/2026/06/traefik-vs-nginx-proxy-manager-vs-caddy-homelab-2026/" rel="alternate"/><published>2026-06-07T00:00:00+07:00</published><updated>2026-06-07T00:00:00+07:00</updated><author><name>WordForge Team</name></author><id>tag:steadypub.com,2026-06-07:/2026/06/traefik-vs-nginx-proxy-manager-vs-caddy-homelab-2026/</id><summary type="html">&lt;p&gt;Compare Traefik, Nginx Proxy Manager, and Caddy head-to-head for your homelab reverse proxy. Docker Compose configs, decision tree, performance benchmarks, Proxmox deployment, and Cloudflare Tunnel integration — all updated for&amp;nbsp;2026.&lt;/p&gt;</summary><content type="html">&lt;hr&gt;
&lt;h1&gt;Traefik vs Nginx Proxy Manager vs Caddy for Homelab 2026: The Reverse Proxy Decision&amp;nbsp;Guide&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~16 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab owners choosing their first reverse proxy, or migrating from one to another
&lt;strong&gt;Last tested:&lt;/strong&gt; June 2026 — Traefik 3.2, Nginx Proxy Manager 2.12, Caddy&amp;nbsp;2.8&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Introduction: The Homelab Reverse Proxy&amp;nbsp;Problem&lt;/h2&gt;
&lt;p&gt;You have fifteen Docker containers running in your homelab — Nextcloud on port 8080, Pi-hole on port 8180, Plex on port 32400, Home Assistant on port 8123. Your browser autocomplete is a graveyard&amp;nbsp;of &lt;code&gt;192.168.1.50:XXXX&lt;/code&gt; entries, your family refuses to type port numbers, and half your services scream &amp;#8220;Not Secure&amp;#8221; because you never set up &lt;span class="caps"&gt;HTTPS&lt;/span&gt;. There is a single piece of software that fixes all of this at once: a &lt;strong&gt;reverse proxy&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;A reverse proxy sits at the edge of your network, receives every incoming &lt;span class="caps"&gt;HTTP&lt;/span&gt; request on standard ports 80 and 443, inspects the domain name in the request header, and routes traffic to the correct backend container. You go from memorizing ports to&amp;nbsp;typing &lt;code&gt;photos.homelab.local&lt;/code&gt;, &lt;code&gt;admin.homelab.local&lt;/code&gt;,&amp;nbsp;and &lt;code&gt;dash.homelab.local&lt;/code&gt;. Every service gets automatic &lt;span class="caps"&gt;HTTPS&lt;/span&gt; via Let&amp;#8217;s Encrypt. Your browser lock icon turns green. Your family stops asking why the website looks&amp;nbsp;broken.&lt;/p&gt;
&lt;p&gt;But here is the problem: in 2026, there are three dominant reverse proxies in the homelab space — &lt;strong&gt;Traefik&lt;/strong&gt;, &lt;strong&gt;Nginx Proxy Manager&lt;/strong&gt;, and &lt;strong&gt;Caddy&lt;/strong&gt; — and they serve fundamentally different audiences. Pick wrong, and you spend weeks fighting configuration files that feel designed by people who hate you. Pick right, and your reverse proxy becomes the most reliable piece of your&amp;nbsp;infrastructure.&lt;/p&gt;
&lt;p&gt;This guide compares all three head-to-head with copy-paste Docker Compose configs, a detailed comparison matrix, a decision tree for five common homelab scenarios, Cloudflare Tunnel integration, and Proxmox deployment notes — everything updated for&amp;nbsp;2026.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Meet the Three&amp;nbsp;Contenders&lt;/h2&gt;
&lt;h3&gt;Traefik — The Kubernetes-Native&amp;nbsp;Powerhouse&lt;/h3&gt;
&lt;p&gt;Traefik is the Swiss Army knife of reverse proxies. It was purpose-built for container-native environments: it discovers services automatically by watching Docker socket events or Kubernetes &lt;span class="caps"&gt;API&lt;/span&gt; endpoints. You spin up a new container with the&amp;nbsp;label &lt;code&gt;traefik.http.routers.app.rule=Host("app.example.com")&lt;/code&gt; and Traefik wires it into the routing table without a config file edit or a&amp;nbsp;reload.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why homelabbers love it:&lt;/strong&gt; Automatic service discovery means zero manual proxy-host configuration. A dashboard&amp;nbsp;at &lt;code&gt;traefik.example.com&lt;/code&gt; shows every router, service, and middleware in real time. Middleware chains — rate limiting, &lt;span class="caps"&gt;IP&lt;/span&gt; whitelisting, basic auth, redirect regex — stack like &lt;span class="caps"&gt;LEGO&lt;/span&gt; blocks. Traefik 3.x added Gateway &lt;span class="caps"&gt;API&lt;/span&gt; support, &lt;span class="caps"&gt;HTTP&lt;/span&gt;/3 (&lt;span class="caps"&gt;QUIC&lt;/span&gt;), and OpenTelemetry&amp;nbsp;tracing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why homelabbers curse it:&lt;/strong&gt; The learning curve is real. Traefik has three configuration layers (static, dynamic, and Docker labels) and the documentation assumes you already understand reverse proxy theory. A misplaced &lt;span class="caps"&gt;YAML&lt;/span&gt; indent or a&amp;nbsp;forgotten &lt;code&gt;entrypoints&lt;/code&gt; definition produces silent failures. The dashboard is read-only by default — you cannot add a route through the &lt;span class="caps"&gt;GUI&lt;/span&gt;. If you need a &lt;span class="caps"&gt;GUI&lt;/span&gt; for proxy-host management, Traefik is not your&amp;nbsp;tool.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Advanced users who run 10+ containers, want automatic discovery, and are comfortable with &lt;span class="caps"&gt;YAML&lt;/span&gt;-first configuration. If you already use Portainer or Komodo to manage container stacks, Traefik pairs&amp;nbsp;naturally.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;Nginx Proxy Manager — The &lt;span class="caps"&gt;GUI&lt;/span&gt;-First Beginner&amp;#8217;s&amp;nbsp;Choice&lt;/h3&gt;
&lt;p&gt;Nginx Proxy Manager (&lt;span class="caps"&gt;NPM&lt;/span&gt;) wraps the battle-tested Nginx engine in a clean, intuitive web &lt;span class="caps"&gt;GUI&lt;/span&gt;. You&amp;nbsp;open &lt;code&gt;http://your-ip:81&lt;/code&gt;, log in, click &amp;#8220;Add Proxy Host,&amp;#8221; fill in domain name, backend &lt;span class="caps"&gt;IP&lt;/span&gt;:port, toggle &amp;#8220;Block Common Exploits,&amp;#8221; and click &amp;#8220;&lt;span class="caps"&gt;SSL&lt;/span&gt;&amp;#8221; to request a Let&amp;#8217;s Encrypt certificate. That is the entire workflow. No config files. No &lt;span class="caps"&gt;YAML&lt;/span&gt;. No &lt;span class="caps"&gt;CLI&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why homelabbers love it:&lt;/strong&gt; The barrier to entry is near-zero. If you can fill out a web form, you can run &lt;span class="caps"&gt;NPM&lt;/span&gt;. The &lt;span class="caps"&gt;GUI&lt;/span&gt; shows every proxy host with a green/red status indicator. Let&amp;#8217;s Encrypt certificate renewal is fully automatic. Access lists let you add &lt;span class="caps"&gt;HTTP&lt;/span&gt; basic auth to specific hosts with a few clicks. &lt;span class="caps"&gt;NPM&lt;/span&gt; 2.12 added &lt;span class="caps"&gt;HTTP&lt;/span&gt;/2 push support, improved WebSocket handling, and a dark mode for the admin&amp;nbsp;panel.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why homelabbers curse it:&lt;/strong&gt; The &lt;span class="caps"&gt;GUI&lt;/span&gt; is the only management interface — there is no &lt;span class="caps"&gt;API&lt;/span&gt;, no IaC path, and no config-as-code workflow. If your &lt;span class="caps"&gt;NPM&lt;/span&gt; database gets corrupted, you must rebuild every proxy host by hand (unless you backed up the SQLite file). Custom Nginx directives require dropping into the &amp;#8220;Advanced&amp;#8221; tab and writing raw Nginx config — eliminating the &lt;span class="caps"&gt;GUI&lt;/span&gt;&amp;#8217;s simplicity advantage. No native Docker socket integration or automatic service&amp;nbsp;discovery.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Beginners who want a working reverse proxy in 15 minutes. Homelabbers with fewer than 15 services who prefer clicking to typing. Anyone migrating from a manual Nginx setup who wants a &lt;span class="caps"&gt;GUI&lt;/span&gt; wrapper around the same engine they already&amp;nbsp;trust.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Already running &lt;span class="caps"&gt;NPM&lt;/span&gt;?&lt;/strong&gt; See our dedicated beginner guide: &lt;a href="/2026/06/nginx-proxy-manager-docker-compose/"&gt;Nginx Proxy Manager Docker&amp;nbsp;Compose&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;Caddy — The Zero-Config &lt;span class="caps"&gt;HTTPS&lt;/span&gt;&amp;nbsp;Contender&lt;/h3&gt;
&lt;p&gt;Caddy is the developer-friendly reverse proxy that ships with automatic &lt;span class="caps"&gt;HTTPS&lt;/span&gt; by default. You write a&amp;nbsp;three-line &lt;code&gt;Caddyfile&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;app.example.com {
    reverse_proxy localhost:8080
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Caddy obtains a Let&amp;#8217;s Encrypt certificate on first launch and renews it silently forever. No certificate settings. No cron jobs. No &amp;#8220;&lt;span class="caps"&gt;SSL&lt;/span&gt;&amp;#8221; tab to click. It just works. Caddy 2.8 added &lt;span class="caps"&gt;HTTP&lt;/span&gt;/3 support, improved reverse proxy health checks, and a&amp;nbsp;new &lt;code&gt;caddy adapt&lt;/code&gt; command for validating configs before&amp;nbsp;reload.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why homelabbers love it:&lt;/strong&gt; The configuration syntax is the cleanest of the three. A Caddyfile reads like pseudocode. Zero &lt;span class="caps"&gt;SSL&lt;/span&gt; configuration overhead. Built-in support for the &lt;span class="caps"&gt;ACME&lt;/span&gt; &lt;span class="caps"&gt;DNS&lt;/span&gt;-01 challenge (needed for wildcard certificates and services behind Cloudflare).&amp;nbsp;The &lt;code&gt;caddy-docker-proxy&lt;/code&gt; module adds Docker label-based routing similar to Traefik but with Caddy&amp;#8217;s simpler&amp;nbsp;syntax.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why homelabbers curse it:&lt;/strong&gt; The plugin ecosystem, while growing, is smaller than Nginx&amp;#8217;s. Some advanced features — rate limiting, failover, request transformation — require compiling Caddy with non-standard modules&amp;nbsp;using &lt;code&gt;xcaddy&lt;/code&gt;. The official Docker image is minimal; adding plugins requires a custom build step in your Dockerfile or using a community image. No native &lt;span class="caps"&gt;GUI&lt;/span&gt;. The Caddyfile syntax, while clean, is unlike any other reverse proxy config&amp;nbsp;format.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Users who want the simplest possible &lt;span class="caps"&gt;HTTPS&lt;/span&gt; setup. Developers who value clean configuration syntax. Homelabbers who run fewer than 10 services and want a &amp;#8220;set and forget&amp;#8221; reverse proxy that handles certificates without human&amp;nbsp;intervention.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Head-to-Head Comparison&amp;nbsp;Matrix&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Criteria&lt;/th&gt;
&lt;th&gt;Traefik 3.x&lt;/th&gt;
&lt;th&gt;Nginx Proxy Manager 2.12&lt;/th&gt;
&lt;th&gt;Caddy 2.8&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Learning curve&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Steep (&lt;span class="caps"&gt;YAML&lt;/span&gt; + labels)&lt;/td&gt;
&lt;td&gt;Flat (&lt;span class="caps"&gt;GUI&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;Moderate (Caddyfile)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;GUI&lt;/span&gt; management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Dashboard (read-only)&lt;/td&gt;
&lt;td&gt;Full &lt;span class="caps"&gt;GUI&lt;/span&gt; admin&lt;/td&gt;
&lt;td&gt;None (&lt;span class="caps"&gt;CLI&lt;/span&gt;/config)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Auto &lt;span class="caps"&gt;HTTPS&lt;/span&gt; (Let&amp;#8217;s Encrypt)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Built-in&lt;/td&gt;
&lt;td&gt;✅ One-click in &lt;span class="caps"&gt;GUI&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;✅ Zero-config default&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Automatic service discovery&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Docker/K8s labels&lt;/td&gt;
&lt;td&gt;❌ Manual only&lt;/td&gt;
&lt;td&gt;⚠️&amp;nbsp;With &lt;code&gt;caddy-docker-proxy&lt;/code&gt; plugin&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Docker Compose complexity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High (static + dynamic configs)&lt;/td&gt;
&lt;td&gt;Low (single service + &lt;span class="caps"&gt;DB&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;Low (single service + Caddyfile)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Raw config flexibility&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Very high&lt;/td&gt;
&lt;td&gt;Medium (Advanced tab)&lt;/td&gt;
&lt;td&gt;High (Caddyfile)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Middleware / plugins&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;50+ built-in middlewares&lt;/td&gt;
&lt;td&gt;Nginx directives&lt;/td&gt;
&lt;td&gt;Plugin ecosystem (xcaddy)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;HTTP&lt;/span&gt;/3 (&lt;span class="caps"&gt;QUIC&lt;/span&gt;) support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Native in v3&lt;/td&gt;
&lt;td&gt;❌ (&lt;span class="caps"&gt;HTTP&lt;/span&gt;/2 max)&lt;/td&gt;
&lt;td&gt;✅ Native in v2.8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;WebSocket support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Automatic&lt;/td&gt;
&lt;td&gt;✅ Toggle in &lt;span class="caps"&gt;GUI&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;✅ Automatic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;API&lt;/span&gt; / IaC support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ &lt;span class="caps"&gt;REST&lt;/span&gt; &lt;span class="caps"&gt;API&lt;/span&gt; + &lt;span class="caps"&gt;CRD&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;❌ No &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;✅ Admin &lt;span class="caps"&gt;API&lt;/span&gt;&amp;nbsp;+ &lt;code&gt;caddy adapt&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Resource usage (idle)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~40 &lt;span class="caps"&gt;MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;~25 &lt;span class="caps"&gt;MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;~20 &lt;span class="caps"&gt;MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Docker image size&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~80 &lt;span class="caps"&gt;MB&lt;/span&gt; (alpine)&lt;/td&gt;
&lt;td&gt;~60 &lt;span class="caps"&gt;MB&lt;/span&gt; (alpine)&lt;/td&gt;
&lt;td&gt;~40 &lt;span class="caps"&gt;MB&lt;/span&gt; (alpine)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt;-01 challenge&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Built-in&lt;/td&gt;
&lt;td&gt;❌ Manual advanced config&lt;/td&gt;
&lt;td&gt;✅ Built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Wildcard certs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Via &lt;span class="caps"&gt;DNS&lt;/span&gt;-01&lt;/td&gt;
&lt;td&gt;⚠️ Manual Nginx config&lt;/td&gt;
&lt;td&gt;✅ Via &lt;span class="caps"&gt;DNS&lt;/span&gt;-01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dashboard / metrics&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Built-in dashboard + Prometheus&lt;/td&gt;
&lt;td&gt;Basic proxy-host list&lt;/td&gt;
&lt;td&gt;None (external monitoring)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;10+ containers, automation first&lt;/td&gt;
&lt;td&gt;Beginners, &amp;lt;15 services, &lt;span class="caps"&gt;GUI&lt;/span&gt;-first&lt;/td&gt;
&lt;td&gt;Simplicity first, &amp;lt;10 services&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Decision Tree: Which Reverse Proxy Should You&amp;nbsp;Choose?&lt;/h2&gt;
&lt;p&gt;Answer these five questions in order. The first &amp;#8220;yes&amp;#8221; you hit is your&amp;nbsp;recommendation.&lt;/p&gt;
&lt;h3&gt;Scenario 1: &amp;#8220;I just want &lt;span class="caps"&gt;HTTPS&lt;/span&gt; on my services. I don&amp;#8217;t care about Docker labels, APIs, or advanced routing. Give me a &lt;span class="caps"&gt;GUI&lt;/span&gt;.&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;→ Pick Nginx Proxy Manager.&lt;/strong&gt; You will be up and running in 15 minutes. The &lt;span class="caps"&gt;GUI&lt;/span&gt; eliminates &lt;span class="caps"&gt;YAML&lt;/span&gt; entirely. Everything is&amp;nbsp;point-and-click.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;Scenario 2: &amp;#8220;I run 15+ containers, add new ones every week, and I want my reverse proxy to detect new services automatically without manual host&amp;nbsp;creation.&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;→ Pick Traefik.&lt;/strong&gt; Docker label-based auto-discovery means you configure routing inside each&amp;nbsp;container&amp;#8217;s &lt;code&gt;docker-compose.yml&lt;/code&gt; and Traefik picks it up without a reload. No &lt;span class="caps"&gt;GUI&lt;/span&gt;&amp;nbsp;bottleneck.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;Scenario 3: &amp;#8220;I hate &lt;span class="caps"&gt;YAML&lt;/span&gt; and I hate GUIs. I want the cleanest possible config syntax and I never want to think about &lt;span class="caps"&gt;SSL&lt;/span&gt; certificates&amp;nbsp;again.&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;→ Pick Caddy.&lt;/strong&gt;&amp;nbsp;The &lt;code&gt;Caddyfile&lt;/code&gt; syntax is the most readable of any reverse proxy. Automatic &lt;span class="caps"&gt;HTTPS&lt;/span&gt; is truly zero-config — no toggle, no checkbox, no cron job. It just&amp;nbsp;happens.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;Scenario 4: &amp;#8220;I need advanced routing — sticky sessions, circuit breakers, rate limiting, &lt;span class="caps"&gt;IP&lt;/span&gt; whitelisting, traffic splitting — and I&amp;#8217;m comfortable with config&amp;nbsp;files.&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;→ Pick Traefik or Caddy, depending on your tolerance for &lt;span class="caps"&gt;YAML&lt;/span&gt;.&lt;/strong&gt; Traefik has a richer built-in middleware catalog. Caddy requires plugins for some advanced features but the config syntax is easier to maintain long-term. If your routing logic spans multiple conditions, Traefik&amp;#8217;s router/middleware/service separation is&amp;nbsp;cleaner.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;Scenario 5: &amp;#8220;I want to manage my reverse proxy config in Git, review changes in pull requests, and deploy via &lt;span class="caps"&gt;CI&lt;/span&gt;/&lt;span class="caps"&gt;CD&lt;/span&gt;.&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;→ Pick Traefik.&lt;/strong&gt; Its &lt;span class="caps"&gt;YAML&lt;/span&gt; configuration files are Git-ops friendly. You can&amp;nbsp;store &lt;code&gt;traefik.yml&lt;/code&gt; and &lt;code&gt;dynamic.yml&lt;/code&gt; in version control, review routing changes before deployment, and use Git history to roll back misconfigurations.&amp;nbsp;Caddy&amp;#8217;s &lt;code&gt;Caddyfile&lt;/code&gt; also works in Git-ops flows, but Traefik&amp;#8217;s separation of static and dynamic config gives finer control. &lt;span class="caps"&gt;NPM&lt;/span&gt; has no config-as-code&amp;nbsp;path.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Docker Compose: All Three Side by&amp;nbsp;Side&lt;/h2&gt;
&lt;p&gt;All three reverse proxies can be deployed in under 5 minutes with these minimal Compose files. Customize&amp;nbsp;the &lt;code&gt;.env&lt;/code&gt; variables before&amp;nbsp;starting.&lt;/p&gt;
&lt;h3&gt;Traefik Docker Compose&amp;nbsp;(v3.2)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# traefik/docker-compose.yml&lt;/span&gt;
&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;traefik&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;traefik:v3.2&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;traefik&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;80:80&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# HTTP&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;443:443&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# HTTPS&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8080:8080&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Dashboard (internal-only recommended)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/var/run/docker.sock:/var/run/docker.sock:ro&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;# Docker provider&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./traefik.yml:/traefik.yml:ro&lt;/span&gt;&lt;span class="w"&gt;                   &lt;/span&gt;&lt;span class="c1"&gt;# Static config&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./dynamic.yml:/dynamic.yml:ro&lt;/span&gt;&lt;span class="w"&gt;                   &lt;/span&gt;&lt;span class="c1"&gt;# Dynamic config&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./certs:/certs&lt;/span&gt;&lt;span class="w"&gt;                                  &lt;/span&gt;&lt;span class="c1"&gt;# Let&amp;#39;s Encrypt storage&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;proxy&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.enable=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.dashboard.rule=Host(`traefik.homelab.local`)&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.dashboard.service=api@internal&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.dashboard.middlewares=auth&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Basic auth: generate with `htpasswd -nb admin password`&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.middlewares.auth.basicauth.users=admin:$$2y$$10$$...&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;external&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Traefik static config&lt;/strong&gt;&amp;nbsp;(&lt;code&gt;traefik.yml&lt;/code&gt;):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# traefik.yml — Static configuration (read on startup only)&lt;/span&gt;
&lt;span class="nt"&gt;entryPoints&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;web&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;redirections&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;entryPoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;websecure&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;scheme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;https&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;websecure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;:443&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;docker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;unix:///var/run/docker.sock&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;exposedByDefault&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;false&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="c1"&gt;# Only expose labeled containers&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/dynamic.yml&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="c1"&gt;# Services defined in YAML&lt;/span&gt;

&lt;span class="nt"&gt;certificatesResolvers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;letsencrypt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;acme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;your-email@example.com&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/certs/acme.json&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;httpChallenge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;entryPoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;web&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="c1"&gt;# HTTP-01 challenge&lt;/span&gt;

&lt;span class="nt"&gt;api&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;dashboard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;insecure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;false&lt;/span&gt;&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="c1"&gt;# Keep internal-only&lt;/span&gt;

&lt;span class="nt"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;prometheus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;                     &lt;/span&gt;&lt;span class="c1"&gt;# /metrics endpoint for Grafana&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h3&gt;Nginx Proxy Manager Docker Compose&amp;nbsp;(v2.12)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# nginx-proxy-manager/docker-compose.yml&lt;/span&gt;
&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;npm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;jc21/nginx-proxy-manager:2.12&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;npm&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;80:80&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# HTTP&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;443:443&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# HTTPS&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;81:81&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Admin GUI&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./data:/data&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./letsencrypt:/etc/letsencrypt&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;DISABLE_IPV6=true&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;proxy&lt;/span&gt;

&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;external&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After starting,&amp;nbsp;open &lt;code&gt;http://localhost:81&lt;/code&gt; and log in&amp;nbsp;with &lt;code&gt;admin@example.com&lt;/code&gt; / &lt;code&gt;changeme&lt;/code&gt;. Add proxy hosts via the &lt;span class="caps"&gt;GUI&lt;/span&gt; — no config files&amp;nbsp;needed.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;New to Docker Compose?&lt;/strong&gt; Start with our &lt;a href="/2026/06/docker-compose-for-beginners/"&gt;Docker Compose for Beginners&lt;/a&gt; guide before&amp;nbsp;deploying.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;Caddy Docker Compose&amp;nbsp;(v2.8)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# caddy/docker-compose.yml&lt;/span&gt;
&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;caddy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;caddy:2.8-alpine&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;caddy&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;80:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;443:443&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;443:443/udp&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;# HTTP/3 (QUIC)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./Caddyfile:/etc/caddy/Caddyfile:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./data:/data&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;# Certificate storage&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./config:/config&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# Server config&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;proxy&lt;/span&gt;

&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;external&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Caddyfile&amp;nbsp;example:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Caddyfile&lt;/span&gt;
&lt;span class="err"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;your&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="nv"&gt;@example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;admin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;off&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Disable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;admin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;API&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;production&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;homelab&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;reverse_proxy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;nextcloud&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;photos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;homelab&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;reverse_proxy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;immich&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3001&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Wildcard&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;via&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Cloudflare&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DNS&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;01&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;challenge&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Requires&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cloudflare&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;module&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xcaddy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;--with github.com/caddy-dns/cloudflare&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;homelab&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;tls&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;dns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cloudflare&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CLOUDFLARE_API_TOKEN&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nv"&gt;@app&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;homelab&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;local&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;@app&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;reverse_proxy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;nextcloud&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Proxmox Deployment&amp;nbsp;Notes&lt;/h2&gt;
&lt;p&gt;All three reverse proxies run cleanly inside Proxmox &lt;span class="caps"&gt;LXC&lt;/span&gt; containers or VMs. Here are the deployment specifics for homelab users running Proxmox&amp;nbsp;8.x:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Setup&lt;/th&gt;
&lt;th&gt;Traefik&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;NPM&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Caddy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Recommended Proxmox host&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;LXC&lt;/span&gt; (privileged, nesting=1) or &lt;span class="caps"&gt;VM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;LXC&lt;/span&gt; (any) or &lt;span class="caps"&gt;VM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;LXC&lt;/span&gt; (any) or &lt;span class="caps"&gt;VM&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Docker inside &lt;span class="caps"&gt;LXC&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Requires &lt;code&gt;features: nesting=1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Same&lt;/td&gt;
&lt;td&gt;Same&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best practice&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Dedicated &lt;span class="caps"&gt;LXC&lt;/span&gt; container, 2 vCPU, 2 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Dedicated &lt;span class="caps"&gt;LXC&lt;/span&gt;, 1 vCPU, 1 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Dedicated &lt;span class="caps"&gt;LXC&lt;/span&gt;, 1 vCPU, 512 &lt;span class="caps"&gt;MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Port 80/443 access&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Forward from router to Proxmox host &lt;span class="caps"&gt;IP&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Forward from router to host &lt;span class="caps"&gt;IP&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Forward from router to host &lt;span class="caps"&gt;IP&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Proxmox firewall&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Allow ports 80, 443 inbound&lt;/td&gt;
&lt;td&gt;Allow ports 80, 443, 81 inbound&lt;/td&gt;
&lt;td&gt;Allow ports 80, 443 inbound&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Setting up Proxmox first?&lt;/strong&gt; Follow our &lt;a href="/2026/06/proxmox-beginner-guide-2026/"&gt;Proxmox Beginner Guide&lt;/a&gt; before deploying a reverse proxy&amp;nbsp;container.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;All three reverse proxies benefit from being the &lt;strong&gt;only&lt;/strong&gt; service listening on ports 80 and 443 on the Proxmox host. If you run multiple reverse proxies or services that bind to these ports, use macvlan or ipvlan Docker networks to assign dedicated&amp;nbsp;IPs.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Cloudflare Tunnel&amp;nbsp;Integration&lt;/h2&gt;
&lt;p&gt;Pairing a reverse proxy with Cloudflare Tunnel gives you secure remote access without opening ports 80/443 on your router. This is ideal if you are behind &lt;span class="caps"&gt;CGNAT&lt;/span&gt; or prefer not to expose your home &lt;span class="caps"&gt;IP&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;Architecture&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Internet → Cloudflare Edge → cloudflared tunnel → localhost:8080 → Reverse Proxy → Docker backend
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The reverse proxy receives requests on an internal port (e.g., 8080) instead of binding directly to 80/443. Cloudflare&amp;nbsp;Tunnel&amp;#8217;s &lt;code&gt;cloudflared&lt;/code&gt; daemon connects to Cloudflare&amp;#8217;s edge and forwards traffic&amp;nbsp;to &lt;code&gt;localhost:8080&lt;/code&gt;, which Traefik/&lt;span class="caps"&gt;NPM&lt;/span&gt;/Caddy listens&amp;nbsp;on.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Minimal &lt;code&gt;cloudflared&lt;/code&gt; config&lt;/strong&gt;&amp;nbsp;(&lt;code&gt;config.yml&lt;/code&gt;):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;tunnel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;YOUR-TUNNEL-ID&lt;/span&gt;
&lt;span class="nt"&gt;credentials-file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/etc/cloudflared/credentials.json&lt;/span&gt;

&lt;span class="nt"&gt;ingress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;*.yourdomain.com&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;http://reverse-proxy:80&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;http_status:404&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Complete Cloudflare Tunnel setup:&lt;/strong&gt; See our &lt;a href="/2026/06/cloudflare-tunnel-homelab/"&gt;Cloudflare Tunnel Homelab Guide&lt;/a&gt; for the full walkthrough, including Tunnel creation, &lt;span class="caps"&gt;DNS&lt;/span&gt; configuration, and security&amp;nbsp;hardening.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Traefik + Cloudflare Tunnel&amp;nbsp;specifics&lt;/h3&gt;
&lt;p&gt;Traefik needs to trust&amp;nbsp;the &lt;code&gt;X-Forwarded-*&lt;/code&gt; headers sent by Cloudflare. Add the following to&amp;nbsp;your &lt;code&gt;traefik.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;entryPoints&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;websecure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;:443&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;forwardedHeaders&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;trustedIPs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;173.245.48.0/20&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;# Cloudflare IP ranges&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;103.21.244.0/22&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;103.22.200.0/22&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# Full list at https://www.cloudflare.com/ips/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Performance Benchmarks&amp;nbsp;(Estimated)&lt;/h2&gt;
&lt;p&gt;These numbers are approximate, derived from community benchmarks on Reddit r/selfhosted and the Caddy vs Traefik vs Nginx comparison threads. Your mileage will vary based on hardware, backend latency, and &lt;span class="caps"&gt;TLS&lt;/span&gt;&amp;nbsp;configuration.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Traefik 3.2&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;NPM&lt;/span&gt; 2.12 (Nginx)&lt;/th&gt;
&lt;th&gt;Caddy 2.8&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Requests/sec (static file, &lt;span class="caps"&gt;1KB&lt;/span&gt;)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~18,000&lt;/td&gt;
&lt;td&gt;~28,000&lt;/td&gt;
&lt;td&gt;~25,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Requests/sec (proxy to backend, &lt;span class="caps"&gt;1KB&lt;/span&gt;)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~12,000&lt;/td&gt;
&lt;td&gt;~18,000&lt;/td&gt;
&lt;td&gt;~16,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;TLS&lt;/span&gt; handshake latency (new)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~12 ms&lt;/td&gt;
&lt;td&gt;~8 ms&lt;/td&gt;
&lt;td&gt;~10 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Idle &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~40 &lt;span class="caps"&gt;MB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;~25 &lt;span class="caps"&gt;MB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;~20 &lt;span class="caps"&gt;MB&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Under load &lt;span class="caps"&gt;RAM&lt;/span&gt; (1,000 req/s)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~120 &lt;span class="caps"&gt;MB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;~80 &lt;span class="caps"&gt;MB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;~60 &lt;span class="caps"&gt;MB&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Configuration reload time&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&amp;lt;50 ms (hot)&lt;/td&gt;
&lt;td&gt;&amp;lt;100 ms (reloads Nginx)&lt;/td&gt;
&lt;td&gt;&amp;lt;30 ms (graceful)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Key takeaway:&lt;/strong&gt; &lt;span class="caps"&gt;NPM&lt;/span&gt; (backed by Nginx) is the raw throughput champion for homelab workloads. Caddy is close behind with less &lt;span class="caps"&gt;RAM&lt;/span&gt;. Traefik trades some throughput for its dynamic discovery features. For a homelab serving family traffic — not a SaaS product with 10,000 concurrent users — any of the three will saturate your gigabit &lt;span class="caps"&gt;LAN&lt;/span&gt; before the reverse proxy becomes the&amp;nbsp;bottleneck.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Internal Links: Building Your Homelab&amp;nbsp;Stack&lt;/h2&gt;
&lt;p&gt;Each reverse proxy is one piece of a larger homelab infrastructure. Here is how the rest of the SteadyPub content library&amp;nbsp;connects:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Article&lt;/th&gt;
&lt;th&gt;Why It Connects&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Docker Compose basics&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="/2026/06/docker-compose-for-beginners/"&gt;Docker Compose for Beginners&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Foundation for all three reverse proxy deployments&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Container management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="/2026/06/portainer-docker-compose-stack/"&gt;Portainer Docker Compose Stack&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Manage reverse proxy containers with a &lt;span class="caps"&gt;GUI&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Local &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="/2026/06/pihole-docker-compose/"&gt;Pi-hole Docker Compose&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Resolve &lt;code&gt;*.homelab.local&lt;/code&gt; domains through reverse proxy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Alt &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="/2026/06/adguard-home-docker/"&gt;AdGuard Home Docker&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Alternative &lt;span class="caps"&gt;DNS&lt;/span&gt; for internal domain resolution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cloudflare Tunnel&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="/2026/06/cloudflare-tunnel-homelab/"&gt;Cloudflare Tunnel Homelab&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Secure remote access without opening ports&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Monitoring&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="/2026/06/grafana-docker-compose/"&gt;Grafana Docker Compose&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Monitor reverse proxy performance with metrics&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Monitoring&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="/2026/06/prometheus-monitoring-homelab/"&gt;Prometheus Monitoring Homelab&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Collect reverse proxy metrics for Grafana dashboards&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hardware&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="/2026/06/best-mini-pc-for-homelab/"&gt;Best Mini &lt;span class="caps"&gt;PC&lt;/span&gt; for Homelab&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Hardware for running your reverse proxy 24/7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hardware&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="/2026/06/intel-n100-mini-pc-homelab/"&gt;Intel N100 Mini &lt;span class="caps"&gt;PC&lt;/span&gt; Homelab&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Low-power, always-on reverse proxy host&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;VPN&lt;/span&gt; (alternative)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="/2026/06/self-hosted-vpn-homelab/"&gt;Self-Hosted &lt;span class="caps"&gt;VPN&lt;/span&gt; Homelab&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;WireGuard as an alternative to Cloudflare Tunnel&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;SSO&lt;/span&gt; (next step)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="/"&gt;Vaultwarden Docker Compose&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Password manager behind your reverse proxy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Identity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="/2026/06/authelia-authentik-sso-homelab/"&gt;Authelia / Authentik &lt;span class="caps"&gt;SSO&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Add single sign-on in front of proxy-protected services&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;&lt;span class="caps"&gt;FAQ&lt;/span&gt;: Common Reverse Proxy&amp;nbsp;Questions&lt;/h2&gt;
&lt;h3&gt;Do I need a reverse proxy if I only have three&amp;nbsp;services?&lt;/h3&gt;
&lt;p&gt;Yes — for &lt;span class="caps"&gt;HTTPS&lt;/span&gt; alone. Without a reverse proxy, you must configure &lt;span class="caps"&gt;TLS&lt;/span&gt; on each service individually. With one, you configure it once. Even for three services, the time savings justify the&amp;nbsp;setup.&lt;/p&gt;
&lt;h3&gt;Can I run two reverse proxies at the same&amp;nbsp;time?&lt;/h3&gt;
&lt;p&gt;Technically yes, but avoid it. Two reverse proxies competing for ports 80/443 create routing headaches. Pick one reverse proxy and route all traffic through it. If you need a second (e.g., Traefik for Docker services and &lt;span class="caps"&gt;NPM&lt;/span&gt; for non-Docker services), use a dedicated &lt;span class="caps"&gt;IP&lt;/span&gt; per proxy via&amp;nbsp;macvlan.&lt;/p&gt;
&lt;h3&gt;Which reverse proxy is best for WebSocket-heavy services (Home Assistant, Uptime Kuma,&amp;nbsp;code-server)?&lt;/h3&gt;
&lt;p&gt;All three handle WebSockets natively with minimal configuration. Traefik and Caddy detect and proxy WebSocket upgrades automatically. &lt;span class="caps"&gt;NPM&lt;/span&gt; requires toggling the &amp;#8220;WebSockets Support&amp;#8221; switch in the &lt;span class="caps"&gt;GUI&lt;/span&gt; for each proxy&amp;nbsp;host.&lt;/p&gt;
&lt;h3&gt;How do I monitor reverse proxy&amp;nbsp;health?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Traefik:&lt;/strong&gt; Built-in Prometheus metrics endpoint&amp;nbsp;at &lt;code&gt;/metrics&lt;/code&gt;. Pair with &lt;a href="/2026/06/grafana-docker-compose/"&gt;Grafana&lt;/a&gt; for&amp;nbsp;dashboards.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;NPM&lt;/span&gt;:&lt;/strong&gt; No native metrics. Monitor via container health checks and &lt;span class="caps"&gt;HTTP&lt;/span&gt; status&amp;nbsp;probes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Caddy:&lt;/strong&gt; Built-in Prometheus metrics with&amp;nbsp;the &lt;code&gt;caddy-http-prometheus&lt;/code&gt; plugin.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For general uptime monitoring of your services behind the proxy, add &lt;a href="/2026/06/uptime-kuma-docker-compose-homelab-2026/"&gt;Uptime Kuma&lt;/a&gt; to your Docker&amp;nbsp;stack.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Final&amp;nbsp;Recommendation&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;You are&amp;#8230;&lt;/th&gt;
&lt;th&gt;Use&amp;#8230;&lt;/th&gt;
&lt;th&gt;Because&amp;#8230;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;A beginner with 3-10 services&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Nginx Proxy Manager&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;GUI&lt;/span&gt; eliminates the learning curve. You&amp;#8217;ll be online in 15 minutes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;An intermediate tinkerer who values simplicity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Caddy&lt;/td&gt;
&lt;td&gt;Cleanest config syntax. Automatic &lt;span class="caps"&gt;HTTPS&lt;/span&gt; with zero effort.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;An advanced homelabber with 15+ containers and automation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Traefik&lt;/td&gt;
&lt;td&gt;Auto-discovery and config-as-code scale with your infrastructure.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Someone who wants Git-ops / &lt;span class="caps"&gt;CI&lt;/span&gt;/&lt;span class="caps"&gt;CD&lt;/span&gt; for config&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Traefik&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;YAML&lt;/span&gt; configs are version-control friendly.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Someone who never wants to edit a text file&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Nginx Proxy Manager&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;GUI&lt;/span&gt;-only workflow.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Someone who wants the absolute lightest resource footprint&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Caddy&lt;/td&gt;
&lt;td&gt;20 &lt;span class="caps"&gt;MB&lt;/span&gt; idle &lt;span class="caps"&gt;RAM&lt;/span&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;There is no single &amp;#8220;best&amp;#8221; reverse proxy for everyone. The correct choice depends on how many services you run, how much you value automation versus simplicity, and whether you prefer clicking buttons or editing config files. All three are production-grade, actively maintained, and power thousands of homelabs in&amp;nbsp;2026.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SteadyPub recommendation:&lt;/strong&gt; Start with &lt;strong&gt;Nginx Proxy Manager&lt;/strong&gt; if you are new to reverse proxies. Graduate to &lt;strong&gt;Traefik&lt;/strong&gt; once you have 15+ containers and want automatic discovery. Use &lt;strong&gt;Caddy&lt;/strong&gt; if you value clean config syntax and truly zero-touch &lt;span class="caps"&gt;HTTPS&lt;/span&gt; above all&amp;nbsp;else.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Last updated: June 2026. Docker image versions: Traefik 3.2.0, Nginx Proxy Manager 2.12.1, Caddy&amp;nbsp;2.8.4.&lt;/em&gt;&lt;/p&gt;</content><category term="Guides"/><category term="traefik"/><category term="nginx-proxy-manager"/><category term="caddy"/><category term="reverse-proxy"/><category term="docker"/><category term="docker-compose"/><category term="homelab"/><category term="self-hosted"/><category term="ssl"/><category term="lets-encrypt"/><category term="proxmox"/><category term="cloudflare"/><category term="networking"/><category term="portainer"/><category term="uptime-kuma"/><category term="authelia"/><category term="sso"/></entry><entry><title>Uptime Kuma Docker Compose Setup for Homelab 2026: Monitor Every Service</title><link href="https://steadypub.com/2026/06/uptime-kuma-docker-compose-homelab-2026/" rel="alternate"/><published>2026-06-07T00:00:00+07:00</published><updated>2026-06-07T00:00:00+07:00</updated><author><name>WordForge Team</name></author><id>tag:steadypub.com,2026-06-07:/2026/06/uptime-kuma-docker-compose-homelab-2026/</id><summary type="html">&lt;p&gt;Deploy Uptime Kuma with Docker Compose to monitor your entire homelab. Step-by-step guide covers status pages, Telegram/Discord notifications, reverse proxy integration with &lt;span class="caps"&gt;NPM&lt;/span&gt; and Traefik, monitor type decision matrix, and the &amp;#8220;watch the watcher&amp;#8221; pattern with Healthchecks.io — all updated for&amp;nbsp;2026.&lt;/p&gt;</summary><content type="html">&lt;hr&gt;
&lt;h1&gt;Uptime Kuma Docker Compose Setup for Homelab 2026: Monitor Every&amp;nbsp;Service&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~14 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab owners who want to know when their services go down — before their family tells&amp;nbsp;them&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Introduction: The &amp;#8220;Who Watches the Watcher&amp;#8221;&amp;nbsp;Problem&lt;/h2&gt;
&lt;p&gt;Your homelab runs twenty Docker containers. Nextcloud holds your family photos. Jellyfin streams your media library. Pi-hole filters your &lt;span class="caps"&gt;DNS&lt;/span&gt;. Home Assistant controls your lights. And at 2 &lt;span class="caps"&gt;AM&lt;/span&gt;, while you are asleep, one of them silently crashes — and you find out at breakfast when your partner asks why the media server is broken&amp;nbsp;again.&lt;/p&gt;
&lt;p&gt;This is the fundamental monitoring problem every homelab owner faces: &lt;strong&gt;you cannot fix what you do not know is broken&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Uptime Kuma&lt;/strong&gt; is the solution. It is a free, open-source, self-hosted uptime monitoring tool with a beautiful web dashboard, multi-channel notifications, public status pages, and support for &lt;span class="caps"&gt;HTTP&lt;/span&gt;, &lt;span class="caps"&gt;TCP&lt;/span&gt;, &lt;span class="caps"&gt;DNS&lt;/span&gt;, Ping, Docker, and Push monitors. It runs in a single Docker container, consumes under 100 &lt;span class="caps"&gt;MB&lt;/span&gt; of &lt;span class="caps"&gt;RAM&lt;/span&gt;, and can monitor fifty services from a Raspberry Pi. And in 2026, with version 1.x mature and feature-complete, it is the undisputed king of self-hosted uptime&amp;nbsp;monitoring.&lt;/p&gt;
&lt;p&gt;But deploying Uptime Kuma is only half the battle. The real question is: &lt;strong&gt;who watches the watcher?&lt;/strong&gt; If Uptime Kuma itself goes down — because your Docker host rebooted, your Proxmox node crashed, or your &lt;span class="caps"&gt;ISP&lt;/span&gt; dropped the connection — all your monitoring goes dark and you will never know. This guide covers that too, with the &lt;strong&gt;Healthchecks.io &amp;#8220;watch the watcher&amp;#8221; pattern&lt;/strong&gt; that gives you a dead man&amp;#8217;s switch for your monitoring&amp;nbsp;stack.&lt;/p&gt;
&lt;p&gt;By the end of this guide, you will have: a production-ready Uptime Kuma deployment via Docker Compose, five real monitors watching your actual homelab services, Telegram and Discord notifications, a public-facing status page behind your reverse proxy, and a Healthchecks.io heartbeat that alerts you if Uptime Kuma itself dies. No other guide covers all of this in&amp;nbsp;2026.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;New to Docker Compose?&lt;/strong&gt; Start with our &lt;a href="/2026/06/docker-compose-for-beginners/"&gt;Docker Compose for Beginners guide&lt;/a&gt;. Already running a reverse proxy? Everything here integrates with &lt;a href="/2026/06/nginx-proxy-manager-docker-compose/"&gt;Nginx Proxy Manager&lt;/a&gt; and &lt;a href="/2026/06/traefik-vs-nginx-proxy-manager-vs-caddy-homelab-2026/"&gt;Traefik&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;Why Uptime Kuma in a&amp;nbsp;Homelab?&lt;/h2&gt;
&lt;p&gt;Before you deploy anything, it helps to understand what Uptime Kuma is — and what it is not. The homelab monitoring landscape has several tools, and choosing the wrong one wastes&amp;nbsp;hours.&lt;/p&gt;
&lt;h3&gt;Uptime Kuma vs. the&amp;nbsp;Alternatives&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Uptime Kuma&lt;/th&gt;
&lt;th&gt;UptimeRobot (Free)&lt;/th&gt;
&lt;th&gt;Prometheus + Alertmanager&lt;/th&gt;
&lt;th&gt;Grafana OnCall&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Self-hosted&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;❌ SaaS only&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Setup time&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~10 minutes&lt;/td&gt;
&lt;td&gt;~5 minutes&lt;/td&gt;
&lt;td&gt;~2 hours&lt;/td&gt;
&lt;td&gt;~1 hour&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Status pages&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Built-in&lt;/td&gt;
&lt;td&gt;✅ Built-in&lt;/td&gt;
&lt;td&gt;❌ Needs Grafana&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Push monitors&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;✅ Pushgateway&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Docker monitoring&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Native&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;✅ cAdvisor&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;GUI&lt;/span&gt; dashboard&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Beautiful&lt;/td&gt;
&lt;td&gt;✅ Simple&lt;/td&gt;
&lt;td&gt;❌ &lt;span class="caps"&gt;CLI&lt;/span&gt;/config only&lt;/td&gt;
&lt;td&gt;✅ Grafana&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Notification channels&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;60+&lt;/td&gt;
&lt;td&gt;5 (free tier)&lt;/td&gt;
&lt;td&gt;10+&lt;/td&gt;
&lt;td&gt;10+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Resource usage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~80 &lt;span class="caps"&gt;MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;N/A (SaaS)&lt;/td&gt;
&lt;td&gt;~2 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;~500 &lt;span class="caps"&gt;MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Learning curve&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;When to choose Uptime Kuma:&lt;/strong&gt; You want a dead-simple, beautiful uptime dashboard that takes 10 minutes to deploy and immediately tells you which services are up or down. You need built-in status pages, push monitors for cron jobs, and dozens of notification channels — without writing a single line of&amp;nbsp;PromQL.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;When to pair it with Prometheus and Grafana:&lt;/strong&gt; Uptime is a binary signal — up or down. It does not tell you &lt;em&gt;why&lt;/em&gt; your service is slow, &lt;em&gt;which&lt;/em&gt; database query is eating &lt;span class="caps"&gt;CPU&lt;/span&gt;, or &lt;em&gt;when&lt;/em&gt; your disk will fill up. For that, you want metrics. The two tools complement each other perfectly: Uptime Kuma for &amp;#8220;is it alive?&amp;#8221; and &lt;a href="/2026/06/grafana-prometheus-setup/"&gt;Grafana + Prometheus&lt;/a&gt; for &amp;#8220;how healthy is&amp;nbsp;it?&amp;#8221;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Resource requirements:&lt;/strong&gt; Uptime Kuma runs comfortably on a Raspberry Pi 4, an Intel N100 &lt;a href="/2026/06/best-mini-pc-for-homelab/"&gt;mini &lt;span class="caps"&gt;PC&lt;/span&gt;&lt;/a&gt;, or any Docker host with 512 &lt;span class="caps"&gt;MB&lt;/span&gt; of free &lt;span class="caps"&gt;RAM&lt;/span&gt;. The database (SQLite) stays small — under 200 &lt;span class="caps"&gt;MB&lt;/span&gt; even with hundreds of monitors and months of&amp;nbsp;history.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What You&amp;#8217;ll&amp;nbsp;Need&lt;/h2&gt;
&lt;h3&gt;Hardware&amp;nbsp;Requirements&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Minimum&lt;/th&gt;
&lt;th&gt;Recommended&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1 core (&lt;span class="caps"&gt;ARM&lt;/span&gt; or x86)&lt;/td&gt;
&lt;td&gt;2 cores&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;256 &lt;span class="caps"&gt;MB&lt;/span&gt; free&lt;/td&gt;
&lt;td&gt;512 &lt;span class="caps"&gt;MB&lt;/span&gt; free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Disk&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;500 &lt;span class="caps"&gt;MB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;2 &lt;span class="caps"&gt;GB&lt;/span&gt; (for history)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Network&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Any&lt;/td&gt;
&lt;td&gt;Dedicated &lt;span class="caps"&gt;VLAN&lt;/span&gt; for monitoring traffic&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Software&amp;nbsp;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Docker Engine&lt;/strong&gt; 24.x+ and &lt;strong&gt;Docker Compose&lt;/strong&gt;&amp;nbsp;v2+&lt;/li&gt;
&lt;li&gt;A Linux host — any distribution that runs Docker (Debian 12, Ubuntu 24.04, Proxmox &lt;span class="caps"&gt;LXC&lt;/span&gt;, Raspberry Pi &lt;span class="caps"&gt;OS&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;Optional but recommended: a reverse proxy (&lt;a href="/2026/06/nginx-proxy-manager-docker-compose/"&gt;Nginx Proxy Manager&lt;/a&gt; or &lt;a href="/2026/06/traefik-vs-nginx-proxy-manager-vs-caddy-homelab-2026/"&gt;Traefik&lt;/a&gt;) for &lt;span class="caps"&gt;HTTPS&lt;/span&gt;&amp;nbsp;access&lt;/li&gt;
&lt;li&gt;Optional: a &lt;a href="/2026/06/cloudflare-tunnel-homelab/"&gt;Cloudflare Tunnel&lt;/a&gt; if you want to expose your status page publicly without opening&amp;nbsp;ports&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Services You Will&amp;nbsp;Monitor&lt;/h3&gt;
&lt;p&gt;This guide assumes you have at least five homelab services running. Examples used&amp;nbsp;throughout:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Nextcloud&lt;/strong&gt; — &lt;span class="caps"&gt;HTTP&lt;/span&gt; monitor on port&amp;nbsp;8443&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Jellyfin&lt;/strong&gt; — &lt;span class="caps"&gt;HTTP&lt;/span&gt; monitor on port&amp;nbsp;8096&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pi-hole&lt;/strong&gt; — &lt;span class="caps"&gt;DNS&lt;/span&gt; monitor on port&amp;nbsp;53&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Portainer&lt;/strong&gt; — &lt;span class="caps"&gt;HTTP&lt;/span&gt; monitor on port&amp;nbsp;9443&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Home Assistant&lt;/strong&gt; — &lt;span class="caps"&gt;HTTP&lt;/span&gt; monitor on port&amp;nbsp;8123&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you do not have these specific services, the monitor types and configuration patterns apply to any service in your&amp;nbsp;stack.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Project&amp;nbsp;Structure&lt;/h2&gt;
&lt;p&gt;Create a clean directory for Uptime Kuma. Keeping it alongside your other Docker Compose stacks makes backups&amp;nbsp;straightforward.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;~/&lt;/span&gt;&lt;span class="nv"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;uptime&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;kuma&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
├──&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;compose&lt;/span&gt;.&lt;span class="nv"&gt;yml&lt;/span&gt;
├──&lt;span class="w"&gt; &lt;/span&gt;.&lt;span class="nv"&gt;env&lt;/span&gt;
└──&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;data&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;auto&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;created&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;by&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Docker&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;data/&lt;/code&gt; directory holds the SQLite database, uploaded monitor screenshots, and notification credentials. Back this&amp;nbsp;up.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The Docker Compose&amp;nbsp;Configuration&lt;/h2&gt;
&lt;h3&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This is the production-ready Compose file. It pins the Uptime Kuma version&amp;nbsp;(not &lt;code&gt;latest&lt;/code&gt;), mounts a persistent volume, sets resource limits, and includes a healthcheck so Docker itself knows whether the container is&amp;nbsp;healthy.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;uptime-kuma&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;louislam/uptime-kuma:1&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;uptime-kuma&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3001:3001&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./data:/app/data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TZ=${TZ:-Asia/Jakarta}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;healthcheck&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;CMD&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;extra/healthcheck&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;30s&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;10s&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;retries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;3&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;start_period&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;10s&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;512M&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;reservations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;128M&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Uncomment if you use a shared Docker network for reverse proxy&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# networks:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#   - proxy_network&lt;/span&gt;

&lt;span class="c1"&gt;# Uncomment if using a shared reverse proxy network&lt;/span&gt;
&lt;span class="c1"&gt;# networks:&lt;/span&gt;
&lt;span class="c1"&gt;#   proxy_network:&lt;/span&gt;
&lt;span class="c1"&gt;#     external: true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Why&amp;nbsp;version &lt;code&gt;1&lt;/code&gt; and&amp;nbsp;not &lt;code&gt;latest&lt;/code&gt;?&lt;/strong&gt; Pinning to the major version&amp;nbsp;(&lt;code&gt;1&lt;/code&gt;) means you get patch updates&amp;nbsp;(&lt;code&gt;1.23.x&lt;/code&gt;) automatically without risking a breaking v2 migration. When Uptime Kuma v2 is released, you will evaluate the changelog before upgrading — not wake up to a broken monitoring&amp;nbsp;stack.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;.env&lt;/code&gt; File&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;#&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Uptime&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Kuma&lt;/span&gt;
&lt;span class="nv"&gt;TZ&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;Asia&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;Jakarta&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Keep it simple. The timezone ensures all timestamps, maintenance windows, and notification schedules align with your local&amp;nbsp;time.&lt;/p&gt;
&lt;h3&gt;Optional: Docker Socket for Container&amp;nbsp;Monitoring&lt;/h3&gt;
&lt;p&gt;If you want Uptime Kuma to monitor Docker containers directly (checking container health status from the Docker daemon), mount the Docker socket as&amp;nbsp;read-only:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./data:/app/data&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/var/run/docker.sock:/var/run/docker.sock:ro&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Security note:&lt;/strong&gt; Mounting the Docker socket gives the container access to the Docker &lt;span class="caps"&gt;API&lt;/span&gt;. In a homelab this is generally acceptable, but understand the trade-off: any process with access&amp;nbsp;to &lt;code&gt;docker.sock&lt;/code&gt; can start, stop, or inspect any container on the&amp;nbsp;host.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step-by-Step&amp;nbsp;Installation&lt;/h2&gt;
&lt;h3&gt;Step 1: Create the Project Directory and&amp;nbsp;Files&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;~/docker/uptime-kuma
&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/docker/uptime-kuma

&lt;span class="c1"&gt;# Create the .env file&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;TZ=Asia/Jakarta&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;.env

&lt;span class="c1"&gt;# Create docker-compose.yml with the content above&lt;/span&gt;
nano&lt;span class="w"&gt; &lt;/span&gt;docker-compose.yml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Step 2: Start the&amp;nbsp;Container&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Verify it is&amp;nbsp;running:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;ps
&lt;span class="c1"&gt;# Should show uptime-kuma as &amp;quot;Up&amp;quot; and &amp;quot;(healthy)&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Step 3: Complete First-Run&amp;nbsp;Setup&lt;/h3&gt;
&lt;p&gt;Open &lt;code&gt;http://&amp;lt;your-server-ip&amp;gt;:3001&lt;/code&gt; in your browser. The first-run wizard asks you&amp;nbsp;to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Create an admin account&lt;/strong&gt; — username, password (use a password manager — you will not log in often, but losing this account means losing access to your monitoring&amp;nbsp;dashboard)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enable &lt;span class="caps"&gt;2FA&lt;/span&gt;&lt;/strong&gt; (optional but recommended if your dashboard is accessible outside your &lt;span class="caps"&gt;LAN&lt;/span&gt;) — Uptime Kuma supports &lt;span class="caps"&gt;TOTP&lt;/span&gt;-based two-factor&amp;nbsp;authentication&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Set a custom page title&lt;/strong&gt; — call it &amp;#8220;Homelab Status&amp;#8221; or your domain&amp;nbsp;name&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Missing your server &lt;span class="caps"&gt;IP&lt;/span&gt;?&lt;/strong&gt; If you deployed on &lt;a href="/2026/06/proxmox-beginner-guide/"&gt;Proxmox&lt;/a&gt;, use the container/&lt;span class="caps"&gt;LXC&lt;/span&gt; &lt;span class="caps"&gt;IP&lt;/span&gt;. If on bare metal,&amp;nbsp;use &lt;code&gt;ip addr show&lt;/code&gt; to find&amp;nbsp;it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Step 4: Add Your First&amp;nbsp;Monitor&lt;/h3&gt;
&lt;p&gt;Click &lt;strong&gt;&amp;#8220;Add New Monitor&amp;#8221;&lt;/strong&gt; and fill&amp;nbsp;in:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Example Value&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Monitor Type&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;HTTP&lt;/span&gt;(s)&lt;/td&gt;
&lt;td&gt;Most homelab services use &lt;span class="caps"&gt;HTTP&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Friendly Name&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Nextcloud&lt;/td&gt;
&lt;td&gt;Display name on your dashboard&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;URL&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://nextcloud.homelab.local&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Full &lt;span class="caps"&gt;URL&lt;/span&gt;,&amp;nbsp;including &lt;code&gt;https://&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Heartbeat Interval&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;60 seconds&lt;/td&gt;
&lt;td&gt;60s is fine for most services&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Retries&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Avoids false positives from transient blips&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Resend Notification&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0 (every down event)&lt;/td&gt;
&lt;td&gt;You want to know every time it goes down&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Max Redirects&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;Most homelab services should not redirect&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Accepted Status Codes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;td&gt;Optional; tighten to expected codes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Click &lt;strong&gt;Save&lt;/strong&gt;. The monitor appears on your dashboard. It runs its first check within 60 seconds. A green heart means your service is reachable. A red heart means it is not — and if you have configured notifications, you will know&amp;nbsp;immediately.&lt;/p&gt;
&lt;h3&gt;Step 5: Configure Notification&amp;nbsp;Channels&lt;/h3&gt;
&lt;p&gt;A monitor without an alert is a log entry you will never read. Uptime Kuma supports over 60 notification channels. Here are the four most useful for homelab&amp;nbsp;owners:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Channel&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;Setup Complexity&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Telegram&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Instant push notifications to your phone&lt;/td&gt;
&lt;td&gt;Low — needs bot token + chat &lt;span class="caps"&gt;ID&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Discord&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Sharing alerts with a homelab community or family server&lt;/td&gt;
&lt;td&gt;Low — needs webhook &lt;span class="caps"&gt;URL&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Email (&lt;span class="caps"&gt;SMTP&lt;/span&gt;)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Reliable fallback when chat services are down&lt;/td&gt;
&lt;td&gt;Medium — needs &lt;span class="caps"&gt;SMTP&lt;/span&gt; server credentials&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ntfy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Self-hosted push notifications, zero reliance on third parties&lt;/td&gt;
&lt;td&gt;Medium — needs ntfy server &lt;span class="caps"&gt;URL&lt;/span&gt; + topic&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Setting up&amp;nbsp;Telegram:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Message &lt;code&gt;@BotFather&lt;/code&gt; on Telegram and create a bot&amp;nbsp;with &lt;code&gt;/newbot&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Copy the bot token (looks&amp;nbsp;like &lt;code&gt;123456:ABC-DEF1234ghikl...&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Send a message to your bot, then&amp;nbsp;visit &lt;code&gt;https://api.telegram.org/bot&amp;lt;TOKEN&amp;gt;/getUpdates&lt;/code&gt; to find your chat &lt;span class="caps"&gt;ID&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;In Uptime Kuma: &lt;strong&gt;Settings → Notifications → Setup Notification →&amp;nbsp;Telegram&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Paste the bot token and chat &lt;span class="caps"&gt;ID&lt;/span&gt;, click &lt;strong&gt;Test&lt;/strong&gt;, and confirm you receive the test&amp;nbsp;message&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Setting up&amp;nbsp;Discord:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;In your Discord server: &lt;strong&gt;Server Settings → Integrations → Webhooks → New&amp;nbsp;Webhook&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Copy the webhook &lt;span class="caps"&gt;URL&lt;/span&gt; (looks&amp;nbsp;like &lt;code&gt;https://discord.com/api/webhooks/...&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;In Uptime Kuma: &lt;strong&gt;Settings → Notifications → Setup Notification →&amp;nbsp;Discord&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Paste the webhook &lt;span class="caps"&gt;URL&lt;/span&gt;, click &lt;strong&gt;Test&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Step 6: Create a Public Status&amp;nbsp;Page&lt;/h3&gt;
&lt;p&gt;A public status page lets your family (or users, if you share services) check the health of your homelab without accessing the admin dashboard. It is a read-only, beautifully branded page you can host&amp;nbsp;at &lt;code&gt;status.yourdomain.com&lt;/code&gt;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Settings → Status Page → New Status&amp;nbsp;Page&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Give it a name and a slug&amp;nbsp;(e.g., &lt;code&gt;homelab&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pick which monitors appear&lt;/strong&gt; — select the services your family cares about (Jellyfin, Home Assistant) but not internal-only ones (database, Docker&amp;nbsp;socket)&lt;/li&gt;
&lt;li&gt;Customize the footer with your domain, a logo, and a custom message (&amp;#8220;Having trouble? Message me on&amp;nbsp;Signal.&amp;#8221;)&lt;/li&gt;
&lt;li&gt;Copy the generated &lt;span class="caps"&gt;URL&lt;/span&gt; slug. If reverse proxy is configured, this&amp;nbsp;becomes &lt;code&gt;https://status.yourdomain.com&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;No reverse proxy yet?&lt;/strong&gt; The status page &lt;span class="caps"&gt;URL&lt;/span&gt; will&amp;nbsp;be &lt;code&gt;http://&amp;lt;server-ip&amp;gt;:3001/status/homelab&lt;/code&gt;. Jump to the &lt;a href="#reverse-proxy-integration"&gt;Reverse Proxy Integration&lt;/a&gt; section to make it accessible at a clean domain with &lt;span class="caps"&gt;HTTPS&lt;/span&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Step 7: Add Maintenance&amp;nbsp;Windows&lt;/h3&gt;
&lt;p&gt;When you take Jellyfin down to add a new hard drive, you do not want Uptime Kuma spamming notifications. Maintenance windows suppress alerts on a&amp;nbsp;schedule.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Settings → Maintenance → Add Maintenance Window&lt;/strong&gt;, select the affected monitors, set the start/end time, and save. Notifications pause during the window but uptime checks continue — so you can see the downtime in your history without the&amp;nbsp;noise.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Monitor Types &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; Decision&amp;nbsp;Matrix&lt;/h2&gt;
&lt;p&gt;Uptime Kuma supports eight monitor types. Choosing the right one for each service is the difference between meaningful alerts and&amp;nbsp;noise.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Monitor Type&lt;/th&gt;
&lt;th&gt;Protocol&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;HTTP&lt;/span&gt;(s)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;HTTP&lt;/span&gt;/&lt;span class="caps"&gt;HTTPS&lt;/span&gt; &lt;span class="caps"&gt;GET&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Web services, APIs, dashboards&lt;/td&gt;
&lt;td&gt;&lt;a href="/2026/06/nextcloud-docker-compose/"&gt;Nextcloud&lt;/a&gt;, &lt;a href="/2026/06/portainer-setup-guide/"&gt;Portainer&lt;/a&gt;, &lt;a href="/2026/06/self-hosted-media-server-jellyfin-plex-emby/"&gt;Jellyfin&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;TCP&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Raw &lt;span class="caps"&gt;TCP&lt;/span&gt; connect&lt;/td&gt;
&lt;td&gt;Databases, game servers, mail servers&lt;/td&gt;
&lt;td&gt;MySQL (3306), Minecraft (25565), &lt;span class="caps"&gt;SMTP&lt;/span&gt; (25)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ping&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;ICMP&lt;/span&gt; Echo&lt;/td&gt;
&lt;td&gt;Network devices, bare-metal servers&lt;/td&gt;
&lt;td&gt;Router (192.168.1.1), &lt;span class="caps"&gt;NAS&lt;/span&gt;, managed switch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt; query&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt; servers, ad-blockers&lt;/td&gt;
&lt;td&gt;&lt;a href="/2026/06/pihole-unbound-dns/"&gt;Pi-hole&lt;/a&gt;&amp;nbsp;(query &lt;code&gt;google.com&lt;/code&gt; against 192.168.1.2:53)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Docker&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Docker socket &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Container health checks&lt;/td&gt;
&lt;td&gt;Any container with a healthcheck defined in its Compose file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Push&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Inbound &lt;span class="caps"&gt;HTTP&lt;/span&gt; (passive)&lt;/td&gt;
&lt;td&gt;Cron jobs, backup scripts&lt;/td&gt;
&lt;td&gt;Nightly &lt;code&gt;borg backup&lt;/code&gt; script pushes a heartbeat when it completes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;MQTT&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;MQTT&lt;/span&gt; topic&lt;/td&gt;
&lt;td&gt;IoT devices, sensor data&lt;/td&gt;
&lt;td&gt;Temperature sensor publishes&amp;nbsp;to &lt;code&gt;homelab/sensors/temp&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;gRPC&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;gRPC health check&lt;/td&gt;
&lt;td&gt;Microservices&lt;/td&gt;
&lt;td&gt;Custom gRPC health probe endpoints&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Decision Matrix: Which Monitor for Which&amp;nbsp;Service?&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Your Service&lt;/th&gt;
&lt;th&gt;Use This Monitor&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Web app (Nextcloud, Jellyfin, Portainer, Home Assistant)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;HTTP&lt;/span&gt;(s)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Verifies the web server responds with the expected status code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database (PostgreSQL, MySQL, Redis)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;TCP&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Confirms the port is open and accepting connections without needing to authenticate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Router, switch, access point&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Ping&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Simplest network-layer check — does the device respond to &lt;span class="caps"&gt;ICMP&lt;/span&gt;?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pi-hole, AdGuard Home, Unbound&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Verifies &lt;span class="caps"&gt;DNS&lt;/span&gt; resolution works, not just that port 53 is open&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Docker container with healthcheck&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Docker&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Reads container health status directly from Docker daemon — more accurate than a port check&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nightly backup script, log rotation cron&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Push&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The script calls a unique Uptime Kuma &lt;span class="caps"&gt;URL&lt;/span&gt; after success; if the &lt;span class="caps"&gt;URL&lt;/span&gt; is not called within the window, Uptime Kuma alerts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;MQTT&lt;/span&gt; sensor (Zigbee2MQTT, ESPHome)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;MQTT&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Watches for a heartbeat message on a topic&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Reverse Proxy&amp;nbsp;Integration&lt;/h2&gt;
&lt;p&gt;Accessing Uptime Kuma&amp;nbsp;on &lt;code&gt;http://192.168.1.50:3001&lt;/code&gt; works — until your browser marks it &amp;#8220;Not Secure&amp;#8221; and refuses to save your password. A reverse proxy gives&amp;nbsp;you &lt;code&gt;https://uptime.yourdomain.com&lt;/code&gt; with automatic &lt;span class="caps"&gt;SSL&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;Option 1: Nginx Proxy&amp;nbsp;Manager&lt;/h3&gt;
&lt;p&gt;If you already use &lt;a href="/2026/06/nginx-proxy-manager-docker-compose/"&gt;Nginx Proxy Manager&lt;/a&gt;, this takes 30&amp;nbsp;seconds:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Log into &lt;span class="caps"&gt;NPM&lt;/span&gt;&amp;nbsp;at &lt;code&gt;https://npm.yourdomain.com:81&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hosts → Proxy Hosts → Add Proxy&amp;nbsp;Host&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Fill&amp;nbsp;in:&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Domain&amp;nbsp;Names:&lt;/strong&gt; &lt;code&gt;uptime.yourdomain.com&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Forward Hostname / &lt;span class="caps"&gt;IP&lt;/span&gt;:&lt;/strong&gt; &lt;code&gt;uptime-kuma&lt;/code&gt; (the container name, if on the same Docker network)&amp;nbsp;or &lt;code&gt;192.168.1.50&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Forward&amp;nbsp;Port:&lt;/strong&gt; &lt;code&gt;3001&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Websocket Support:&lt;/strong&gt; ✅ Enable (Uptime Kuma uses WebSockets for real-time dashboard&amp;nbsp;updates)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;SSL&lt;/span&gt; tab →&lt;/strong&gt; select &amp;#8220;Request a new &lt;span class="caps"&gt;SSL&lt;/span&gt; Certificate,&amp;#8221; check &amp;#8220;Force &lt;span class="caps"&gt;SSL&lt;/span&gt;&amp;#8221; and &amp;#8220;&lt;span class="caps"&gt;HTTP&lt;/span&gt;/2&amp;nbsp;Support&amp;#8221;&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Save&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Your dashboard is now&amp;nbsp;at &lt;code&gt;https://uptime.yourdomain.com&lt;/code&gt; with a valid Let&amp;#8217;s Encrypt&amp;nbsp;certificate.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For the status page&lt;/strong&gt;, add a second proxy&amp;nbsp;host: &lt;code&gt;status.yourdomain.com&lt;/code&gt; → same backend&amp;nbsp;(&lt;code&gt;uptime-kuma:3001&lt;/code&gt;). In Uptime Kuma, configure the status page slug&amp;nbsp;to &lt;code&gt;homelab&lt;/code&gt;. Visitors&amp;nbsp;to &lt;code&gt;https://status.yourdomain.com&lt;/code&gt; see a dedicated read-only status&amp;nbsp;page.&lt;/p&gt;
&lt;h3&gt;Option 2:&amp;nbsp;Traefik&lt;/h3&gt;
&lt;p&gt;If you use &lt;a href="/2026/06/traefik-vs-nginx-proxy-manager-vs-caddy-homelab-2026/"&gt;Traefik&lt;/a&gt;, add these labels to&amp;nbsp;your &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.enable=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.uptimekuma.rule=Host(`uptime.yourdomain.com`)&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.uptimekuma.entrypoints=websecure&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.uptimekuma.tls.certresolver=letsencrypt&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.services.uptimekuma.loadbalancer.server.port=3001&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The dashboard appears&amp;nbsp;at &lt;code&gt;https://uptime.yourdomain.com&lt;/code&gt; with automatic &lt;span class="caps"&gt;TLS&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;Option 3: Cloudflare Tunnel (Zero Port&amp;nbsp;Forwarding)&lt;/h3&gt;
&lt;p&gt;If you do not want to open any ports on your router, use a &lt;a href="/2026/06/cloudflare-tunnel-homelab/"&gt;Cloudflare Tunnel&lt;/a&gt; to expose the status page publicly. Add this ingress rule to&amp;nbsp;your &lt;code&gt;config.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;ingress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;status.yourdomain.com&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;http://uptime-kuma:3001&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;http_status:404&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Security tip:&lt;/strong&gt; Only expose the status page&amp;nbsp;(&lt;code&gt;status.yourdomain.com&lt;/code&gt;), not the admin dashboard&amp;nbsp;(&lt;code&gt;uptime.yourdomain.com&lt;/code&gt;). Add a Cloudflare Access policy to the admin dashboard subdomain for an extra authentication&amp;nbsp;layer.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;Watch the Watcher&amp;#8221; — Healthchecks.io&amp;nbsp;Integration&lt;/h2&gt;
&lt;p&gt;Here is the problem with self-hosted monitoring: when your Docker host crashes, Uptime Kuma crashes with it. You get no alert because the tool that sends alerts is also dead. This is the &lt;strong&gt;&amp;#8220;who watches the watcher&amp;#8221; problem&lt;/strong&gt;, and the solution is a dead man&amp;#8217;s&amp;nbsp;switch.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://healthchecks.io"&gt;Healthchecks.io&lt;/a&gt; is a free service (open-source, self-hostable) that expects a periodic &lt;span class="caps"&gt;HTTP&lt;/span&gt; request — a heartbeat — from your monitored service. If the heartbeat does not arrive within a configured grace period, Healthchecks.io sends you an alert. It works even when your entire homelab is offline because Healthchecks.io runs outside your&amp;nbsp;infrastructure.&lt;/p&gt;
&lt;h3&gt;Setup (5&amp;nbsp;Minutes)&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Create a free Healthchecks.io account&lt;/strong&gt; at &lt;a href="https://healthchecks.io"&gt;healthchecks.io&lt;/a&gt; — the free tier includes 20&amp;nbsp;checks&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Create a new check&lt;/strong&gt; → name it &amp;#8220;Uptime Kuma Heartbeat,&amp;#8221; set grace period to 5 minutes, set schedule to &amp;#8220;&lt;em&gt;/5 * * * &lt;/em&gt;&amp;#8221; (every 5&amp;nbsp;minutes)&lt;/li&gt;
&lt;li&gt;Copy the &lt;strong&gt;Ping &lt;span class="caps"&gt;URL&lt;/span&gt;&lt;/strong&gt; — it looks&amp;nbsp;like &lt;code&gt;https://hc-ping.com/&amp;lt;uuid&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;The Heartbeat Cron&amp;nbsp;Job&lt;/h3&gt;
&lt;p&gt;On a &lt;strong&gt;secondary device&lt;/strong&gt; — a &lt;a href="/2026/06/best-vps-for-homelab/"&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt;&lt;/a&gt;, a Raspberry Pi Zero, or even your always-on desktop — create a cron job that hits the Uptime Kuma health&amp;nbsp;endpoint:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Run every 5 minutes — verifies Uptime Kuma is responding&lt;/span&gt;
*/5&lt;span class="w"&gt; &lt;/span&gt;*&lt;span class="w"&gt; &lt;/span&gt;*&lt;span class="w"&gt; &lt;/span&gt;*&lt;span class="w"&gt; &lt;/span&gt;*&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;/dev/null&lt;span class="w"&gt; &lt;/span&gt;-w&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;%{http_code}&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;https://uptime.yourdomain.com/api/status-page/heartbeat/homelab&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-q&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;200&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-fsS&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;/dev/null&lt;span class="w"&gt; &lt;/span&gt;https://hc-ping.com/&amp;lt;uuid&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;What this&amp;nbsp;does:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Every 5 minutes, the cron job hits your Uptime Kuma status page &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;If the response is &lt;span class="caps"&gt;HTTP&lt;/span&gt; 200 (Uptime Kuma is alive), it pings&amp;nbsp;Healthchecks.io&lt;/li&gt;
&lt;li&gt;If the response is anything else (Uptime Kuma is down or unreachable), Healthchecks.io receives no&amp;nbsp;ping&lt;/li&gt;
&lt;li&gt;Healthchecks.io waits the 5-minute grace period, then sends you an alert via email, Telegram, Discord, or any of its dozen notification&amp;nbsp;channels&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The key is running this cron job &lt;strong&gt;outside&lt;/strong&gt; the infrastructure Uptime Kuma is monitoring. If your homelab loses power, the &lt;span class="caps"&gt;VPS&lt;/span&gt; that runs this cron job is unaffected, and you get the&amp;nbsp;alert.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Self-hosting Healthchecks.io:&lt;/strong&gt; You can deploy your own instance via Docker Compose. See the &lt;a href="https://healthchecks.io/docs/self_hosted_docker/"&gt;Healthchecks.io Docker deployment guide&lt;/a&gt; for the Compose file. This keeps everything self-hosted while the watcher sits on a separate &lt;span class="caps"&gt;VPS&lt;/span&gt; or a friend&amp;#8217;s&amp;nbsp;homelab.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;Updating &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;Maintenance&lt;/h2&gt;
&lt;h3&gt;How to Update Uptime&amp;nbsp;Kuma&lt;/h3&gt;
&lt;p&gt;Uptime Kuma releases frequently. Updating is a two-command&amp;nbsp;process:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/docker/uptime-kuma
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;pull&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="c1"&gt;# Pull the latest 1.x image&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Recreate the container with the new image&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Uptime Kuma runs database migrations automatically on startup. The process takes under 10 seconds and your monitor history is&amp;nbsp;preserved.&lt;/p&gt;
&lt;h3&gt;Backup&amp;nbsp;Strategy&lt;/h3&gt;
&lt;p&gt;The entire state of Uptime Kuma — monitors, notifications, status pages, settings — lives&amp;nbsp;in &lt;code&gt;./data/kuma.db&lt;/code&gt; (the SQLite database). Back this&amp;nbsp;up.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Simple backup with&amp;nbsp;tar:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Run this before updates or on a cron schedule&lt;/span&gt;
tar&lt;span class="w"&gt; &lt;/span&gt;-czf&lt;span class="w"&gt; &lt;/span&gt;uptime-kuma-backup-&lt;span class="k"&gt;$(&lt;/span&gt;date&lt;span class="w"&gt; &lt;/span&gt;+%Y%m%d&lt;span class="k"&gt;)&lt;/span&gt;.tar.gz&lt;span class="w"&gt; &lt;/span&gt;~/docker/uptime-kuma/data/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Restore:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/docker/uptime-kuma
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;down
tar&lt;span class="w"&gt; &lt;/span&gt;-xzf&lt;span class="w"&gt; &lt;/span&gt;uptime-kuma-backup-20260607.tar.gz&lt;span class="w"&gt; &lt;/span&gt;-C&lt;span class="w"&gt; &lt;/span&gt;/
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Version Pinning&amp;nbsp;Policy&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Strategy&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;th&gt;When to Use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;louislam/uptime-kuma:1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Auto-updates within v1.x&lt;/td&gt;
&lt;td&gt;Production homelab — stable, gets patches&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;louislam/uptime-kuma:latest&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Always the newest release&lt;/td&gt;
&lt;td&gt;Testing/lab only — may include breaking changes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;louislam/uptime-kuma:1.23.13&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Exact version pin&lt;/td&gt;
&lt;td&gt;Mission-critical deployments — full control&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code&gt;:1&lt;/code&gt; tag used in this guide is the sweet spot: you get security patches and bug fixes automatically, but you will never wake up to a v2 migration without opting&amp;nbsp;in.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Troubleshooting Common&amp;nbsp;Issues&lt;/h2&gt;
&lt;h3&gt;Monitors Show &amp;#8220;Down&amp;#8221; but the Service is Actually&amp;nbsp;Reachable&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Likely cause:&lt;/strong&gt; Network isolation. Uptime Kuma runs in a Docker container with its own network namespace. If your monitored services are on a different Docker network, &lt;span class="caps"&gt;VLAN&lt;/span&gt;, or host interface, Uptime Kuma cannot reach&amp;nbsp;them.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Ensure Uptime Kuma is on the same Docker network as the monitored services, or use the host&amp;#8217;s &lt;span class="caps"&gt;IP&lt;/span&gt; address&amp;nbsp;(&lt;code&gt;192.168.1.50&lt;/code&gt;) instead&amp;nbsp;of &lt;code&gt;localhost&lt;/code&gt; or container&amp;nbsp;names.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Add Uptime Kuma to your existing proxy/traefik network&lt;/span&gt;
&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;proxy_network&lt;/span&gt;

&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;proxy_network&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;external&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Notifications Not&amp;nbsp;Firing&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Click &amp;#8220;Test&amp;#8221;&lt;/strong&gt; on the notification configuration — if the test fails, the credentials are&amp;nbsp;wrong&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Check the monitor&amp;#8217;s notification assignment&lt;/strong&gt; — a monitor must have at least one notification channel assigned in its&amp;nbsp;settings&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Check rate limits&lt;/strong&gt; — Telegram limits bots to ~30 messages/second; Discord has per-webhook rate limits. If you have 50 monitors all going down simultaneously, some notifications may be&amp;nbsp;throttled&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Verify the notification condition&lt;/strong&gt; — by default, Uptime Kuma notifies on every status change. If you have &amp;#8220;Resend Notification&amp;#8221; set to a high number, you may be waiting for the resend&amp;nbsp;interval&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Status Page Not Loading&amp;nbsp;Publicly&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Reverse proxy misconfiguration&lt;/strong&gt; — the status page &lt;span class="caps"&gt;URL&lt;/span&gt; in Uptime Kuma must match the external &lt;span class="caps"&gt;URL&lt;/span&gt;. In Settings → Status Page, the &amp;#8220;Domain&amp;#8221; field should&amp;nbsp;be &lt;code&gt;https://status.yourdomain.com&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WebSocket blocked&lt;/strong&gt; — status pages use WebSockets for live updates. If your reverse proxy strips WebSocket headers, the page loads but never updates. Enable WebSocket support in &lt;span class="caps"&gt;NPM&lt;/span&gt; or&amp;nbsp;Traefik&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cloudflare proxy cache&lt;/strong&gt; — if you proxy through Cloudflare (orange cloud), ensure the status page subdomain has caching disabled (set to &amp;#8220;Bypass&amp;#8221; in Page&amp;nbsp;Rules)&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;High &lt;span class="caps"&gt;CPU&lt;/span&gt;&amp;nbsp;Usage&lt;/h3&gt;
&lt;p&gt;Uptime Kuma normally consumes under 1% &lt;span class="caps"&gt;CPU&lt;/span&gt;. If you see sustained &lt;span class="caps"&gt;CPU&lt;/span&gt;&amp;nbsp;spikes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Too many monitors on too short an interval&lt;/strong&gt; — 200 &lt;span class="caps"&gt;HTTP&lt;/span&gt; monitors at 20-second intervals is 600 requests/minute. Increase the interval to 60 or 120&amp;nbsp;seconds&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Certificate expiry checks on all monitors&lt;/strong&gt; — this is a host-level integration, not per-monitor. Enable it once in Settings → Monitoring → &amp;#8220;Certificate Expiry&amp;nbsp;Notification&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Browser dashboard open 24/7&lt;/strong&gt; — the dashboard uses WebSockets and real-time chart rendering. Close the browser tab when not actively&amp;nbsp;monitoring&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;&lt;span class="caps"&gt;FAQ&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Q: Can Uptime Kuma monitor services on another &lt;span class="caps"&gt;VLAN&lt;/span&gt;?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Yes, as long as the Docker host can route to that &lt;span class="caps"&gt;VLAN&lt;/span&gt;. If your Docker host sits on the management &lt;span class="caps"&gt;VLAN&lt;/span&gt; (192.168.1.0/24) and your IoT &lt;span class="caps"&gt;VLAN&lt;/span&gt; is 192.168.100.0/24, Uptime Kuma can monitor devices on the IoT &lt;span class="caps"&gt;VLAN&lt;/span&gt; — provided inter-&lt;span class="caps"&gt;VLAN&lt;/span&gt; routing is allowed. See our &lt;a href="/2026/06/homelab-networking-basics/"&gt;homelab networking guide&lt;/a&gt; for &lt;span class="caps"&gt;VLAN&lt;/span&gt;&amp;nbsp;setup.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: How many monitors can I run on a Raspberry Pi&amp;nbsp;4?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Approximately 200 monitors at 60-second intervals before you notice &lt;span class="caps"&gt;CPU&lt;/span&gt; impact. Uptime Kuma is remarkably lightweight — each &lt;span class="caps"&gt;HTTP&lt;/span&gt; check is a&amp;nbsp;single &lt;code&gt;fetch()&lt;/code&gt; call.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: Does Uptime Kuma support &lt;span class="caps"&gt;SNMP&lt;/span&gt; for switch&amp;nbsp;monitoring?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Not natively as of version 1.x. For &lt;span class="caps"&gt;SNMP&lt;/span&gt; monitoring of managed switches, pair Uptime Kuma with &lt;a href="/2026/06/grafana-prometheus-setup/"&gt;Prometheus + &lt;span class="caps"&gt;SNMP&lt;/span&gt; Exporter&lt;/a&gt;. Use Uptime Kuma&amp;#8217;s Ping monitor for basic switch&amp;nbsp;reachability.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: Can I run Uptime Kuma behind Authelia or Authentik &lt;span class="caps"&gt;SSO&lt;/span&gt;?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Yes. Place the &lt;span class="caps"&gt;SSO&lt;/span&gt; middleware in your reverse proxy layer, not in Uptime Kuma itself. In &lt;span class="caps"&gt;NPM&lt;/span&gt;, configure a custom location that requires Authelia authentication before proxying to port 3001. In Traefik, add&amp;nbsp;the &lt;code&gt;traefik.http.routers.uptimekuma.middlewares=authelia@file&lt;/code&gt; label.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: What is the difference between Uptime Kuma and&amp;nbsp;Prometheus?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Uptime Kuma tells you &lt;strong&gt;if&lt;/strong&gt; a service is up. Prometheus tells you &lt;strong&gt;how&lt;/strong&gt; the service is performing. They answer different questions. Uptime Kuma is binary (up/down) and lightweight. Prometheus collects numeric metrics (&lt;span class="caps"&gt;CPU&lt;/span&gt; usage, request latency, disk I/O) over time and requires more resources. The two work together — Uptime Kuma for immediate outage detection, Prometheus for capacity planning and performance&amp;nbsp;optimization.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: How do I monitor my &lt;span class="caps"&gt;VPS&lt;/span&gt; from my&amp;nbsp;homelab?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Add a &lt;span class="caps"&gt;TCP&lt;/span&gt; monitor for &lt;span class="caps"&gt;SSH&lt;/span&gt; (port 22) and an &lt;span class="caps"&gt;HTTP&lt;/span&gt;(s) monitor for any web services running on the &lt;span class="caps"&gt;VPS&lt;/span&gt;. If the &lt;span class="caps"&gt;VPS&lt;/span&gt; has a public domain,&amp;nbsp;monitor &lt;code&gt;https://status.yourdomain.com&lt;/code&gt; from your homelab&amp;#8217;s Uptime Kuma. For the reverse — monitoring your homelab from your &lt;span class="caps"&gt;VPS&lt;/span&gt; — run a second Uptime Kuma instance on the &lt;span class="caps"&gt;VPS&lt;/span&gt; or use the Healthchecks.io pattern described&amp;nbsp;above.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; Next&amp;nbsp;Steps&lt;/h2&gt;
&lt;p&gt;You now have a production-ready Uptime Kuma deployment that monitors your entire homelab, alerts you via Telegram or Discord when something breaks, shows a public status page your family can check, and keeps itself honest with a Healthchecks.io dead man&amp;#8217;s&amp;nbsp;switch.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What to do&amp;nbsp;next:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Add more monitors&lt;/strong&gt; — every service in&amp;nbsp;your &lt;code&gt;docker-compose.yml&lt;/code&gt; should have a corresponding monitor in Uptime&amp;nbsp;Kuma&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Set up a dashboard &lt;span class="caps"&gt;TV&lt;/span&gt;&lt;/strong&gt; — plug a cheap tablet or old monitor into a Raspberry Pi, open Uptime Kuma in full-screen kiosk mode, and mount it on the wall. Instant homelab nerve&amp;nbsp;center&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pair with metrics&lt;/strong&gt; — deploy &lt;a href="/2026/06/grafana-prometheus-setup/"&gt;Grafana and Prometheus&lt;/a&gt; for deep performance dashboards; Uptime Kuma handles &amp;#8220;is it up?&amp;#8221;, Grafana handles &amp;#8220;is it&amp;nbsp;healthy?&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Add a second Healthchecks.io check&lt;/strong&gt; — monitor the health of your reverse proxy, your router, and your &lt;span class="caps"&gt;ISP&lt;/span&gt; connection. A five-minute cron job on a $5 &lt;span class="caps"&gt;VPS&lt;/span&gt; can tell you the difference between &amp;#8220;Jellyfin crashed&amp;#8221; and &amp;#8220;your internet is&amp;nbsp;down&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Review your notification channels&lt;/strong&gt; — during a real outage at 3 &lt;span class="caps"&gt;AM&lt;/span&gt;, which channel will actually wake you up? Configure at least two channels (Telegram + Email) for critical&amp;nbsp;services&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The homelab monitoring journey does not end here — it starts here. Every new service you deploy should come with the question: &amp;#8220;How will I know when this breaks?&amp;#8221; And now you have the&amp;nbsp;answer.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What service will you monitor&amp;nbsp;first?&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Last updated: June 2026 — Uptime Kuma 1.x. Tested on Debian 12 with Docker&amp;nbsp;24+.&lt;/em&gt;&lt;/p&gt;</content><category term="Guides"/><category term="uptime-kuma"/><category term="docker"/><category term="docker-compose"/><category term="homelab"/><category term="self-hosted"/><category term="monitoring"/><category term="status-page"/><category term="notifications"/><category term="nginx-proxy-manager"/><category term="traefik"/><category term="portainer"/><category term="healthchecks"/><category term="alerting"/></entry><entry><title>Best NAS OS for Homelab 2026: TrueNAS vs Unraid vs OpenMediaVault vs Synology</title><link href="https://steadypub.com/2026/06/best-nas-os-homelab-2026/" rel="alternate"/><published>2026-06-06T14:00:00+07:00</published><updated>2026-06-06T14:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-06:/2026/06/best-nas-os-homelab-2026/</id><summary type="html">&lt;p&gt;Compare the four best &lt;span class="caps"&gt;NAS&lt;/span&gt; operating systems for homelab in 2026: TrueNAS 26, Unraid 7.3, OpenMediaVault 7, and Synology &lt;span class="caps"&gt;DSM&lt;/span&gt;. Covers cost, features, hardware requirements, and a decision tree to help you&amp;nbsp;choose.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~16 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab owners looking to build or buy a &lt;span class="caps"&gt;NAS&lt;/span&gt; for centralized storage
&lt;strong&gt;Prerequisites:&lt;/strong&gt; Basic familiarity with Linux and self-hosting&amp;nbsp;concepts&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why Your Homelab Needs a &lt;span class="caps"&gt;NAS&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;If you run a homelab with Docker containers, virtual machines, or media servers, centralized storage is not optional — it is the backbone of your setup. A dedicated &lt;span class="caps"&gt;NAS&lt;/span&gt; (Network Attached Storage) operating system gives&amp;nbsp;you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;One pool of storage&lt;/strong&gt; that every container, &lt;span class="caps"&gt;VM&lt;/span&gt;, and client on your network can access — no more juggling &lt;span class="caps"&gt;USB&lt;/span&gt; drives or resizing virtual&amp;nbsp;disks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Data redundancy&lt;/strong&gt; through &lt;span class="caps"&gt;RAID&lt;/span&gt;, &lt;span class="caps"&gt;ZFS&lt;/span&gt; mirrors, or parity arrays so a single drive failure does not wipe out your Plex library, Nextcloud files, or Immich photo&amp;nbsp;archive.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Snapshot and backup capabilities&lt;/strong&gt; built into the &lt;span class="caps"&gt;OS&lt;/span&gt; itself — schedule hourly snapshots, replicate to a second box, or push encrypted backups to Backblaze&amp;nbsp;B2.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;App hosting on the &lt;span class="caps"&gt;NAS&lt;/span&gt; itself&lt;/strong&gt; — most &lt;span class="caps"&gt;NAS&lt;/span&gt; &lt;span class="caps"&gt;OS&lt;/span&gt; options today ship with Docker or Kubernetes support, so you can run your services directly on the storage&amp;nbsp;box.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Without a &lt;span class="caps"&gt;NAS&lt;/span&gt;, every self-hosted app becomes its own storage island. With a &lt;span class="caps"&gt;NAS&lt;/span&gt;, your &lt;a href="https://steadypub.com/2026/06/docker-compose-for-beginners/"&gt;Docker Compose stacks&lt;/a&gt; mount shared volumes, your &lt;a href="https://steadypub.com/2026/06/proxmox-beginner-guide-2026/"&gt;Proxmox VMs&lt;/a&gt; pull disk images from &lt;span class="caps"&gt;NFS&lt;/span&gt; shares, and your &lt;a href="https://steadypub.com/2026/06/best-self-hosted-apps-2026/"&gt;self-hosted apps&lt;/a&gt; all read and write to the same redundant&amp;nbsp;pool.&lt;/p&gt;
&lt;p&gt;The question is not &lt;em&gt;whether&lt;/em&gt; you need a &lt;span class="caps"&gt;NAS&lt;/span&gt;. The question is: &lt;strong&gt;which &lt;span class="caps"&gt;NAS&lt;/span&gt; operating system fits your&amp;nbsp;homelab?&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The 4 Best &lt;span class="caps"&gt;NAS&lt;/span&gt; Options for Homelab in&amp;nbsp;2026&lt;/h2&gt;
&lt;p&gt;The &lt;span class="caps"&gt;NAS&lt;/span&gt; software landscape in 2026 has consolidated around four dominant options — two free and open-source, one paid with a generous one-time license, and one turnkey hardware-plus-software bundle. Here is the landscape at a&amp;nbsp;glance:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;th&gt;License&lt;/th&gt;
&lt;th&gt;Storage Tech&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TrueNAS 26&lt;/strong&gt; (&lt;span class="caps"&gt;SCALE&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Open Source (&lt;span class="caps"&gt;BSD&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;ZFS&lt;/span&gt; pools&lt;/td&gt;
&lt;td&gt;Data integrity purists, matched drives&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Unraid 7.3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$59–129 (one-time)&lt;/td&gt;
&lt;td&gt;Proprietary + &lt;span class="caps"&gt;OSS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Parity array + &lt;span class="caps"&gt;ZFS&lt;/span&gt; optional&lt;/td&gt;
&lt;td&gt;Flexible builders, mixed drive sizes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OpenMediaVault 7&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Open Source (GPLv3)&lt;/td&gt;
&lt;td&gt;mdadm/&lt;span class="caps"&gt;LVM&lt;/span&gt; + &lt;span class="caps"&gt;ZFS&lt;/span&gt; plugin&lt;/td&gt;
&lt;td&gt;Lightweight setups, old hardware, &lt;span class="caps"&gt;ARM&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Synology &lt;span class="caps"&gt;DSM&lt;/span&gt; 7.2&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$200+ (hardware)&lt;/td&gt;
&lt;td&gt;Proprietary&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;SHR&lt;/span&gt;/Btrfs&lt;/td&gt;
&lt;td&gt;Users who want zero setup and polish&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Each of these can run Docker containers, share files over &lt;span class="caps"&gt;SMB&lt;/span&gt;/&lt;span class="caps"&gt;NFS&lt;/span&gt;, and serve as the storage backbone for your homelab. The differences lie in &lt;em&gt;how&lt;/em&gt; they protect your data, &lt;em&gt;how much&lt;/em&gt; hardware they need, and &lt;em&gt;how steep&lt;/em&gt; the learning curve is. Let us examine each in&amp;nbsp;detail.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;TrueNAS 26&amp;nbsp;(Free)&lt;/h3&gt;
&lt;p&gt;TrueNAS is the heavyweight champion of data integrity. The latest release — TrueNAS 26 (replacing the previous TrueNAS &lt;span class="caps"&gt;SCALE&lt;/span&gt; 24.10 branding) — runs on Debian and uses OpenZFS as its storage engine. &lt;span class="caps"&gt;ZFS&lt;/span&gt; is what sets TrueNAS apart: every block of data is checksummed, so if a drive silently corrupts a file (bit rot), &lt;span class="caps"&gt;ZFS&lt;/span&gt; detects and repairs it automatically. No other filesystem in this comparison offers that level of protection at the filesystem&amp;nbsp;level.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key&amp;nbsp;features:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;OpenZFS 2.3+&lt;/strong&gt; — snapshots, replication, inline compression, deduplication, and&amp;nbsp;self-healing&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Docker/Apps via Kubernetes&lt;/strong&gt; — the Apps system uses Helm charts under the hood, with a catalog of 100+ pre-configured apps (Plex, Jellyfin, Immich,&amp;nbsp;Nextcloud)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Built-in &lt;span class="caps"&gt;SMB&lt;/span&gt;, &lt;span class="caps"&gt;NFS&lt;/span&gt;, iSCSI&lt;/strong&gt; — enterprise-grade sharing out of the&amp;nbsp;box&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Web &lt;span class="caps"&gt;UI&lt;/span&gt; with real-time reporting&lt;/strong&gt; — disk health, pool usage, network throughput, &lt;span class="caps"&gt;CPU&lt;/span&gt;/&lt;span class="caps"&gt;RAM&lt;/span&gt;&amp;nbsp;graphs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Hardware requirements:&lt;/strong&gt;
TrueNAS is the hungriest option. You need at least 8 &lt;span class="caps"&gt;GB&lt;/span&gt; of &lt;span class="caps"&gt;RAM&lt;/span&gt; (&lt;span class="caps"&gt;ZFS&lt;/span&gt; uses &lt;span class="caps"&gt;RAM&lt;/span&gt; as a read cache called &lt;span class="caps"&gt;ARC&lt;/span&gt;), and 16 &lt;span class="caps"&gt;GB&lt;/span&gt;+ is recommended for production use. &lt;span class="caps"&gt;ECC&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; is strongly recommended — not because &lt;span class="caps"&gt;ZFS&lt;/span&gt; demands it, but because &lt;span class="caps"&gt;ZFS&lt;/span&gt;&amp;#8217;s self-healing guarantees weaken if a memory error corrupts data in-flight before &lt;span class="caps"&gt;ZFS&lt;/span&gt; can checksum it. Storage-wise, &lt;span class="caps"&gt;ZFS&lt;/span&gt; pools require matched drives: all drives in a vdev should be the same size, and expanding a pool typically requires adding an entire new vdev rather than a single&amp;nbsp;drive.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Users who want the strongest data integrity guarantees, are willing to invest in proper hardware, and plan their storage capacity&amp;nbsp;upfront.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;
- Best-in-class data integrity with &lt;span class="caps"&gt;ZFS&lt;/span&gt; checksums and self-healing
- Free and open source — no license keys, no subscription
- Active development — iXsystems releases regular updates with new features
- Enterprise heritage — same &lt;span class="caps"&gt;ZFS&lt;/span&gt; engine used in data centers worldwide
- Built-in replication to a second TrueNAS box for off-site&amp;nbsp;backup&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;
- High &lt;span class="caps"&gt;RAM&lt;/span&gt; requirement — 8 &lt;span class="caps"&gt;GB&lt;/span&gt; minimum, 16 &lt;span class="caps"&gt;GB&lt;/span&gt;+ recommended for usable &lt;span class="caps"&gt;ARC&lt;/span&gt;
- Inflexible pool expansion — adding a single drive to an existing pool is not straightforward
- Steep learning curve — &lt;span class="caps"&gt;ZFS&lt;/span&gt; concepts (vdevs, pools, datasets, &lt;span class="caps"&gt;ARC&lt;/span&gt;) take time to master
- Kubernetes-based Apps are more complex than plain Docker Compose — some homelab users prefer the simplicity&amp;nbsp;of &lt;code&gt;docker-compose.yml&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;Unraid 7.3 ($59–129&amp;nbsp;One-Time)&lt;/h3&gt;
&lt;p&gt;Unraid takes the opposite philosophy: flexibility over rigidity. Instead of &lt;span class="caps"&gt;ZFS&lt;/span&gt; pools, Unraid uses a proprietary &lt;strong&gt;parity-protected array&lt;/strong&gt; where any mix of drives — 4 &lt;span class="caps"&gt;TB&lt;/span&gt;, 8 &lt;span class="caps"&gt;TB&lt;/span&gt;, 14 &lt;span class="caps"&gt;TB&lt;/span&gt;, different brands and speeds — can coexist in the same array. You designate one or two drives as parity drives, and Unraid calculates parity data so any single (or dual, with two parity drives) drive failure is recoverable. The parity drive must be at least as large as your largest data&amp;nbsp;drive.&lt;/p&gt;
&lt;p&gt;Unraid 7.3 (released May 2026) is the latest stable release, and it has added &lt;strong&gt;optional &lt;span class="caps"&gt;ZFS&lt;/span&gt; support&lt;/strong&gt; — you can now create &lt;span class="caps"&gt;ZFS&lt;/span&gt; pools alongside the traditional Unraid array, giving you the best of both worlds if you have matched drives for &lt;span class="caps"&gt;ZFS&lt;/span&gt; and mismatched drives for the main&amp;nbsp;array.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key&amp;nbsp;features:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mixed drive array&lt;/strong&gt; — throw in any &lt;span class="caps"&gt;SATA&lt;/span&gt;/NVMe drives you have; Unraid handles the parity&amp;nbsp;math&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Community Applications (&lt;span class="caps"&gt;CA&lt;/span&gt;) plugin&lt;/strong&gt; — arguably the best Docker app ecosystem of any &lt;span class="caps"&gt;NAS&lt;/span&gt; &lt;span class="caps"&gt;OS&lt;/span&gt;. One-click install for over 2,000 apps, from Plex to Home Assistant to&amp;nbsp;Paperless-ngx&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Native Docker + Docker Compose&lt;/strong&gt; — no Kubernetes wrapper; just plain Docker with a friendly &lt;span class="caps"&gt;GUI&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;GPU&lt;/span&gt; passthrough&lt;/strong&gt; — assign a &lt;span class="caps"&gt;GPU&lt;/span&gt; to a &lt;span class="caps"&gt;VM&lt;/span&gt; or Docker container for hardware transcoding or &lt;span class="caps"&gt;AI&lt;/span&gt;&amp;nbsp;inference&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;VM&lt;/span&gt; manager&lt;/strong&gt; — run Windows, Linux, or macOS VMs with passed-through&amp;nbsp;hardware&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Hardware requirements:&lt;/strong&gt;
Unraid is lighter than TrueNAS. 4 &lt;span class="caps"&gt;GB&lt;/span&gt; of &lt;span class="caps"&gt;RAM&lt;/span&gt; is the minimum, and 8–16 &lt;span class="caps"&gt;GB&lt;/span&gt; is comfortable for most homelab use. &lt;span class="caps"&gt;ECC&lt;/span&gt; is nice but entirely optional. Because Unraid reads data from individual drives (not striping across all drives like &lt;span class="caps"&gt;RAID&lt;/span&gt;-Z), only the drive hosting the requested file spins up — the rest can stay idle, saving&amp;nbsp;power.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pricing tiers (one-time purchase, lifetime&amp;nbsp;updates):&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tier&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;th&gt;Max Attached Devices&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Basic&lt;/td&gt;
&lt;td&gt;$59&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Plus&lt;/td&gt;
&lt;td&gt;$89&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pro&lt;/td&gt;
&lt;td&gt;$129&lt;/td&gt;
&lt;td&gt;Unlimited&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Homelab builders who acquire drives gradually, want the easiest Docker experience, or need &lt;span class="caps"&gt;GPU&lt;/span&gt; passthrough for media transcoding and &lt;span class="caps"&gt;AI&lt;/span&gt;&amp;nbsp;workloads.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;
- Mix any drive sizes — gradually upgrade by swapping smaller drives for larger ones
- Best Docker app ecosystem — Community Applications plugin is unmatched in ease of use
- One-time payment, lifetime updates — no subscription trap
- &lt;span class="caps"&gt;GPU&lt;/span&gt; passthrough for transcoding and &lt;span class="caps"&gt;AI&lt;/span&gt; — excellent Plex/Jellyfin host
- Optional &lt;span class="caps"&gt;ZFS&lt;/span&gt; support in v7.3+ for users who want &lt;span class="caps"&gt;ZFS&lt;/span&gt; pools alongside the&amp;nbsp;array&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;
- No native bit rot protection on the parity array — &lt;span class="caps"&gt;ZFS&lt;/span&gt; is better for long-term archival
- Parity array write speed is slower than &lt;span class="caps"&gt;ZFS&lt;/span&gt; (writes require reading parity + data + writing parity)
- Paid license — though the one-time cost is reasonable for what you get
- Boots from a &lt;span class="caps"&gt;USB&lt;/span&gt; flash drive — which can fail without warning if you use a cheap&amp;nbsp;stick&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;OpenMediaVault 7&amp;nbsp;(Free)&lt;/h3&gt;
&lt;p&gt;OpenMediaVault (&lt;span class="caps"&gt;OMV&lt;/span&gt;) is the lightweight, runs-on-anything &lt;span class="caps"&gt;NAS&lt;/span&gt; &lt;span class="caps"&gt;OS&lt;/span&gt;. Built on Debian 12 (Bookworm), &lt;span class="caps"&gt;OMV&lt;/span&gt; 7 is the current stable release, with &lt;span class="caps"&gt;OMV&lt;/span&gt; 8 expected later in 2026 based on Debian 13 (Trixie). &lt;span class="caps"&gt;OMV&lt;/span&gt; does not force you into a specific storage technology — it supports mdadm (Linux software &lt;span class="caps"&gt;RAID&lt;/span&gt;), &lt;span class="caps"&gt;LVM&lt;/span&gt;, and Btrfs natively, with an optional &lt;span class="caps"&gt;ZFS&lt;/span&gt; plugin (via the &lt;span class="caps"&gt;OMV&lt;/span&gt;-extras&amp;nbsp;repository).&lt;/p&gt;
&lt;p&gt;&lt;span class="caps"&gt;OMV&lt;/span&gt;&amp;#8217;s philosophy is minimalism: install a bare Debian system, add the &lt;span class="caps"&gt;OMV&lt;/span&gt; packages, and manage everything through a clean web interface. It consumes far fewer resources than TrueNAS or Unraid, making it ideal for repurposed&amp;nbsp;hardware.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key&amp;nbsp;features:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;mdadm &lt;span class="caps"&gt;RAID&lt;/span&gt;&lt;/strong&gt; — traditional Linux software &lt;span class="caps"&gt;RAID&lt;/span&gt; (0, 1, 5, 6, 10) with grow and reshape&amp;nbsp;support&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;ZFS&lt;/span&gt; plugin&lt;/strong&gt; (via &lt;span class="caps"&gt;OMV&lt;/span&gt;-extras) — &lt;span class="caps"&gt;ZFS&lt;/span&gt; pools with a web &lt;span class="caps"&gt;UI&lt;/span&gt; for snapshot and dataset&amp;nbsp;management&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Docker and Portainer plugin&lt;/strong&gt; — install Portainer from the web &lt;span class="caps"&gt;UI&lt;/span&gt; and manage containers&amp;nbsp;there&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;SMB&lt;/span&gt;, &lt;span class="caps"&gt;NFS&lt;/span&gt;, &lt;span class="caps"&gt;FTP&lt;/span&gt;, Rsync, &lt;span class="caps"&gt;TFTP&lt;/span&gt;&lt;/strong&gt; — all standard file-sharing&amp;nbsp;protocols&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Plugin system&lt;/strong&gt; — additional services (Syncthing, UrBackup, SnapRAID, mergerfs) installable from the web &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Hardware requirements:&lt;/strong&gt;
&lt;span class="caps"&gt;OMV&lt;/span&gt; is the lightest option. It runs comfortably on:
- 1 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; (2 &lt;span class="caps"&gt;GB&lt;/span&gt;+ recommended for &lt;span class="caps"&gt;ZFS&lt;/span&gt;)
- Any x86-64 &lt;span class="caps"&gt;CPU&lt;/span&gt; or &lt;span class="caps"&gt;ARM&lt;/span&gt; (Raspberry Pi 4/5, Odroid, RockPro64)
- A &lt;span class="caps"&gt;USB&lt;/span&gt; flash drive or &lt;span class="caps"&gt;SD&lt;/span&gt; card for the &lt;span class="caps"&gt;OS&lt;/span&gt; + &lt;span class="caps"&gt;SATA&lt;/span&gt;/NVMe drives for&amp;nbsp;data&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Beginners, users with old or low-power hardware, Raspberry Pi enthusiasts, and anyone who wants a free, simple &lt;span class="caps"&gt;NAS&lt;/span&gt; without the overhead of &lt;span class="caps"&gt;ZFS&lt;/span&gt; or the cost of&amp;nbsp;Unraid.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;
- Extremely lightweight — runs on a Raspberry Pi 5 with a &lt;span class="caps"&gt;USB&lt;/span&gt; 3.0 enclosure
- Free and open source — no license costs, no device limits
- Flexible storage — choose mdadm, &lt;span class="caps"&gt;ZFS&lt;/span&gt;, SnapRAID+mergerfs, or plain drives
- Debian underneath —&amp;nbsp;use &lt;code&gt;apt&lt;/code&gt;, systemd, and standard Linux tooling
- Active community — &lt;span class="caps"&gt;OMV&lt;/span&gt;-extras repository maintained by an enthusiastic contributor&amp;nbsp;base&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;
- No built-in bit rot protection without &lt;span class="caps"&gt;ZFS&lt;/span&gt; — mdadm alone does not checksum data
- Weaker Docker &lt;span class="caps"&gt;UI&lt;/span&gt; — relies on Portainer plugin; no integrated container management like Unraid
- Development pace is moderate — major updates follow Debian release cycles (12–24 months)
- Plugin ecosystem is smaller than Unraid&amp;#8217;s Community&amp;nbsp;Applications&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;Synology &lt;span class="caps"&gt;DSM&lt;/span&gt; 7.2 (Pre-Built&amp;nbsp;Hardware)&lt;/h3&gt;
&lt;p&gt;Synology is the &amp;#8220;it just works&amp;#8221; option. You buy a Synology &lt;span class="caps"&gt;NAS&lt;/span&gt; appliance — a compact box with drive bays, an Intel or &lt;span class="caps"&gt;ARM&lt;/span&gt; &lt;span class="caps"&gt;CPU&lt;/span&gt;, and pre-installed DiskStation Manager (&lt;span class="caps"&gt;DSM&lt;/span&gt;) — plug in drives, and go. There is no build process, no &lt;span class="caps"&gt;OS&lt;/span&gt; installation, no hardware compatibility research. &lt;span class="caps"&gt;DSM&lt;/span&gt; is the most polished &lt;span class="caps"&gt;NAS&lt;/span&gt; operating system on the market, with a desktop-like web interface, mobile apps, and a mature ecosystem of first-party&amp;nbsp;packages.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key&amp;nbsp;features:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Synology Hybrid &lt;span class="caps"&gt;RAID&lt;/span&gt; (&lt;span class="caps"&gt;SHR&lt;/span&gt;)&lt;/strong&gt; — Synology&amp;#8217;s proprietary &lt;span class="caps"&gt;RAID&lt;/span&gt; that allows mixing different drive sizes, similar to Unraid&amp;#8217;s philosophy but with real-time striping for better&amp;nbsp;performance&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Btrfs with data checksums&lt;/strong&gt; — Synology uses Btrfs on top of Linux &lt;span class="caps"&gt;RAID&lt;/span&gt;, providing bit rot protection when checksum is enabled on shared&amp;nbsp;folders&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Synology Packages&lt;/strong&gt; — first-party apps for photo management (Synology Photos), surveillance (Surveillance Station), office (Synology Office), backup (Active Backup for Business, Hyper Backup), and media (Video Station, Audio&amp;nbsp;Station)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Container Manager&lt;/strong&gt; — Synology&amp;#8217;s Docker &lt;span class="caps"&gt;UI&lt;/span&gt;, recently upgraded to support Docker Compose&amp;nbsp;natively&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;QuickConnect&lt;/strong&gt; — remote access without port forwarding or a &lt;span class="caps"&gt;VPN&lt;/span&gt; (proxied through Synology&amp;#8217;s&amp;nbsp;servers)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mobile apps&lt;/strong&gt; — &lt;span class="caps"&gt;DS&lt;/span&gt; File, &lt;span class="caps"&gt;DS&lt;/span&gt; Photo, &lt;span class="caps"&gt;DS&lt;/span&gt; Cam, &lt;span class="caps"&gt;DS&lt;/span&gt; Finder, and more on iOS and&amp;nbsp;Android&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Hardware considerations:&lt;/strong&gt;
Entry-level 2-bay models (DS223j) start around $200, while 4-bay Plus-series models (&lt;span class="caps"&gt;DS923&lt;/span&gt;+) run $600+, and 8-bay units exceed $1,000. The hardware is underpowered compared to a &lt;span class="caps"&gt;DIY&lt;/span&gt; build at the same price — a &lt;span class="caps"&gt;DS923&lt;/span&gt;+ has a Ryzen R1600 with 4 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, while $600 buys a used mini &lt;span class="caps"&gt;PC&lt;/span&gt; with an i5 and 32 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;. You pay for the software and the turnkey experience, not raw&amp;nbsp;performance.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Users who want zero setup effort, premium mobile apps for family use, and are willing to pay more for less&amp;nbsp;hassle.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;
- Most polished &lt;span class="caps"&gt;NAS&lt;/span&gt; &lt;span class="caps"&gt;OS&lt;/span&gt; — intuitive web &lt;span class="caps"&gt;UI&lt;/span&gt;, beautiful mobile apps, seamless ecosystem
- Zero build time — unbox, insert drives, power on, and use
- &lt;span class="caps"&gt;SHR&lt;/span&gt; allows mixed drive sizes with striping performance — best of both worlds
- Excellent backup software — Hyper Backup, Active Backup, and Snapshot Replication are best-in-class
- QuickConnect for easy remote access — no reverse proxy or &lt;span class="caps"&gt;VPN&lt;/span&gt; setup needed
- Btrfs checksums for data integrity when enabled on shared&amp;nbsp;folders&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;
- Expensive hardware for the specs — you pay a significant premium for the software
- Vendor lock-in — migrating away from Synology to &lt;span class="caps"&gt;DIY&lt;/span&gt; requires planning
- Limited upgradeability — &lt;span class="caps"&gt;CPU&lt;/span&gt;, &lt;span class="caps"&gt;RAM&lt;/span&gt; (sometimes soldered), and &lt;span class="caps"&gt;NIC&lt;/span&gt; are fixed
- Proprietary &lt;span class="caps"&gt;OS&lt;/span&gt; — you are dependent on Synology for security updates and feature releases
- Some models have soldered &lt;span class="caps"&gt;RAM&lt;/span&gt; and non-standard drive&amp;nbsp;caddies&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Side-by-Side Comparison&amp;nbsp;Table&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;TrueNAS 26&lt;/th&gt;
&lt;th&gt;Unraid 7.3&lt;/th&gt;
&lt;th&gt;OpenMediaVault 7&lt;/th&gt;
&lt;th&gt;Synology &lt;span class="caps"&gt;DSM&lt;/span&gt; 7.2&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cost (&lt;span class="caps"&gt;OS&lt;/span&gt;)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;$59–129 (one-time)&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Included with hardware&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hardware Cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;DIY&lt;/span&gt; (~$300+)&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;DIY&lt;/span&gt; (~$300+)&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;DIY&lt;/span&gt; ($100+ Pi possible)&lt;/td&gt;
&lt;td&gt;$200–$1,000+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;License Type&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Open Source (&lt;span class="caps"&gt;BSD&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;Proprietary + &lt;span class="caps"&gt;GPL&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Open Source (GPLv3)&lt;/td&gt;
&lt;td&gt;Proprietary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;OpenZFS 2.3+&lt;/td&gt;
&lt;td&gt;Parity array + &lt;span class="caps"&gt;ZFS&lt;/span&gt; opt&lt;/td&gt;
&lt;td&gt;mdadm/&lt;span class="caps"&gt;LVM&lt;/span&gt; + &lt;span class="caps"&gt;ZFS&lt;/span&gt; plugin&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;SHR&lt;/span&gt;/Btrfs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mixed Drive Sizes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No (matched vdevs)&lt;/td&gt;
&lt;td&gt;Yes (parity array)&lt;/td&gt;
&lt;td&gt;Yes (mergerfs/SnapRAID)&lt;/td&gt;
&lt;td&gt;Yes (&lt;span class="caps"&gt;SHR&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bit Rot Protection&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes (&lt;span class="caps"&gt;ZFS&lt;/span&gt; checksums)&lt;/td&gt;
&lt;td&gt;No (on parity array)&lt;/td&gt;
&lt;td&gt;Optional (&lt;span class="caps"&gt;ZFS&lt;/span&gt; plugin)&lt;/td&gt;
&lt;td&gt;Yes (Btrfs checksums)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Docker/Apps&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Kubernetes (Helm)&lt;/td&gt;
&lt;td&gt;Native + &lt;span class="caps"&gt;CA&lt;/span&gt; plugin&lt;/td&gt;
&lt;td&gt;Portainer plugin&lt;/td&gt;
&lt;td&gt;Container Manager&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;VM&lt;/span&gt; Support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes (&lt;span class="caps"&gt;KVM&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;Yes (&lt;span class="caps"&gt;KVM&lt;/span&gt; + &lt;span class="caps"&gt;GPU&lt;/span&gt; passthrough)&lt;/td&gt;
&lt;td&gt;Yes (&lt;span class="caps"&gt;KVM&lt;/span&gt; plugin)&lt;/td&gt;
&lt;td&gt;Yes (&lt;span class="caps"&gt;VDSM&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt; Minimum&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;8 &lt;span class="caps"&gt;GB&lt;/span&gt; (16 &lt;span class="caps"&gt;GB&lt;/span&gt; rec.)&lt;/td&gt;
&lt;td&gt;4 &lt;span class="caps"&gt;GB&lt;/span&gt; (8 &lt;span class="caps"&gt;GB&lt;/span&gt; rec.)&lt;/td&gt;
&lt;td&gt;1 &lt;span class="caps"&gt;GB&lt;/span&gt; (2 &lt;span class="caps"&gt;GB&lt;/span&gt; rec.)&lt;/td&gt;
&lt;td&gt;2 &lt;span class="caps"&gt;GB&lt;/span&gt; (model-dependent)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;ARM&lt;/span&gt;/Raspberry Pi&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No (x86-64 only)&lt;/td&gt;
&lt;td&gt;No (x86-64 only)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes (&lt;span class="caps"&gt;ARM&lt;/span&gt; models exist)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Learning Curve&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Steep&lt;/td&gt;
&lt;td&gt;Moderate&lt;/td&gt;
&lt;td&gt;Easy&lt;/td&gt;
&lt;td&gt;Easy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mobile Apps&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Limited (TrueCommand, TrueNAS &lt;span class="caps"&gt;UI&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;Limited (Ungoverned, ControlR)&lt;/td&gt;
&lt;td&gt;None (web &lt;span class="caps"&gt;UI&lt;/span&gt; only)&lt;/td&gt;
&lt;td&gt;Excellent (&lt;span class="caps"&gt;DS&lt;/span&gt; File, Photos, Cam, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;GPU&lt;/span&gt; Passthrough&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Excellent&lt;/td&gt;
&lt;td&gt;Limited (&lt;span class="caps"&gt;KVM&lt;/span&gt; plugin)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Snapshot/Replication&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Excellent (&lt;span class="caps"&gt;ZFS&lt;/span&gt; send/recv)&lt;/td&gt;
&lt;td&gt;Good (built-in + &lt;span class="caps"&gt;ZFS&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;Good (&lt;span class="caps"&gt;ZFS&lt;/span&gt; + Rsync)&lt;/td&gt;
&lt;td&gt;Excellent (Snapshot Replication)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Which &lt;span class="caps"&gt;NAS&lt;/span&gt; &lt;span class="caps"&gt;OS&lt;/span&gt; Should You Choose? — Decision&amp;nbsp;Tree&lt;/h2&gt;
&lt;p&gt;There is no single &amp;#8220;best&amp;#8221; &lt;span class="caps"&gt;NAS&lt;/span&gt; — the right choice depends on your drives, your hardware, and what you value most. Here is a decision tree to guide&amp;nbsp;you:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;Do you want to buy hardware, plug it in, and never open a terminal?&amp;#8221;&lt;/strong&gt;
   → &lt;strong&gt;Get a Synology.&lt;/strong&gt; Nothing else matches the polish and convenience. Pay the premium and move&amp;nbsp;on.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;Do you have a collection of random, mismatched drives?&amp;#8221;&lt;/strong&gt;
   → &lt;strong&gt;Unraid is your best friend.&lt;/strong&gt; Its parity array handles any mix of sizes and brands. You can add or replace drives individually over time without rebuilding the entire&amp;nbsp;array.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;Do you have matched drives and care deeply about data integrity?&amp;#8221;&lt;/strong&gt;
   → &lt;strong&gt;TrueNAS 26 with &lt;span class="caps"&gt;ZFS&lt;/span&gt;.&lt;/strong&gt; If you buy drives in matching pairs or sets, &lt;span class="caps"&gt;ZFS&lt;/span&gt; gives you checksums, snapshots, replication, and self-healing that no other option matches. Invest in &lt;span class="caps"&gt;ECC&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; if you&amp;nbsp;can.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;Are you on a tight budget, using old hardware, or a Raspberry Pi?&amp;#8221;&lt;/strong&gt;
   → &lt;strong&gt;OpenMediaVault.&lt;/strong&gt; It runs on anything, costs nothing, and supports every storage technology under the sun. Pair it with SnapRAID + mergerfs for a Unraid-like experience, or enable the &lt;span class="caps"&gt;ZFS&lt;/span&gt; plugin if your hardware supports&amp;nbsp;it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;Do you want to run Plex/Jellyfin with hardware transcoding?&amp;#8221;&lt;/strong&gt;
   → &lt;strong&gt;Unraid or TrueNAS.&lt;/strong&gt; Unraid&amp;#8217;s &lt;span class="caps"&gt;GPU&lt;/span&gt; passthrough is more straightforward, but TrueNAS 26 also supports &lt;span class="caps"&gt;GPU&lt;/span&gt; assignment to apps. Both work — Unraid edges ahead on&amp;nbsp;ease.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;Are you unsure and just want to experiment?&amp;#8221;&lt;/strong&gt;
   → &lt;strong&gt;Start with OpenMediaVault.&lt;/strong&gt; It is free, runs in a &lt;span class="caps"&gt;VM&lt;/span&gt;, and costs nothing to try. If you outgrow it, the data on your drives can be migrated to TrueNAS or Unraid&amp;nbsp;later.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;&lt;span class="caps"&gt;DIY&lt;/span&gt; &lt;span class="caps"&gt;NAS&lt;/span&gt; Hardware Recommendations for&amp;nbsp;2026&lt;/h2&gt;
&lt;p&gt;Building your own &lt;span class="caps"&gt;NAS&lt;/span&gt; gives you far more performance per dollar than a Synology — but you need to choose the right hardware. Here are three build tiers matched to the &lt;span class="caps"&gt;NAS&lt;/span&gt; &lt;span class="caps"&gt;OS&lt;/span&gt; options above. For more detailed hardware guidance, see our &lt;a href="https://steadypub.com/2026/06/homelab-server-hardware-2025/"&gt;homelab hardware guide&lt;/a&gt; and &lt;a href="https://steadypub.com/2026/06/mini-pc-home-server-2025/"&gt;mini &lt;span class="caps"&gt;PC&lt;/span&gt; home server roundup&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Budget Build (~$200–350) —&amp;nbsp;OpenMediaVault&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Base:&lt;/strong&gt; Raspberry Pi 5 (8 &lt;span class="caps"&gt;GB&lt;/span&gt;) with Argon &lt;span class="caps"&gt;EON&lt;/span&gt; case (4-bay &lt;span class="caps"&gt;SATA&lt;/span&gt;) — around $180&amp;nbsp;total&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Alternative:&lt;/strong&gt; Used &lt;span class="caps"&gt;HP&lt;/span&gt; EliteDesk 800 G4 Mini (i5-8500T, 16 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;) off eBay —&amp;nbsp;$150&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Drives:&lt;/strong&gt; 2× 4 &lt;span class="caps"&gt;TB&lt;/span&gt; refurbished enterprise HDDs (&lt;span class="caps"&gt;HGST&lt;/span&gt;/&lt;span class="caps"&gt;WD&lt;/span&gt;) ~$50&amp;nbsp;each&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Why &lt;span class="caps"&gt;OMV&lt;/span&gt;:&lt;/strong&gt; Lightweight enough for a Pi, or pairs well with the EliteDesk&amp;#8217;s 35 W &lt;span class="caps"&gt;TDP&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Note:&lt;/strong&gt; Use a powered &lt;span class="caps"&gt;USB&lt;/span&gt; 3.0 hub or &lt;span class="caps"&gt;SATA&lt;/span&gt; &lt;span class="caps"&gt;HAT&lt;/span&gt; for the Pi — the onboard &lt;span class="caps"&gt;USB&lt;/span&gt; ports may not deliver enough power for spinning&amp;nbsp;drives&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Mid-Range Build (~$500–800) — Unraid or&amp;nbsp;TrueNAS&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Base:&lt;/strong&gt; Topton N22 / N305 board (Intel N305, 6× &lt;span class="caps"&gt;SATA&lt;/span&gt;, 2× M.2, 2× 2.5GbE) — $220 on&amp;nbsp;AliExpress&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Case:&lt;/strong&gt; Jonsbo N3 (8-bay hot-swap, &lt;span class="caps"&gt;ITX&lt;/span&gt;) —&amp;nbsp;$150&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;:&lt;/strong&gt; 32 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;DDR5&lt;/span&gt; &lt;span class="caps"&gt;SODIMM&lt;/span&gt; —&amp;nbsp;$80&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;PSU&lt;/span&gt;:&lt;/strong&gt; &lt;span class="caps"&gt;SFX&lt;/span&gt; 450W Gold —&amp;nbsp;$90&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Drives:&lt;/strong&gt; Start with 3× 8 &lt;span class="caps"&gt;TB&lt;/span&gt; &lt;span class="caps"&gt;WD&lt;/span&gt; Red Plus or Seagate IronWolf — $160–200&amp;nbsp;each&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flexibility:&lt;/strong&gt; This build runs TrueNAS (with matched 8 &lt;span class="caps"&gt;TB&lt;/span&gt; drives in &lt;span class="caps"&gt;RAID&lt;/span&gt;-Z1) or Unraid (add drives later one at a time). The N305&amp;#8217;s Quick Sync supports Plex&amp;nbsp;transcoding.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Performance Build (~$1,000+) — TrueNAS&amp;nbsp;26&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Base:&lt;/strong&gt; Intel Core i5-13500 (Raptor Lake, 14 cores, &lt;span class="caps"&gt;UHD&lt;/span&gt; 770 Quick Sync) —&amp;nbsp;$230&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Motherboard:&lt;/strong&gt; W680 chipset board with &lt;span class="caps"&gt;IPMI&lt;/span&gt; (ASRock Rack &lt;span class="caps"&gt;W680D4U&lt;/span&gt;) or consumer Z790 with 8× &lt;span class="caps"&gt;SATA&lt;/span&gt; —&amp;nbsp;$300&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;:&lt;/strong&gt; 64 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;DDR5&lt;/span&gt; &lt;span class="caps"&gt;ECC&lt;/span&gt; —&amp;nbsp;$200&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;NIC&lt;/span&gt;:&lt;/strong&gt; Intel X710-&lt;span class="caps"&gt;DA2&lt;/span&gt; (dual &lt;span class="caps"&gt;SFP&lt;/span&gt;+ 10GbE) — $80 on&amp;nbsp;eBay&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Drives:&lt;/strong&gt; 6× 16 &lt;span class="caps"&gt;TB&lt;/span&gt; Seagate Exos X18 in &lt;span class="caps"&gt;RAID&lt;/span&gt;-Z2 — staggered purchase over&amp;nbsp;time&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Why TrueNAS:&lt;/strong&gt; At this tier, you want &lt;span class="caps"&gt;ZFS&lt;/span&gt; with &lt;span class="caps"&gt;ECC&lt;/span&gt;, 10GbE networking, and enterprise-grade data protection. This box will serve your homelab for 5+&amp;nbsp;years.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Setting Up Your &lt;span class="caps"&gt;NAS&lt;/span&gt; with&amp;nbsp;Docker&lt;/h2&gt;
&lt;p&gt;All four &lt;span class="caps"&gt;NAS&lt;/span&gt; &lt;span class="caps"&gt;OS&lt;/span&gt; options support Docker, which means your app stack is portable. Whether you run &lt;a href="https://steadypub.com/2026/06/docker-compose-for-beginners/"&gt;Docker Compose&lt;/a&gt; on TrueNAS, Unraid&amp;#8217;s Community Applications, &lt;span class="caps"&gt;OMV&lt;/span&gt; with &lt;a href="https://steadypub.com/2026/06/portainer-docker-management/"&gt;Portainer&lt;/a&gt;, or Synology&amp;#8217;s Container Manager, the core workflow is the&amp;nbsp;same:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a dataset or shared folder for persistent container data (configs, databases,&amp;nbsp;media)&lt;/li&gt;
&lt;li&gt;Define your stack&amp;nbsp;in &lt;code&gt;docker-compose.yml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Mount the &lt;span class="caps"&gt;NAS&lt;/span&gt; shares as Docker&amp;nbsp;volumes&lt;/li&gt;
&lt;li&gt;Expose services through a reverse proxy (Traefik, Nginx Proxy Manager, or&amp;nbsp;Caddy)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A typical homelab app stack on a &lt;span class="caps"&gt;NAS&lt;/span&gt; might include:
- &lt;strong&gt;Plex&lt;/strong&gt; or &lt;strong&gt;Jellyfin&lt;/strong&gt; — media server with &lt;span class="caps"&gt;GPU&lt;/span&gt; transcoding on Unraid or TrueNAS
- &lt;strong&gt;&lt;a href="https://steadypub.com/2026/06/nextcloud-self-hosted/"&gt;Nextcloud&lt;/a&gt;&lt;/strong&gt; — private cloud storage and collaboration hub
- &lt;strong&gt;&lt;a href="https://steadypub.com/2026/06/immich-docker-compose-setup/"&gt;Immich&lt;/a&gt;&lt;/strong&gt; — Google Photos replacement with &lt;span class="caps"&gt;AI&lt;/span&gt;-powered search
- &lt;strong&gt;Pi-hole&lt;/strong&gt; or &lt;strong&gt;AdGuard Home&lt;/strong&gt; — network-wide ad blocking
- &lt;strong&gt;Vaultwarden&lt;/strong&gt; — self-hosted password manager
- &lt;strong&gt;Homepage&lt;/strong&gt; or &lt;strong&gt;Homer&lt;/strong&gt; — dashboard for all your&amp;nbsp;services&lt;/p&gt;
&lt;p&gt;Because the &lt;span class="caps"&gt;NAS&lt;/span&gt; handles storage, your containers stay stateless — back up the &lt;span class="caps"&gt;NAS&lt;/span&gt; datasets, and your entire app stack is&amp;nbsp;recoverable.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;&lt;span class="caps"&gt;FAQ&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Q: Can I run a &lt;span class="caps"&gt;NAS&lt;/span&gt; on a Raspberry Pi 5?&lt;/strong&gt;
Yes — OpenMediaVault runs well on a Pi 5 with Debian &lt;span class="caps"&gt;ARM64&lt;/span&gt;. Attach &lt;span class="caps"&gt;USB&lt;/span&gt; 3.0 drives or use a &lt;span class="caps"&gt;SATA&lt;/span&gt; &lt;span class="caps"&gt;HAT&lt;/span&gt;. TrueNAS and Unraid require x86-64 and will not run on &lt;span class="caps"&gt;ARM&lt;/span&gt;. A Pi-based &lt;span class="caps"&gt;NAS&lt;/span&gt; is best for light workloads (file sharing, Pi-hole, small Docker stacks), not heavy media transcoding or &lt;span class="caps"&gt;ZFS&lt;/span&gt;&amp;nbsp;pools.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: Is Unraid worth the price when TrueNAS is free?&lt;/strong&gt;
Unraid is worth $59–129 if you have mixed drive sizes, want the easiest Docker experience (Community Applications), or need straightforward &lt;span class="caps"&gt;GPU&lt;/span&gt; passthrough. TrueNAS is the better zero-cost choice if you buy drives in matched sets and value &lt;span class="caps"&gt;ZFS&lt;/span&gt; data integrity above all. The cost is one-time, not recurring — many Unraid users buy once and use it for 5+&amp;nbsp;years.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: Can I migrate from Synology to a &lt;span class="caps"&gt;DIY&lt;/span&gt; &lt;span class="caps"&gt;NAS&lt;/span&gt;?&lt;/strong&gt;
Yes. The safest approach is to build your new &lt;span class="caps"&gt;NAS&lt;/span&gt; (TrueNAS, Unraid, or &lt;span class="caps"&gt;OMV&lt;/span&gt;) on separate hardware, transfer data over the network&amp;nbsp;via &lt;code&gt;rsync&lt;/code&gt; or &lt;span class="caps"&gt;NFS&lt;/span&gt;, and then repurpose or sell the Synology. Directly importing Synology drives into a &lt;span class="caps"&gt;DIY&lt;/span&gt; build is possible but risky — Synology uses a modified mdadm/&lt;span class="caps"&gt;LVM&lt;/span&gt; layout that may not import cleanly. Plan your migration, keep the Synology powered on until you have verified the data on the new box, and always have a&amp;nbsp;backup.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: Do I need &lt;span class="caps"&gt;ECC&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; for TrueNAS?&lt;/strong&gt;
&lt;span class="caps"&gt;ECC&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; is strongly recommended but not strictly required for homelab use. The risk is that a memory error could corrupt data in-flight before &lt;span class="caps"&gt;ZFS&lt;/span&gt; writes it to disk — meaning &lt;span class="caps"&gt;ZFS&lt;/span&gt; would checksum the already-corrupted data and never know it was wrong. For media libraries and replaceable data, this risk is acceptable. For irreplaceable family photos, legal documents, or business data, use &lt;span class="caps"&gt;ECC&lt;/span&gt;. 8 &lt;span class="caps"&gt;GB&lt;/span&gt; is the absolute minimum; 16 &lt;span class="caps"&gt;GB&lt;/span&gt;+ lets &lt;span class="caps"&gt;ZFS&lt;/span&gt; cache more data in &lt;span class="caps"&gt;ARC&lt;/span&gt; for faster&amp;nbsp;reads.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: Which &lt;span class="caps"&gt;NAS&lt;/span&gt; is best for Plex and media servers?&lt;/strong&gt;
Unraid is the most popular Plex host thanks to its Community Applications one-click install and excellent &lt;span class="caps"&gt;GPU&lt;/span&gt; passthrough support for hardware transcoding. TrueNAS 26 also works well if you are comfortable with the Kubernetes-based Apps system. Synology supports Plex but the underpowered CPUs in many models struggle with transcoding 4K content. The key feature for any Plex host is Intel Quick Sync Video (iGPU) or a dedicated &lt;span class="caps"&gt;NVIDIA&lt;/span&gt; &lt;span class="caps"&gt;GPU&lt;/span&gt; for hardware-accelerated transcoding — check your &lt;span class="caps"&gt;CPU&lt;/span&gt; supports it before&amp;nbsp;building.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: How many drives do I need to start?&lt;/strong&gt;
- &lt;strong&gt;TrueNAS:&lt;/strong&gt; Minimum 2 for a mirror, 3 for &lt;span class="caps"&gt;RAID&lt;/span&gt;-Z1. Buy all your drives up front — expanding later requires adding entire new vdevs.
- &lt;strong&gt;Unraid:&lt;/strong&gt; Minimum 2 (1 data + 1 parity). You can add drives one at a time indefinitely up to your license limit.
- &lt;strong&gt;OpenMediaVault:&lt;/strong&gt; As few as 1 drive (no redundancy). Add a second for &lt;span class="caps"&gt;RAID&lt;/span&gt; 1 mirroring or use SnapRAID with 1 parity + any number of data drives.
- &lt;strong&gt;Synology:&lt;/strong&gt; 2-bay minimum for &lt;span class="caps"&gt;SHR&lt;/span&gt; (1-drive redundancy). 4-bay and 8-bay models scale&amp;nbsp;up.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;There is no universal &amp;#8220;best&amp;#8221; &lt;span class="caps"&gt;NAS&lt;/span&gt; operating system — each option excels in a different&amp;nbsp;scenario:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;TrueNAS 26&lt;/strong&gt; dominates on data integrity. If you buy matched drives, invest in &lt;span class="caps"&gt;ECC&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, and want &lt;span class="caps"&gt;ZFS&lt;/span&gt;&amp;#8217;s self-healing guarantees, there is no&amp;nbsp;substitute.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Unraid 7.3&lt;/strong&gt; wins on flexibility and ease. Its mixed-drive array and Community Applications make it the go-to choice for homelab builders who collect drives over&amp;nbsp;time.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OpenMediaVault 7&lt;/strong&gt; is the budget champion. It runs on anything — from a Raspberry Pi to a repurposed office &lt;span class="caps"&gt;PC&lt;/span&gt; — and costs&amp;nbsp;nothing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Synology &lt;span class="caps"&gt;DSM&lt;/span&gt;&lt;/strong&gt; is the turnkey solution. Pay the premium, unbox it, and move on with your&amp;nbsp;life.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you are unsure where to start, install OpenMediaVault on whatever machine you have (or a &lt;span class="caps"&gt;VM&lt;/span&gt;) and get comfortable with the concepts. Once you understand your storage needs — how many drives, what redundancy level, what apps you will host — you can confidently choose TrueNAS or Unraid. The &lt;span class="caps"&gt;NAS&lt;/span&gt; you build today will be the foundation your homelab grows on for&amp;nbsp;years.&lt;/p&gt;</content><category term="Guides"/><category term="nas"/><category term="truenas"/><category term="unraid"/><category term="openmediavault"/><category term="synology"/><category term="homelab"/><category term="self-hosted"/><category term="storage"/><category term="zfs"/><category term="docker"/></entry><entry><title>Host Ollama on Proxmox 2026: Self-Hosted AI in Your Homelab</title><link href="https://steadypub.com/2026/06/ollama-proxmox-homelab/" rel="alternate"/><published>2026-06-06T00:33:00+07:00</published><updated>2026-06-06T00:33:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-06:/2026/06/ollama-proxmox-homelab/</id><summary type="html">&lt;p&gt;Run your own private &lt;span class="caps"&gt;LLM&lt;/span&gt; server with Ollama on Proxmox. Covers &lt;span class="caps"&gt;LXC&lt;/span&gt; vs &lt;span class="caps"&gt;VM&lt;/span&gt; setup, &lt;span class="caps"&gt;GPU&lt;/span&gt; passthrough for &lt;span class="caps"&gt;NVIDIA&lt;/span&gt; and Intel &lt;span class="caps"&gt;ARC&lt;/span&gt;, OpenWebUI for a ChatGPT-like interface, and performance benchmarks on consumer&amp;nbsp;hardware.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~20 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab owners who want a private, offline &lt;span class="caps"&gt;AI&lt;/span&gt; assistant without monthly subscriptions
&lt;strong&gt;Last tested:&lt;/strong&gt; Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; 8.2, Ollama 0.5, OpenWebUI 0.4, June&amp;nbsp;2026&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why Self-Host an &lt;span class="caps"&gt;LLM&lt;/span&gt;?&lt;/h2&gt;
&lt;p&gt;Cloud &lt;span class="caps"&gt;AI&lt;/span&gt; services come with three problems for homelab users: &lt;strong&gt;privacy&lt;/strong&gt; (your data leaves your network), &lt;strong&gt;cost&lt;/strong&gt; (ChatGPT Plus is $20/month, Claude Pro is $20/month, and &lt;span class="caps"&gt;API&lt;/span&gt; bills add up fast), and &lt;strong&gt;availability&lt;/strong&gt; (outages, rate limits, and terms-of-service&amp;nbsp;changes).&lt;/p&gt;
&lt;p&gt;Running Ollama on your Proxmox server solves all three. You get a private, always-on &lt;span class="caps"&gt;LLM&lt;/span&gt; that works even when your internet is down — and the only recurring cost is&amp;nbsp;electricity.&lt;/p&gt;
&lt;h3&gt;What You&amp;#8217;ll&amp;nbsp;Build&lt;/h3&gt;
&lt;p&gt;By the end of this guide, you will&amp;nbsp;have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ollama&lt;/strong&gt; serving multiple open-weight models (Llama 3.3, Mistral, Phi-4, Qwen&amp;nbsp;2.5)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OpenWebUI&lt;/strong&gt; providing a ChatGPT-style chat interface accessible from any device on your &lt;span class="caps"&gt;LAN&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Optional &lt;strong&gt;&lt;span class="caps"&gt;GPU&lt;/span&gt; acceleration&lt;/strong&gt; for 3–10× faster token&amp;nbsp;generation&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Docker Compose&lt;/strong&gt; stack you can version-control and redeploy in&amp;nbsp;minutes&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Hardware&amp;nbsp;Requirements&lt;/h2&gt;
&lt;h3&gt;Minimum (&lt;span class="caps"&gt;CPU&lt;/span&gt;-Only&amp;nbsp;Inference)&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Requirement&lt;/th&gt;
&lt;th&gt;Real-World Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;4 cores, x86_64&lt;/td&gt;
&lt;td&gt;Intel N100, old i5-6500&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;16 &lt;span class="caps"&gt;GB&lt;/span&gt; (8 &lt;span class="caps"&gt;GB&lt;/span&gt; for &lt;span class="caps"&gt;OS&lt;/span&gt; + 8 &lt;span class="caps"&gt;GB&lt;/span&gt; for a 7B model)&lt;/td&gt;
&lt;td&gt;Any &lt;span class="caps"&gt;DDR4&lt;/span&gt; system&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;30 &lt;span class="caps"&gt;GB&lt;/span&gt; free (models are 4–15 &lt;span class="caps"&gt;GB&lt;/span&gt; each)&lt;/td&gt;
&lt;td&gt;256 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt; minimum&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;GPU&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;None required&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt; inference works&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Recommended (&lt;span class="caps"&gt;GPU&lt;/span&gt;-Accelerated)&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Requirement&lt;/th&gt;
&lt;th&gt;Real-World Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;6+ cores&lt;/td&gt;
&lt;td&gt;Intel i5-12400, Ryzen 5 5600&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;32 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;DDR4&lt;/span&gt; 3200 MHz&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;GPU&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;NVIDIA&lt;/span&gt; &lt;span class="caps"&gt;RTX&lt;/span&gt; 3060 12 &lt;span class="caps"&gt;GB&lt;/span&gt;, &lt;span class="caps"&gt;RTX&lt;/span&gt; 4060 Ti 16 &lt;span class="caps"&gt;GB&lt;/span&gt;, or Intel &lt;span class="caps"&gt;ARC&lt;/span&gt; A770 16 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Buy used on eBay&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;100 &lt;span class="caps"&gt;GB&lt;/span&gt; NVMe&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;WD&lt;/span&gt; Black &lt;span class="caps"&gt;SN770&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;VRAM&lt;/span&gt; rule of thumb:&lt;/strong&gt; A 7B parameter model at Q4_K_M quantization needs ~4.5 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;VRAM&lt;/span&gt;. A 13B model needs ~8 &lt;span class="caps"&gt;GB&lt;/span&gt;. A 34B model needs ~20 &lt;span class="caps"&gt;GB&lt;/span&gt;. Match your &lt;span class="caps"&gt;GPU&lt;/span&gt; &lt;span class="caps"&gt;VRAM&lt;/span&gt; to the model size you want to&amp;nbsp;run.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;Architecture Decision: &lt;span class="caps"&gt;LXC&lt;/span&gt; vs &lt;span class="caps"&gt;VM&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;Proxmox gives you two containerization options. Here is the honest&amp;nbsp;trade-off:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Factor&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;LXC&lt;/span&gt; Container&lt;/th&gt;
&lt;th&gt;Full &lt;span class="caps"&gt;VM&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;GPU&lt;/span&gt; passthrough&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Easier —&amp;nbsp;bind-mount &lt;code&gt;/dev/dri&lt;/code&gt; for Intel iGPU&amp;nbsp;or &lt;code&gt;/dev/nvidia*&lt;/code&gt; for &lt;span class="caps"&gt;NVIDIA&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Requires PCIe passthrough (locks &lt;span class="caps"&gt;GPU&lt;/span&gt; to one &lt;span class="caps"&gt;VM&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Performance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Near-native &lt;span class="caps"&gt;CPU&lt;/span&gt; speed&lt;/td&gt;
&lt;td&gt;~2–5% virtualization overhead&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Docker compatibility&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Works if &lt;span class="caps"&gt;LXC&lt;/span&gt; is privileged + nesting=1&lt;/td&gt;
&lt;td&gt;Works natively&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Isolation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Shares host kernel&lt;/td&gt;
&lt;td&gt;Fully isolated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Snapshot/backup&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Proxmox backup works&lt;/td&gt;
&lt;td&gt;Proxmox backup works&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Intel iGPU (Quick Sync), &lt;span class="caps"&gt;CPU&lt;/span&gt;-only inference&lt;/td&gt;
&lt;td&gt;Dedicated &lt;span class="caps"&gt;NVIDIA&lt;/span&gt; &lt;span class="caps"&gt;GPU&lt;/span&gt;, multi-tenant setups&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Our recommendation:&lt;/strong&gt; Start with an &lt;strong&gt;&lt;span class="caps"&gt;LXC&lt;/span&gt; container&lt;/strong&gt; if you only need &lt;span class="caps"&gt;CPU&lt;/span&gt; inference or Intel iGPU acceleration. Use a &lt;strong&gt;&lt;span class="caps"&gt;VM&lt;/span&gt;&lt;/strong&gt; if you have a dedicated &lt;span class="caps"&gt;NVIDIA&lt;/span&gt; &lt;span class="caps"&gt;GPU&lt;/span&gt; you want to pass&amp;nbsp;through.&lt;/p&gt;
&lt;p&gt;This guide covers both&amp;nbsp;paths.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Path A: &lt;span class="caps"&gt;LXC&lt;/span&gt; Container Setup (&lt;span class="caps"&gt;CPU&lt;/span&gt; or Intel&amp;nbsp;iGPU)&lt;/h2&gt;
&lt;h3&gt;Step A1: Create the &lt;span class="caps"&gt;LXC&lt;/span&gt;&amp;nbsp;Container&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;In the Proxmox web &lt;span class="caps"&gt;UI&lt;/span&gt;, click &lt;strong&gt;Create &lt;span class="caps"&gt;CT&lt;/span&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Template:&lt;/strong&gt; Choose a Debian 12 or Ubuntu 24.04&amp;nbsp;template.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Root Disk:&lt;/strong&gt; Allocate 40 &lt;span class="caps"&gt;GB&lt;/span&gt; (you will need space for Docker images and &lt;span class="caps"&gt;LLM&lt;/span&gt;&amp;nbsp;models).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;:&lt;/strong&gt; Assign 4–8&amp;nbsp;cores.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Memory:&lt;/strong&gt; Assign 16–32 &lt;span class="caps"&gt;GB&lt;/span&gt; (at least 12 &lt;span class="caps"&gt;GB&lt;/span&gt; for a 7B&amp;nbsp;model).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Network:&lt;/strong&gt; &lt;span class="caps"&gt;DHCP&lt;/span&gt; or static &lt;span class="caps"&gt;IP&lt;/span&gt; on your &lt;span class="caps"&gt;LAN&lt;/span&gt;&amp;nbsp;bridge.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Step A2: Enable Docker in &lt;span class="caps"&gt;LXC&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;After creation, select the container → &lt;strong&gt;Options&lt;/strong&gt; →&amp;nbsp;enable:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;unprivileged container&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;No&lt;/strong&gt; (uncheck)&lt;/td&gt;
&lt;td&gt;Docker requires privileges to manage cgroups and networks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Features: nesting&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Yes&lt;/strong&gt; (check)&lt;/td&gt;
&lt;td&gt;Allows Docker-in-&lt;span class="caps"&gt;LXC&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Features: keyctl&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Yes&lt;/strong&gt; (check)&lt;/td&gt;
&lt;td&gt;Required by some container runtimes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Security note:&lt;/strong&gt; An unprivileged &lt;span class="caps"&gt;LXC&lt;/span&gt; is safer, but Docker inside unprivileged &lt;span class="caps"&gt;LXC&lt;/span&gt; containers is unreliable. For a single-user homelab this trade-off is acceptable. If you need stronger isolation, use Path B (&lt;span class="caps"&gt;VM&lt;/span&gt;).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Step A3: Install Docker&amp;nbsp;Engine&lt;/h3&gt;
&lt;p&gt;&lt;span class="caps"&gt;SSH&lt;/span&gt; into the container or use the Proxmox&amp;nbsp;console:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Update and install prerequisites&lt;/span&gt;
apt&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;upgrade&lt;span class="w"&gt; &lt;/span&gt;-y
apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;ca-certificates&lt;span class="w"&gt; &lt;/span&gt;curl

&lt;span class="c1"&gt;# Add Docker&amp;#39;s official GPG key and repository&lt;/span&gt;
install&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0755&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;/etc/apt/keyrings
curl&lt;span class="w"&gt; &lt;/span&gt;-fsSL&lt;span class="w"&gt; &lt;/span&gt;https://download.docker.com/linux/debian/gpg&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;/etc/apt/keyrings/docker.asc
chmod&lt;span class="w"&gt; &lt;/span&gt;a+r&lt;span class="w"&gt; &lt;/span&gt;/etc/apt/keyrings/docker.asc

&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;deb [arch=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;dpkg&lt;span class="w"&gt; &lt;/span&gt;--print-architecture&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;/etc/os-release&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$VERSION_CODENAME&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; stable&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/apt/sources.list.d/docker.list

apt&lt;span class="w"&gt; &lt;/span&gt;update
apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;docker-ce&lt;span class="w"&gt; &lt;/span&gt;docker-ce-cli&lt;span class="w"&gt; &lt;/span&gt;containerd.io&lt;span class="w"&gt; &lt;/span&gt;docker-compose-plugin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Verify:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;--rm&lt;span class="w"&gt; &lt;/span&gt;hello-world
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Step A4: (Optional) Pass Through Intel&amp;nbsp;iGPU&lt;/h3&gt;
&lt;p&gt;If your Proxmox host has an Intel iGPU (&lt;span class="caps"&gt;UHD&lt;/span&gt; 630, &lt;span class="caps"&gt;UHD&lt;/span&gt; 730, Iris Xe), you can give the &lt;span class="caps"&gt;LXC&lt;/span&gt; access to it without full PCIe&amp;nbsp;passthrough:&lt;/p&gt;
&lt;p&gt;On the &lt;strong&gt;Proxmox host&lt;/strong&gt;, find the render&amp;nbsp;device:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-la&lt;span class="w"&gt; &lt;/span&gt;/dev/dri/
&lt;span class="c1"&gt;# You should see: renderD128&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Edit the &lt;span class="caps"&gt;LXC&lt;/span&gt; config file on the host&amp;nbsp;(&lt;code&gt;/etc/pve/lxc/&amp;lt;CTID&amp;gt;.conf&lt;/code&gt;) and&amp;nbsp;add:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;lxc.cgroup2.devices.allow: c 226:* rwm
lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file
lxc.mount.entry: /dev/dri/card0 dev/dri/card0 none bind,optional,create=file
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Inside the &lt;span class="caps"&gt;LXC&lt;/span&gt;, install the Intel compute&amp;nbsp;runtime:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;intel-opencl-icd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Verify &lt;span class="caps"&gt;GPU&lt;/span&gt;&amp;nbsp;visibility:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-la&lt;span class="w"&gt; &lt;/span&gt;/dev/dri/
&lt;span class="c1"&gt;# Should show renderD128 and card0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Path B: Full &lt;span class="caps"&gt;VM&lt;/span&gt; Setup (Dedicated &lt;span class="caps"&gt;NVIDIA&lt;/span&gt; &lt;span class="caps"&gt;GPU&lt;/span&gt;)&lt;/h2&gt;
&lt;h3&gt;Step B1: Create the &lt;span class="caps"&gt;VM&lt;/span&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;In Proxmox, click &lt;strong&gt;Create &lt;span class="caps"&gt;VM&lt;/span&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;OS&lt;/span&gt;:&lt;/strong&gt; Debian 12 or Ubuntu 24.04 &lt;span class="caps"&gt;ISO&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;System:&lt;/strong&gt; Change &lt;strong&gt;&lt;span class="caps"&gt;BIOS&lt;/span&gt;&lt;/strong&gt; to &lt;strong&gt;&lt;span class="caps"&gt;OVMF&lt;/span&gt; (&lt;span class="caps"&gt;UEFI&lt;/span&gt;)&lt;/strong&gt; — required for &lt;span class="caps"&gt;GPU&lt;/span&gt;&amp;nbsp;passthrough.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Machine:&lt;/strong&gt; Set&amp;nbsp;to &lt;code&gt;q35&lt;/code&gt; for better PCIe&amp;nbsp;compatibility.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Disk:&lt;/strong&gt; 60 &lt;span class="caps"&gt;GB&lt;/span&gt;, VirtIO &lt;span class="caps"&gt;SCSI&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;:&lt;/strong&gt; 6–12 cores,&amp;nbsp;type &lt;code&gt;host&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Memory:&lt;/strong&gt; 32 &lt;span class="caps"&gt;GB&lt;/span&gt;&amp;nbsp;minimum.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Step B2: PCIe &lt;span class="caps"&gt;GPU&lt;/span&gt;&amp;nbsp;Passthrough&lt;/h3&gt;
&lt;p&gt;This is the most technical step. You need to prevent the Proxmox host from claiming the &lt;span class="caps"&gt;GPU&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;On the &lt;strong&gt;Proxmox host&lt;/strong&gt;, identify your &lt;span class="caps"&gt;GPU&lt;/span&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;lspci&lt;span class="w"&gt; &lt;/span&gt;-nn&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;nvidia
&lt;span class="c1"&gt;# Example output: 01:00.0 VGA compatible controller [0300]: NVIDIA Corporation GA106 [GeForce RTX 3060] [10de:2504]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note the &lt;span class="caps"&gt;PCI&lt;/span&gt; &lt;span class="caps"&gt;ID&lt;/span&gt;&amp;nbsp;(&lt;code&gt;01:00.0&lt;/code&gt;) and the vendor:device IDs&amp;nbsp;(&lt;code&gt;10de:2504&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Edit &lt;code&gt;/etc/default/grub&lt;/code&gt; and add&amp;nbsp;to &lt;code&gt;GRUB_CMDLINE_LINUX_DEFAULT&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;intel_iommu=on iommu=pt vfio-pci.ids=10de:2504
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;(Replace &lt;code&gt;10de:2504&lt;/code&gt; with your &lt;span class="caps"&gt;GPU&lt;/span&gt;&amp;#8217;s actual IDs. For Intel CPUs&amp;nbsp;use &lt;code&gt;intel_iommu=on&lt;/code&gt;; for &lt;span class="caps"&gt;AMD&lt;/span&gt;&amp;nbsp;use &lt;code&gt;amd_iommu=on&lt;/code&gt;.)&lt;/p&gt;
&lt;p&gt;Update &lt;span class="caps"&gt;GRUB&lt;/span&gt; and&amp;nbsp;reboot:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;update-grub
reboot
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After reboot, add the &lt;span class="caps"&gt;GPU&lt;/span&gt; to the &lt;span class="caps"&gt;VM&lt;/span&gt;: &lt;strong&gt;&lt;span class="caps"&gt;VM&lt;/span&gt; → Hardware → Add → &lt;span class="caps"&gt;PCI&lt;/span&gt; Device&lt;/strong&gt; → select your &lt;span class="caps"&gt;GPU&lt;/span&gt;. Check &lt;strong&gt;All Functions&lt;/strong&gt;, &lt;strong&gt;&lt;span class="caps"&gt;ROM&lt;/span&gt;-Bar&lt;/strong&gt;, and &lt;strong&gt;&lt;span class="caps"&gt;PCI&lt;/span&gt;-Express&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;Step B3: Install &lt;span class="caps"&gt;NVIDIA&lt;/span&gt; Drivers Inside the &lt;span class="caps"&gt;VM&lt;/span&gt;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Inside the VM (Debian 12 example)&lt;/span&gt;
apt&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;build-essential&lt;span class="w"&gt; &lt;/span&gt;dkms
wget&lt;span class="w"&gt; &lt;/span&gt;https://us.download.nvidia.com/XFree86/Linux-x86_64/550.120/NVIDIA-Linux-x86_64-550.120.run
chmod&lt;span class="w"&gt; &lt;/span&gt;+x&lt;span class="w"&gt; &lt;/span&gt;NVIDIA-Linux-x86_64-550.120.run
./NVIDIA-Linux-x86_64-550.120.run&lt;span class="w"&gt; &lt;/span&gt;--no-opengl-files
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Verify:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;nvidia-smi
&lt;span class="c1"&gt;# Should show GPU name, driver version, and CUDA version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then install Docker as in Step A3 and the &lt;span class="caps"&gt;NVIDIA&lt;/span&gt; Container&amp;nbsp;Toolkit:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;distribution&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;/etc/os-release&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$ID$VERSION_ID&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
curl&lt;span class="w"&gt; &lt;/span&gt;-fsSL&lt;span class="w"&gt; &lt;/span&gt;https://nvidia.github.io/libnvidia-container/gpgkey&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;gpg&lt;span class="w"&gt; &lt;/span&gt;--dearmor&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;-L&lt;span class="w"&gt; &lt;/span&gt;https://nvidia.github.io/libnvidia-container/&lt;span class="nv"&gt;$distribution&lt;/span&gt;/libnvidia-container.list&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;sed&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;tee&lt;span class="w"&gt; &lt;/span&gt;/etc/apt/sources.list.d/nvidia-container-toolkit.list

apt&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;nvidia-container-toolkit
nvidia-ctk&lt;span class="w"&gt; &lt;/span&gt;runtime&lt;span class="w"&gt; &lt;/span&gt;configure&lt;span class="w"&gt; &lt;/span&gt;--runtime&lt;span class="o"&gt;=&lt;/span&gt;docker
systemctl&lt;span class="w"&gt; &lt;/span&gt;restart&lt;span class="w"&gt; &lt;/span&gt;docker
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Deploying Ollama + OpenWebUI with Docker&amp;nbsp;Compose&lt;/h2&gt;
&lt;p&gt;Both paths converge here. Create your stack&amp;nbsp;directory:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;~/ollama-stack&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/ollama-stack
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Create &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;ollama&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ollama/ollama:0.5&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ollama&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ollama_data:/root/.ollama&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;11434:11434&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;OLLAMA_KEEP_ALIVE=24h&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;# Keep model in memory between requests&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;OLLAMA_HOST=0.0.0.0&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="c1"&gt;# Listen on all interfaces&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;OLLAMA_NUM_PARALLEL=2&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="c1"&gt;# Max concurrent requests&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# For NVIDIA GPU (comment out if not using GPU):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# deploy:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#   resources:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#     reservations:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#       devices:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#         - driver: nvidia&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#           count: 1&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#           capabilities: [gpu]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# For Intel iGPU (comment out if not using device):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# devices:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#   - /dev/dri:/dev/dri&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;openwebui&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ghcr.io/open-webui/open-webui:main&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;openwebui&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;openwebui_data:/app/backend/data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3000:8080&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;OLLAMA_BASE_URL=http://ollama:11434&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;WEBUI_SECRET_KEY=&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="c1"&gt;# Generate: openssl rand -hex 32&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ollama&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;ollama_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;openwebui_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Generate a secret key and&amp;nbsp;start:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;WEBUI_SECRET_KEY=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;openssl&lt;span class="w"&gt; &lt;/span&gt;rand&lt;span class="w"&gt; &lt;/span&gt;-hex&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;32&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;.env
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Pulling Models and First&amp;nbsp;Chat&lt;/h2&gt;
&lt;h3&gt;Pull Your First&amp;nbsp;Model&lt;/h3&gt;
&lt;p&gt;The easiest way: use OpenWebUI&amp;#8217;s built-in model manager&amp;nbsp;at &lt;code&gt;http://your-server-ip:3000&lt;/code&gt; → Settings → Models → Pull a&amp;nbsp;model.&lt;/p&gt;
&lt;p&gt;Or via &lt;span class="caps"&gt;CLI&lt;/span&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Pull a compact model good for CPU inference (4 GB)&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;pull&lt;span class="w"&gt; &lt;/span&gt;llama3.2:3b

&lt;span class="c1"&gt;# Pull a strong general-purpose model (4.7 GB, needs GPU for speed)&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;pull&lt;span class="w"&gt; &lt;/span&gt;llama3.3:latest

&lt;span class="c1"&gt;# Pull a coding specialist (9 GB)&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;pull&lt;span class="w"&gt; &lt;/span&gt;qwen2.5-coder:14b

&lt;span class="c1"&gt;# List installed models&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;list
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Model Picks for Your&amp;nbsp;Hardware&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Hardware&lt;/th&gt;
&lt;th&gt;Recommended Models&lt;/th&gt;
&lt;th&gt;Speed (tokens/sec)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Intel N100 (&lt;span class="caps"&gt;CPU&lt;/span&gt; only)&lt;/td&gt;
&lt;td&gt;llama3.2:3b, phi3:mini, gemma2:2b&lt;/td&gt;
&lt;td&gt;5–10 t/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;i5-12400 (&lt;span class="caps"&gt;CPU&lt;/span&gt; only)&lt;/td&gt;
&lt;td&gt;llama3.1:8b, mistral:7b, qwen2.5:7b&lt;/td&gt;
&lt;td&gt;8–15 t/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RTX&lt;/span&gt; 3060 12 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;llama3.1:8b, mistral-nemo:12b, qwen2.5:14b&lt;/td&gt;
&lt;td&gt;40–80 t/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RTX&lt;/span&gt; 4060 Ti 16 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;llama3.3:latest, qwen2.5:14b, codestral:22b&lt;/td&gt;
&lt;td&gt;50–90 t/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dual &lt;span class="caps"&gt;RTX&lt;/span&gt; 3060 (24 &lt;span class="caps"&gt;GB&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;mixtral:8x7b, command-r:35b&lt;/td&gt;
&lt;td&gt;25–45 t/s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;First Chat via&amp;nbsp;OpenWebUI&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Open &lt;code&gt;http://your-server-ip:3000&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Create an admin account (first user becomes&amp;nbsp;admin)&lt;/li&gt;
&lt;li&gt;Select your model from the dropdown&amp;nbsp;(top-left)&lt;/li&gt;
&lt;li&gt;Type: &lt;em&gt;&amp;#8220;Explain VLANs like I&amp;#8217;m setting up my first homelab&amp;nbsp;network&amp;#8221;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Watch the tokens stream&amp;nbsp;back&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;OpenWebUI also supports:
- &lt;strong&gt;&lt;span class="caps"&gt;RAG&lt;/span&gt; (Retrieval-Augmented Generation):&lt;/strong&gt; Upload PDFs, markdown files, or code repos and chat with them
- &lt;strong&gt;Multiple models simultaneously:&lt;/strong&gt; Compare answers side-by-side
- &lt;strong&gt;Web search integration:&lt;/strong&gt; Configure a search &lt;span class="caps"&gt;API&lt;/span&gt; (SearXNG, Google) for live data
- &lt;strong&gt;Voice input/output:&lt;/strong&gt; Using browser Web Speech &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Performance&amp;nbsp;Optimization&lt;/h2&gt;
&lt;h3&gt;1. Keep Models in&amp;nbsp;Memory&lt;/h3&gt;
&lt;p&gt;The environment&amp;nbsp;variable &lt;code&gt;OLLAMA_KEEP_ALIVE=24h&lt;/code&gt; keeps the last-used model loaded in &lt;span class="caps"&gt;RAM&lt;/span&gt;/&lt;span class="caps"&gt;VRAM&lt;/span&gt; for 24 hours. Without it, Ollama unloads models after 5 minutes of inactivity, causing a 3–10 second cold-start delay on the next&amp;nbsp;request.&lt;/p&gt;
&lt;h3&gt;2. Adjust Context&amp;nbsp;Window&lt;/h3&gt;
&lt;p&gt;Default context is 2048 tokens. Increase for longer&amp;nbsp;conversations:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;llama3.3:latest
&lt;span class="c1"&gt;# Inside the REPL:&lt;/span&gt;
/set&lt;span class="w"&gt; &lt;/span&gt;parameter&lt;span class="w"&gt; &lt;/span&gt;num_ctx&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8192&lt;/span&gt;
/save&lt;span class="w"&gt; &lt;/span&gt;my-llama3.3-8k
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Or via the &lt;span class="caps"&gt;API&lt;/span&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;curl&lt;span class="w"&gt; &lt;/span&gt;http://localhost:11434/api/generate&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;{&lt;/span&gt;
&lt;span class="s1"&gt;  &amp;quot;model&amp;quot;: &amp;quot;llama3.3:latest&amp;quot;,&lt;/span&gt;
&lt;span class="s1"&gt;  &amp;quot;prompt&amp;quot;: &amp;quot;Hello&amp;quot;,&lt;/span&gt;
&lt;span class="s1"&gt;  &amp;quot;options&amp;quot;: { &amp;quot;num_ctx&amp;quot;: 8192 }&lt;/span&gt;
&lt;span class="s1"&gt;}&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;3. Quantization&amp;nbsp;Level&lt;/h3&gt;
&lt;p&gt;When pulling models, you can specify&amp;nbsp;quantization:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Smaller, faster, slight quality loss&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;pull&lt;span class="w"&gt; &lt;/span&gt;llama3.2:3b-q4_K_M

&lt;span class="c1"&gt;# Larger, slower, best quality&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;pull&lt;span class="w"&gt; &lt;/span&gt;llama3.2:3b-q8_0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;Q4_K_M&lt;/code&gt; is the sweet spot for most homelab use: 4-bit quantization with medium quality preservation, fitting 7B models in ~4 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;VRAM&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;4. Concurrent&amp;nbsp;Requests&lt;/h3&gt;
&lt;p&gt;Ollama can handle parallel requests.&amp;nbsp;Set &lt;code&gt;OLLAMA_NUM_PARALLEL=2&lt;/code&gt; (or more with a powerful &lt;span class="caps"&gt;GPU&lt;/span&gt;) in the Compose file. This lets two family members chat&amp;nbsp;simultaneously.&lt;/p&gt;
&lt;h3&gt;5. Disk&amp;nbsp;I/O&lt;/h3&gt;
&lt;p&gt;Place Ollama data on an NVMe drive if possible. Model loading reads 4–15 &lt;span class="caps"&gt;GB&lt;/span&gt; from disk. On a &lt;span class="caps"&gt;SATA&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt;, a 7B model loads in ~5 seconds; on NVMe, ~1&amp;nbsp;second.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Security&amp;nbsp;Considerations&lt;/h2&gt;
&lt;h3&gt;Do Not Expose to the Public&amp;nbsp;Internet&lt;/h3&gt;
&lt;p&gt;Ollama and OpenWebUI have &lt;strong&gt;no built-in authentication by default&lt;/strong&gt;. They are designed for &lt;span class="caps"&gt;LAN&lt;/span&gt;-only access. If you need remote&amp;nbsp;access:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Use Tailscale or WireGuard &lt;span class="caps"&gt;VPN&lt;/span&gt;&lt;/strong&gt; to connect to your home&amp;nbsp;network&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Put OpenWebUI behind a reverse proxy&lt;/strong&gt; (&lt;span class="caps"&gt;NGINX&lt;/span&gt; Proxy Manager, Traefik, or Caddy) with &lt;span class="caps"&gt;HTTPS&lt;/span&gt; and &lt;span class="caps"&gt;HTTP&lt;/span&gt; Basic&amp;nbsp;Auth&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Never&lt;/strong&gt; port-forward port 3000 or 11434&amp;nbsp;directly&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;OpenWebUI Admin&amp;nbsp;Account&lt;/h3&gt;
&lt;p&gt;The first user to register in OpenWebUI becomes the administrator. If you expose it to even your &lt;span class="caps"&gt;LAN&lt;/span&gt;, set a strong password&amp;nbsp;immediately.&lt;/p&gt;
&lt;h3&gt;Model&amp;nbsp;Provenance&lt;/h3&gt;
&lt;p&gt;Only pull models from Ollama&amp;#8217;s official library or Hugging Face mirrors&amp;nbsp;(via &lt;code&gt;ollama pull&lt;/code&gt;). Untrusted &lt;span class="caps"&gt;GGUF&lt;/span&gt; files can contain malicious code. Ollama&amp;#8217;s library&amp;nbsp;(&lt;code&gt;ollama.com/library&lt;/code&gt;) is curated and&amp;nbsp;safe.&lt;/p&gt;
&lt;h3&gt;Resource&amp;nbsp;Limits&lt;/h3&gt;
&lt;p&gt;In Docker Compose, you can cap &lt;span class="caps"&gt;CPU&lt;/span&gt; and&amp;nbsp;memory:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;ollama&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# ... other config ...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;cpus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;4&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;16G&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This prevents a runaway &lt;span class="caps"&gt;LLM&lt;/span&gt; inference from starving other&amp;nbsp;containers.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Troubleshooting&lt;/h2&gt;
&lt;h3&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;Error: unable to load model — &lt;span class="caps"&gt;CUDA&lt;/span&gt; error: out of&amp;nbsp;memory&amp;#8221;&lt;/h3&gt;
&lt;p&gt;The model is too large for your &lt;span class="caps"&gt;GPU&lt;/span&gt; &lt;span class="caps"&gt;VRAM&lt;/span&gt;. Solutions:
- Pull a smaller quantization:&amp;nbsp;add &lt;code&gt;-q4_K_M&lt;/code&gt; suffix
- Use a smaller model: drop from 13B to 7B
- Enable &lt;span class="caps"&gt;CPU&lt;/span&gt; offloading:&amp;nbsp;set &lt;code&gt;OLLAMA_NUM_GPU=12&lt;/code&gt; (layers to offload to &lt;span class="caps"&gt;GPU&lt;/span&gt;, remainder on &lt;span class="caps"&gt;CPU&lt;/span&gt;)&lt;/p&gt;
&lt;h3&gt;OpenWebUI shows &amp;#8220;Ollama connection&amp;nbsp;refused&amp;#8221;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Verify the Ollama container is&amp;nbsp;running: &lt;code&gt;docker compose ps&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Check&amp;nbsp;that &lt;code&gt;OLLAMA_HOST=0.0.0.0&lt;/code&gt; is set (default binds to 127.0.0.1&amp;nbsp;only)&lt;/li&gt;
&lt;li&gt;From inside the OpenWebUI container,&amp;nbsp;test: &lt;code&gt;curl http://ollama:11434/api/tags&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Extremely slow on &lt;span class="caps"&gt;CPU&lt;/span&gt; (1–3&amp;nbsp;tokens/sec)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;-only 7B models are inherently slow on consumer&amp;nbsp;hardware&lt;/li&gt;
&lt;li&gt;Switch to a 3B model&amp;nbsp;(e.g., &lt;code&gt;llama3.2:3b&lt;/code&gt;) for usable 5–10 t/s on &lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Consider a used &lt;span class="caps"&gt;GPU&lt;/span&gt;: a &lt;span class="caps"&gt;GTX&lt;/span&gt; 1070 8 &lt;span class="caps"&gt;GB&lt;/span&gt; costs ~$80 on eBay and handles 7B models at 20+&amp;nbsp;t/s&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;span class="caps"&gt;LXC&lt;/span&gt; container won&amp;#8217;t start after enabling&amp;nbsp;features&lt;/h3&gt;
&lt;p&gt;Ensure &lt;code&gt;nesting=1&lt;/code&gt; and &lt;code&gt;keyctl=1&lt;/code&gt; are both enabled. If the issue persists, convert to a &lt;span class="caps"&gt;VM&lt;/span&gt; — Docker-in-&lt;span class="caps"&gt;LXC&lt;/span&gt; is convenient but&amp;nbsp;fragile.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Monitoring and&amp;nbsp;Maintenance&lt;/h2&gt;
&lt;h3&gt;Check Ollama&amp;nbsp;Logs&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;logs&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;ollama
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Update&amp;nbsp;Models&lt;/h3&gt;
&lt;p&gt;Ollama models don&amp;#8217;t auto-update. Periodically&amp;nbsp;check:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;list
docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;pull&lt;span class="w"&gt; &lt;/span&gt;llama3.3:latest&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Upgrades if newer version exists&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Update the&amp;nbsp;Stack&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/ollama-stack
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;pull&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="c1"&gt;# Pull latest images&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Recreate with new images&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;image&lt;span class="w"&gt; &lt;/span&gt;prune&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;# Clean old images&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Disk&amp;nbsp;Usage&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;du&lt;span class="w"&gt; &lt;/span&gt;-sh&lt;span class="w"&gt; &lt;/span&gt;/root/.ollama/models/
&lt;span class="c1"&gt;# Delete unused models:&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;ollama&lt;span class="w"&gt; &lt;/span&gt;rm&lt;span class="w"&gt; &lt;/span&gt;phi3:mini
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Beyond the&amp;nbsp;Basics&lt;/h2&gt;
&lt;h3&gt;Add SearXNG for Web&amp;nbsp;Search&lt;/h3&gt;
&lt;p&gt;OpenWebUI supports web search via SearXNG. Add to your Compose&amp;nbsp;file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;searxng&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;searxng/searxng:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;searxng&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8080:8080&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;searxng_data:/etc/searxng&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;SEARXNG_BASE_URL=http://searxng:8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then in OpenWebUI → Settings → Web Search → set SearXNG &lt;span class="caps"&gt;URL&lt;/span&gt;&amp;nbsp;to &lt;code&gt;http://searxng:8080&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Add Stable Diffusion for Image&amp;nbsp;Generation&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;automatic1111&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ghcr.io/ai-dock/stable-diffusion-webui:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;sd-webui&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;7860:7860&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;sd_data:/opt/stable-diffusion-webui&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Add GPU config as with Ollama&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;OpenWebUI can connect to it for image generation within&amp;nbsp;chats.&lt;/p&gt;
&lt;h3&gt;Automate Model Pushes with&amp;nbsp;Ansible&lt;/h3&gt;
&lt;p&gt;If you manage multiple Proxmox nodes, use Ansible to ensure Ollama is deployed everywhere with consistent models. See our &lt;a href="/automating-homelab-ansible"&gt;Automating Your Homelab with Ansible&lt;/a&gt;&amp;nbsp;guide.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;You now have a fully private, self-hosted &lt;span class="caps"&gt;AI&lt;/span&gt; assistant running on your Proxmox homelab. No monthly fees, no data leaving your network, and full control over which models you&amp;nbsp;run.&lt;/p&gt;
&lt;h3&gt;What You&amp;nbsp;Achieved&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;✅ Ollama serving open-weight LLMs on your own&amp;nbsp;hardware&lt;/li&gt;
&lt;li&gt;✅ OpenWebUI providing a polished chat interface accessible from any&amp;nbsp;device&lt;/li&gt;
&lt;li&gt;✅ Optional &lt;span class="caps"&gt;GPU&lt;/span&gt; acceleration for fast&amp;nbsp;inference&lt;/li&gt;
&lt;li&gt;✅ A reproducible Docker Compose&amp;nbsp;stack&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="/nginx-proxy-manager-docker"&gt;Set up &lt;span class="caps"&gt;NGINX&lt;/span&gt; Proxy Manager for local domains&lt;/a&gt;&lt;/strong&gt; — access OpenWebUI&amp;nbsp;at &lt;code&gt;ai.yourlan.local&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="/docker-monitoring-grafana-prometheus"&gt;Monitor your stack with Grafana and Prometheus&lt;/a&gt;&lt;/strong&gt; — track &lt;span class="caps"&gt;GPU&lt;/span&gt; utilization and request&amp;nbsp;latency&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="/best-self-hosted-apps-2026"&gt;Explore more self-hosted apps&lt;/a&gt;&lt;/strong&gt; — build a complete privacy-first&amp;nbsp;toolkit&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="/proxmox-beginner-guide"&gt;Proxmox Beginner Guide&lt;/a&gt;&lt;/strong&gt; — if you&amp;#8217;re new to Proxmox, start&amp;nbsp;here&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What models are you running in your homelab?&lt;/strong&gt; Drop a comment&amp;nbsp;below!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Subscribe to the WordForge newsletter&lt;/strong&gt; for weekly self-hosting guides and Docker&amp;nbsp;tips.&lt;/p&gt;
&lt;/blockquote&gt;</content><category term="Tutorials"/><category term="ollama"/><category term="proxmox"/><category term="self-hosted ai"/><category term="llama"/><category term="openwebui"/><category term="homelab"/><category term="local llm"/><category term="docker"/><category term="gpu passthrough"/></entry><entry><title>Cloudflare Tunnel Homelab Guide: Expose Self-Hosted Services Without Port Forwarding (2026)</title><link href="https://steadypub.com/2026/06/cloudflare-tunnel-homelab/" rel="alternate"/><published>2026-06-06T00:00:00+07:00</published><updated>2026-06-06T00:00:00+07:00</updated><author><name>WordForge Team</name></author><id>tag:steadypub.com,2026-06-06:/2026/06/cloudflare-tunnel-homelab/</id><summary type="html">&lt;p&gt;Step-by-step guide to exposing self-hosted services securely using Cloudflare Tunnel — no port forwarding, no dynamic &lt;span class="caps"&gt;DNS&lt;/span&gt;, and free &lt;span class="caps"&gt;SSL&lt;/span&gt;. Covers Docker setup, Nginx Proxy Manager integration, and Zero Trust access&amp;nbsp;policies.&lt;/p&gt;</summary><content type="html">&lt;hr&gt;
&lt;h1&gt;Cloudflare Tunnel Homelab Guide: Expose Self-Hosted Services Without Port Forwarding&amp;nbsp;(2026)&lt;/h1&gt;
&lt;p&gt;If you run a homelab, you have almost certainly wrestled with the same question: &lt;strong&gt;how do I safely access my services from outside my home network?&lt;/strong&gt; The traditional answer involves port forwarding on your router, dynamic &lt;span class="caps"&gt;DNS&lt;/span&gt; updates, and hoping your &lt;span class="caps"&gt;ISP&lt;/span&gt; hasn&amp;#8217;t put you behind &lt;span class="caps"&gt;CGNAT&lt;/span&gt;. It is fragile, it exposes your home &lt;span class="caps"&gt;IP&lt;/span&gt; address to the world, and it is one misconfigured firewall rule away from&amp;nbsp;disaster.&lt;/p&gt;
&lt;p&gt;Cloudflare Tunnel (powered&amp;nbsp;by &lt;code&gt;cloudflared&lt;/code&gt;) eliminates all of those problems. It creates an encrypted outbound-only connection from your homelab to Cloudflare&amp;#8217;s edge network. No open ports. No dynamic &lt;span class="caps"&gt;DNS&lt;/span&gt;. No exposed &lt;span class="caps"&gt;IP&lt;/span&gt; addresses. And you get Cloudflare&amp;#8217;s DDoS protection, free &lt;span class="caps"&gt;SSL&lt;/span&gt; certificates, and global &lt;span class="caps"&gt;CDN&lt;/span&gt; for&amp;nbsp;free.&lt;/p&gt;
&lt;p&gt;In this guide, Dev walks through everything: what Cloudflare Tunnel actually is, how to deploy it with Docker, how to integrate it with Nginx Proxy Manager, and how to layer on Zero Trust access policies so only you (or your family) can reach sensitive&amp;nbsp;dashboards.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is Cloudflare Tunnel and Why Should You Use&amp;nbsp;It?&lt;/h2&gt;
&lt;p&gt;Cloudflare Tunnel is a secure, outbound-only tunnel that connects your local services to Cloudflare&amp;#8217;s global network. The daemon&amp;nbsp;— &lt;code&gt;cloudflared&lt;/code&gt; — runs inside your homelab and establishes a persistent connection to Cloudflare&amp;#8217;s edge. When a visitor&amp;nbsp;hits &lt;code&gt;jellyfin.yourdomain.com&lt;/code&gt;, Cloudflare proxies that request through the tunnel directly to your local&amp;nbsp;service.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What this&amp;nbsp;replaces:&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Old Way&lt;/th&gt;
&lt;th&gt;Cloudflare Tunnel Way&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Open port 443 on router&lt;/td&gt;
&lt;td&gt;Zero open ports&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dynamic &lt;span class="caps"&gt;DNS&lt;/span&gt; (DuckDNS, afraid.org)&lt;/td&gt;
&lt;td&gt;Not needed — Cloudflare handles &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Let&amp;#8217;s Encrypt cert renewal cron jobs&lt;/td&gt;
&lt;td&gt;Free Cloudflare edge certificates, auto-renewed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;ISP&lt;/span&gt; &lt;span class="caps"&gt;CGNAT&lt;/span&gt; blocks everything&lt;/td&gt;
&lt;td&gt;Works behind any &lt;span class="caps"&gt;NAT&lt;/span&gt;, even double-&lt;span class="caps"&gt;NAT&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Your home &lt;span class="caps"&gt;IP&lt;/span&gt; exposed to attackers&lt;/td&gt;
&lt;td&gt;Only Cloudflare&amp;#8217;s IPs are visible&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;What you need before&amp;nbsp;starting:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;A domain name&lt;/strong&gt; — any registrar works, but you must point its nameservers to Cloudflare (free plan&amp;nbsp;included).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A Cloudflare account&lt;/strong&gt; — free tier is more than enough for homelab&amp;nbsp;use.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A machine running Docker&lt;/strong&gt; — a Proxmox &lt;span class="caps"&gt;LXC&lt;/span&gt;, a Raspberry Pi, an old laptop, anything with Docker&amp;nbsp;works.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Services you want to expose&lt;/strong&gt; — Jellyfin, Nextcloud, Home Assistant, Portainer, whatever you&amp;nbsp;self-host.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Important caveat:&lt;/strong&gt; Cloudflare Tunnel decrypts traffic at their edge and re-encrypts it over the tunnel. For the vast majority of homelab services, this is perfectly fine. If you are handling legally protected data (&lt;span class="caps"&gt;HIPAA&lt;/span&gt;, &lt;span class="caps"&gt;PCI&lt;/span&gt;-&lt;span class="caps"&gt;DSS&lt;/span&gt;, etc.), you probably should not be self-hosting it on a homelab connection anyway. For everything else — media servers, dashboards, family photo galleries — Cloudflare Tunnel is an excellent&amp;nbsp;fit.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Set Up Your Domain on&amp;nbsp;Cloudflare&lt;/h2&gt;
&lt;p&gt;If you already have your domain on Cloudflare, skip to Step&amp;nbsp;2.&lt;/p&gt;
&lt;p&gt;Log into the &lt;a href="https://dash.cloudflare.com/"&gt;Cloudflare dashboard&lt;/a&gt; and click &lt;strong&gt;Add a Site&lt;/strong&gt;. Enter your domain name and follow the onboarding wizard. Cloudflare will scan your existing &lt;span class="caps"&gt;DNS&lt;/span&gt; records and import them&amp;nbsp;automatically.&lt;/p&gt;
&lt;p&gt;Once your domain is added, go to your domain registrar (Namecheap, Porkbun, Google Domains, etc.) and replace the existing nameservers with the two Cloudflare-provided nameservers. Propagation typically takes a few minutes but can take up to 24 hours in rare&amp;nbsp;cases.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In the Cloudflare dashboard, go to &lt;span class="caps"&gt;SSL&lt;/span&gt;/&lt;span class="caps"&gt;TLS&lt;/span&gt; → Overview and set your encryption mode to &amp;#8220;Full.&amp;#8221;&lt;/strong&gt; This ensures traffic between Cloudflare&amp;#8217;s edge and your tunnel is encrypted. Without this, you may see redirect loops or &lt;span class="caps"&gt;SSL&lt;/span&gt; errors when accessing your&amp;nbsp;services.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 2: Create a Cloudflare&amp;nbsp;Tunnel&lt;/h2&gt;
&lt;p&gt;Navigate to &lt;strong&gt;Zero Trust → Networks → Tunnels&lt;/strong&gt; in the Cloudflare dashboard. (If this is your first time in the Zero Trust dashboard, you will be asked to pick a team name — choose anything, it is just an internal identifier and can be changed&amp;nbsp;later.)&lt;/p&gt;
&lt;p&gt;Click &lt;strong&gt;Create a tunnel&lt;/strong&gt;, give it a name&amp;nbsp;(e.g., &lt;code&gt;homelab-tunnel&lt;/code&gt;), and click &lt;strong&gt;Save tunnel&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Cloudflare will now show you installation instructions for various platforms. Choose &lt;strong&gt;Docker&lt;/strong&gt; and copy the token from the command. It looks&amp;nbsp;like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;cloudflare/cloudflared:latest&lt;span class="w"&gt; &lt;/span&gt;tunnel&lt;span class="w"&gt; &lt;/span&gt;--no-autoupdate&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--token&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;eyJhIjoiYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwIn0&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;--token&lt;/code&gt; value is your tunnel&amp;#8217;s authentication credential — treat it like a password. Do not commit it to a public Git repository. We will store it properly in a Docker Compose file in the next&amp;nbsp;step.&lt;/p&gt;
&lt;p&gt;Before you close this screen, scroll down to the &lt;strong&gt;Public Hostnames&lt;/strong&gt; section. This is where you map your domain names to local services. Add your first&amp;nbsp;entry:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Subdomain&lt;/td&gt;
&lt;td&gt;&lt;code&gt;jellyfin&lt;/code&gt; (or whatever you like)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Domain&lt;/td&gt;
&lt;td&gt;&lt;code&gt;yourdomain.com&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Type&lt;/td&gt;
&lt;td&gt;&lt;code&gt;HTTP&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;URL&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;192.168.1.100:8096&lt;/code&gt; (your Jellyfin &lt;span class="caps"&gt;IP&lt;/span&gt; and port)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Click &lt;strong&gt;Save hostname&lt;/strong&gt;. Repeat for any other services you want to expose. You can always come back and add more&amp;nbsp;later.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 3: Deploy cloudflared with Docker&amp;nbsp;Compose&lt;/h2&gt;
&lt;p&gt;While you could add public hostnames one-by-one through the Cloudflare dashboard, a cleaner approach for homelab use is to&amp;nbsp;configure &lt;code&gt;cloudflared&lt;/code&gt; with a &lt;span class="caps"&gt;YAML&lt;/span&gt; config file. This keeps all your tunnel routing rules in one place — version-controlled, documented, and easy to recreate if your server&amp;nbsp;dies.&lt;/p&gt;
&lt;p&gt;Create a directory for your tunnel&amp;nbsp;configuration:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;~/cloudflare-tunnel
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Create&amp;nbsp;a &lt;code&gt;config.yml&lt;/code&gt; inside that&amp;nbsp;directory:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# ~/cloudflare-tunnel/config.yml&lt;/span&gt;
&lt;span class="nt"&gt;tunnel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;YOUR-TUNNEL-ID&lt;/span&gt;
&lt;span class="nt"&gt;credentials-file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/home/nonroot/.cloudflared/YOUR-TUNNEL-ID.json&lt;/span&gt;

&lt;span class="nt"&gt;ingress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Route by hostname to Nginx Proxy Manager&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;jellyfin.yourdomain.com&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;http://nginx-proxy-manager:80&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud.yourdomain.com&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;http://nginx-proxy-manager:80&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;homeassistant.yourdomain.com&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;http://nginx-proxy-manager:80&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;portainer.yourdomain.com&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;http://nginx-proxy-manager:80&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Catch-all: return 404 for unmatched hostnames&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;http_status:404&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Why point everything at Nginx Proxy Manager?&lt;/strong&gt; Instead of configuring each service&amp;#8217;s internal &lt;span class="caps"&gt;IP&lt;/span&gt; and port in Cloudflare&amp;#8217;s dashboard, you route all traffic through Nginx Proxy Manager (&lt;span class="caps"&gt;NPM&lt;/span&gt;). &lt;span class="caps"&gt;NPM&lt;/span&gt; handles &lt;span class="caps"&gt;SSL&lt;/span&gt; termination on the local side and lets you manage subdomains, proxy hosts, and access lists from one clean web &lt;span class="caps"&gt;UI&lt;/span&gt;. If you followed our &lt;a href="/nginx-proxy-manager-docker-compose/"&gt;Nginx Proxy Manager Docker Compose guide&lt;/a&gt;, you already have this set&amp;nbsp;up.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&amp;nbsp;Replace &lt;code&gt;YOUR-TUNNEL-ID&lt;/code&gt; with the actual tunnel &lt;span class="caps"&gt;ID&lt;/span&gt; from the Cloudflare dashboard (visible under Zero Trust → Networks → Tunnels, in the format of a &lt;span class="caps"&gt;UUID&lt;/span&gt;&amp;nbsp;like &lt;code&gt;abcdef12-3456-7890-abcd-ef1234567890&lt;/code&gt;).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now create&amp;nbsp;your &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# ~/cloudflare-tunnel/docker-compose.yml&lt;/span&gt;
&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;cloudflared&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;cloudflare/cloudflared:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;cloudflared&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;tunnel run&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TUNNEL_TOKEN=${TUNNEL_TOKEN}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Alternative: use config.yml with credentials file&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# volumes:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#   - ./config.yml:/home/nonroot/.cloudflared/config.yml:ro&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#   - ./credentials.json:/home/nonroot/.cloudflared/${TUNNEL_ID}.json:ro&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# command: tunnel --config /home/nonroot/.cloudflared/config.yml run&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;proxy_network&lt;/span&gt;

&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;proxy_network&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;external&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nginx-proxy-manager_default&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Replace with your NPM network name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Create&amp;nbsp;a &lt;code&gt;.env&lt;/code&gt; file in the same&amp;nbsp;directory:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# ~/cloudflare-tunnel/.env&lt;/span&gt;
&lt;span class="nv"&gt;TUNNEL_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;eyJhIjoiYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwIn0&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Security tip:&lt;/strong&gt; Never&amp;nbsp;commit &lt;code&gt;.env&lt;/code&gt; to version control. Add it&amp;nbsp;to &lt;code&gt;.gitignore&lt;/code&gt; immediately.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Start the&amp;nbsp;tunnel:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/cloudflare-tunnel
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Check the logs to confirm the&amp;nbsp;connection:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;logs&lt;span class="w"&gt; &lt;/span&gt;cloudflared
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You should see a line&amp;nbsp;like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;INF Registered tunnel connection connIndex=0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you&amp;nbsp;see &lt;code&gt;ERR&lt;/code&gt; messages about failed connections, double-check&amp;nbsp;your &lt;code&gt;TUNNEL_TOKEN&lt;/code&gt; value and ensure your server can&amp;nbsp;reach &lt;code&gt;region1.v2.argotunnel.com&lt;/code&gt; on port 7844&amp;nbsp;(outbound).&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 4: Configure Nginx Proxy Manager for Tunnel&amp;nbsp;Traffic&lt;/h2&gt;
&lt;p&gt;With the tunnel running, traffic arriving&amp;nbsp;at &lt;code&gt;jellyfin.yourdomain.com&lt;/code&gt; is routed through Cloudflare&amp;#8217;s edge, through the encrypted tunnel, and lands at Nginx Proxy Manager on port 80 inside your Docker network. Now you need &lt;span class="caps"&gt;NPM&lt;/span&gt; to know what to do with that&amp;nbsp;request.&lt;/p&gt;
&lt;p&gt;Log into your Nginx Proxy Manager web &lt;span class="caps"&gt;UI&lt;/span&gt;&amp;nbsp;(typically &lt;code&gt;http://192.168.1.100:81&lt;/code&gt;) and add a new proxy&amp;nbsp;host:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Domain Names&lt;/td&gt;
&lt;td&gt;&lt;code&gt;jellyfin.yourdomain.com&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scheme&lt;/td&gt;
&lt;td&gt;&lt;code&gt;http&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Forward Hostname / &lt;span class="caps"&gt;IP&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;192.168.1.100&lt;/code&gt; (or the Docker service name)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Forward Port&lt;/td&gt;
&lt;td&gt;&lt;code&gt;8096&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Block Common Exploits&lt;/td&gt;
&lt;td&gt;✅ Enabled&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Websockets Support&lt;/td&gt;
&lt;td&gt;✅ Enabled (needed for Jellyfin, Home Assistant, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Under the &lt;strong&gt;&lt;span class="caps"&gt;SSL&lt;/span&gt;&lt;/strong&gt;&amp;nbsp;tab:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;SSL&lt;/span&gt; Certificate&lt;/td&gt;
&lt;td&gt;&amp;#8220;None&amp;#8221; — Cloudflare handles &lt;span class="caps"&gt;SSL&lt;/span&gt; at the edge&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Force &lt;span class="caps"&gt;SSL&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;❌ Disabled — otherwise you may create redirect loops&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;HTTP&lt;/span&gt;/2 Support&lt;/td&gt;
&lt;td&gt;✅ Enabled&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;HSTS&lt;/span&gt; Enabled&lt;/td&gt;
&lt;td&gt;✅ Enabled&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;HSTS&lt;/span&gt; Subdomains&lt;/td&gt;
&lt;td&gt;✅ Enabled&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Click &lt;strong&gt;Save&lt;/strong&gt;. Repeat for each service you want to&amp;nbsp;expose.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why &lt;span class="caps"&gt;SSL&lt;/span&gt;=None locally?&lt;/strong&gt; Cloudflare terminates &lt;span class="caps"&gt;SSL&lt;/span&gt; at their edge and forwards traffic to your tunnel over an encrypted &lt;span class="caps"&gt;QUIC&lt;/span&gt; connection. The hop&amp;nbsp;from &lt;code&gt;cloudflared&lt;/code&gt; to &lt;span class="caps"&gt;NPM&lt;/span&gt; inside your Docker network is local traffic and doesn&amp;#8217;t need additional encryption. Adding &lt;span class="caps"&gt;SSL&lt;/span&gt; on that hop adds latency with no security&amp;nbsp;benefit.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 5: Add Cloudflare Zero Trust Access (Optional but&amp;nbsp;Recommended)&lt;/h2&gt;
&lt;p&gt;Exposing a service to the internet means anyone who discovers the &lt;span class="caps"&gt;URL&lt;/span&gt; can attempt to access it. For dashboards like Portainer, Proxmox, or Grafana — tools you definitely do not want random internet users interacting with — add an authentication layer with Cloudflare Zero&amp;nbsp;Trust.&lt;/p&gt;
&lt;p&gt;In the Cloudflare Zero Trust dashboard, go to &lt;strong&gt;Access → Applications&lt;/strong&gt; and click &lt;strong&gt;Add an application&lt;/strong&gt;. Choose &lt;strong&gt;Self-hosted&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Configure:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Application name&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Portainer&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Subdomain&lt;/td&gt;
&lt;td&gt;&lt;code&gt;portainer&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Domain&lt;/td&gt;
&lt;td&gt;&lt;code&gt;yourdomain.com&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Identity providers&lt;/td&gt;
&lt;td&gt;Select at least one (Google, GitHub, or One-Time &lt;span class="caps"&gt;PIN&lt;/span&gt; via email are all free)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Under &lt;strong&gt;Policies&lt;/strong&gt;, add a&amp;nbsp;rule:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Policy name&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Allow family&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Include&lt;/td&gt;
&lt;td&gt;Emails ending&amp;nbsp;in &lt;code&gt;@yourdomain.com&lt;/code&gt; (or list specific email addresses)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Save the policy and the application. Now when anyone&amp;nbsp;visits &lt;code&gt;portainer.yourdomain.com&lt;/code&gt;, they will first see a Cloudflare login page. Only authenticated users matching your policy can proceed to the actual Portainer &lt;span class="caps"&gt;UI&lt;/span&gt;. No &lt;span class="caps"&gt;VPN&lt;/span&gt; needed, no app installed — just a browser&amp;nbsp;login.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For services you want fully public (like a blog), simply skip the Zero Trust Access step.&lt;/strong&gt; Cloudflare Tunnel will serve them normally without any authentication&amp;nbsp;gate.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Advanced: Using config.yml with Multiple&amp;nbsp;Networks&lt;/h2&gt;
&lt;p&gt;If you run services across multiple Docker networks or on different physical hosts,&amp;nbsp;the &lt;code&gt;ingress&lt;/code&gt; rules&amp;nbsp;in &lt;code&gt;config.yml&lt;/code&gt; give you full&amp;nbsp;flexibility:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;ingress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Service on Docker network &amp;quot;media&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;jellyfin.yourdomain.com&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;http://jellyfin:8096&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;originRequest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;connectTimeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;30s&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;noTLSVerify&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Service on a different physical host (Proxmox LXC at 192.168.1.50)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;proxmox.yourdomain.com&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;https://192.168.1.50:8006&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;originRequest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;noTLSVerify&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Proxmox uses self-signed certs&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# SSH access via browser (Cloudflare&amp;#39;s browser-based SSH terminal)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ssh.yourdomain.com&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ssh://192.168.1.1:22&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Return 404 for any hostname not explicitly mapped&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;http_status:404&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To use this approach, switch your Docker Compose command&amp;nbsp;to &lt;code&gt;tunnel --config /home/nonroot/.cloudflared/config.yml run&lt;/code&gt; and mount both the config file and the credentials &lt;span class="caps"&gt;JSON&lt;/span&gt; file (downloaded from Cloudflare dashboard under the tunnel&amp;#8217;s configuration&amp;nbsp;tab).&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Troubleshooting Common&amp;nbsp;Issues&lt;/h2&gt;
&lt;h3&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;Error 1033: Argo Tunnel&amp;nbsp;error&amp;#8221;&lt;/h3&gt;
&lt;p&gt;This means Cloudflare could not reach your tunnel.&amp;nbsp;Check &lt;code&gt;docker logs cloudflared&lt;/code&gt;. Common&amp;nbsp;causes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;TUNNEL_TOKEN&lt;/code&gt; is incorrect or&amp;nbsp;expired.&lt;/li&gt;
&lt;li&gt;Your server cannot reach Cloudflare&amp;#8217;s tunnel endpoints (firewall blocking outbound &lt;span class="caps"&gt;UDP&lt;/span&gt;/&lt;span class="caps"&gt;TCP&lt;/span&gt; on port&amp;nbsp;7844).&lt;/li&gt;
&lt;li&gt;The tunnel is stopped or&amp;nbsp;crashed.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;Too Many Redirects&amp;#8221; in the&amp;nbsp;browser&lt;/h3&gt;
&lt;p&gt;This is almost always caused by &lt;span class="caps"&gt;SSL&lt;/span&gt; misconfiguration.&amp;nbsp;Fixes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;In Cloudflare &lt;span class="caps"&gt;SSL&lt;/span&gt;/&lt;span class="caps"&gt;TLS&lt;/span&gt; settings, ensure the mode is set to &lt;strong&gt;Full&lt;/strong&gt;, not&amp;nbsp;Flexible.&lt;/li&gt;
&lt;li&gt;In Nginx Proxy Manager, ensure &lt;strong&gt;Force &lt;span class="caps"&gt;SSL&lt;/span&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;span class="caps"&gt;SSL&lt;/span&gt; Certificate&lt;/strong&gt; are both set to &lt;strong&gt;None&lt;/strong&gt; on the proxy host for tunnel&amp;nbsp;traffic.&lt;/li&gt;
&lt;li&gt;Clear your browser cache or test in an incognito&amp;nbsp;window.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;502 Bad Gateway&amp;#8221; from&amp;nbsp;Cloudflare&lt;/h3&gt;
&lt;p&gt;Your tunnel is connected, but it cannot reach the backend service.&amp;nbsp;Check:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Is the service actually&amp;nbsp;running? &lt;code&gt;docker ps | grep jellyfin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Are &lt;code&gt;cloudflared&lt;/code&gt; and your service on the same Docker network? If using the simple token&amp;nbsp;method, &lt;code&gt;cloudflared&lt;/code&gt; needs to reach the service by its Docker host &lt;span class="caps"&gt;IP&lt;/span&gt; and port. If&amp;nbsp;using &lt;code&gt;config.yml&lt;/code&gt;, ensure the service name in&amp;nbsp;the &lt;code&gt;service&lt;/code&gt; field resolves from&amp;nbsp;the &lt;code&gt;cloudflared&lt;/code&gt; container.&lt;/li&gt;
&lt;li&gt;Is your &lt;span class="caps"&gt;NPM&lt;/span&gt; proxy host pointing to the correct internal &lt;span class="caps"&gt;IP&lt;/span&gt; and&amp;nbsp;port?&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Slow performance on media&amp;nbsp;streaming&lt;/h3&gt;
&lt;p&gt;Cloudflare Tunnel is not designed for high-bandwidth video streaming through their free tier. While it works, Cloudflare&amp;#8217;s Terms of Service (Section 2.8) prohibit serving disproportionate amounts of video or other non-&lt;span class="caps"&gt;HTML&lt;/span&gt; content through their &lt;span class="caps"&gt;CDN&lt;/span&gt; on the free plan. For streaming Jellyfin or Plex to remote users,&amp;nbsp;consider:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Tailscale&lt;/strong&gt; (free for up to 100 devices) — direct peer-to-peer encrypted&amp;nbsp;connection.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WireGuard &lt;span class="caps"&gt;VPN&lt;/span&gt;&lt;/strong&gt; — self-hosted on a cheap &lt;span class="caps"&gt;VPS&lt;/span&gt; as a&amp;nbsp;relay.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Direct port forwarding&lt;/strong&gt; for streaming only (with proper firewall rules and&amp;nbsp;fail2ban).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Use Cloudflare Tunnel for the web &lt;span class="caps"&gt;UI&lt;/span&gt;, metadata, and authentication; route the actual video stream through a separate path if you have more than a handful of remote&amp;nbsp;users.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Security&amp;nbsp;Checklist&lt;/h2&gt;
&lt;p&gt;Before you walk away from this setup, run through these security&amp;nbsp;essentials:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[ ] &lt;strong&gt;Cloudflare &lt;span class="caps"&gt;SSL&lt;/span&gt;/&lt;span class="caps"&gt;TLS&lt;/span&gt; mode set to Full&lt;/strong&gt; (not Flexible — Flexible sends unencrypted traffic between Cloudflare and your tunnel, which defeats the&amp;nbsp;purpose).&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Tunnel token stored&amp;nbsp;in &lt;code&gt;.env&lt;/code&gt;, not committed to&amp;nbsp;Git.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;&lt;span class="caps"&gt;NPM&lt;/span&gt; &amp;#8220;Block Common Exploits&amp;#8221; enabled on every proxy&amp;nbsp;host.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Zero Trust Access policies applied on admin dashboards&lt;/strong&gt; (Portainer, Proxmox, Grafana, Cockpit,&amp;nbsp;etc.).&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Cloudflare &lt;span class="caps"&gt;WAF&lt;/span&gt; (Web Application Firewall) enabled&lt;/strong&gt; — free tier includes basic DDoS protection and managed rulesets. Go to Security → &lt;span class="caps"&gt;WAF&lt;/span&gt; in the Cloudflare&amp;nbsp;dashboard.&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Bot Fight Mode enabled&lt;/strong&gt; (Security → Bots) — blocks basic automated scanners at the&amp;nbsp;edge.&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Regularly review Cloudflare Access audit logs&lt;/strong&gt; (Zero Trust → Logs → Access) to see who is authenticating and from&amp;nbsp;where.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;What We&amp;nbsp;Covered&lt;/h2&gt;
&lt;p&gt;Cloudflare Tunnel gives you a production-grade way to expose self-hosted services without touching your router&amp;#8217;s port forwarding rules. You get free &lt;span class="caps"&gt;SSL&lt;/span&gt;, DDoS protection, and optional authentication gates — all running on infrastructure that serves a significant portion of the&amp;nbsp;internet.&lt;/p&gt;
&lt;p&gt;In this guide, you set&amp;nbsp;up:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A Cloudflare Tunnel from your homelab to Cloudflare&amp;#8217;s&amp;nbsp;edge.&lt;/li&gt;
&lt;li&gt;Docker Compose deployment&amp;nbsp;of &lt;code&gt;cloudflared&lt;/code&gt; with environment-based token&amp;nbsp;management.&lt;/li&gt;
&lt;li&gt;Nginx Proxy Manager integration so you manage all routing from one &lt;span class="caps"&gt;UI&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;Zero Trust Access policies to gate sensitive services behind email-based&amp;nbsp;authentication.&lt;/li&gt;
&lt;li&gt;Troubleshooting steps for the three most common deployment&amp;nbsp;issues.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;From here, consider exploring Cloudflare&amp;#8217;s &lt;strong&gt;&lt;span class="caps"&gt;WAF&lt;/span&gt; custom rules&lt;/strong&gt; to block specific countries or &lt;span class="caps"&gt;IP&lt;/span&gt; ranges, setting up &lt;strong&gt;Cloudflare Pages&lt;/strong&gt; for a static blog (perhaps using Pelican — our favorite), or adding &lt;strong&gt;Cloudflare R2&lt;/strong&gt; as an S3-compatible backup target for your homelab data. The free tier is remarkably generous for personal&amp;nbsp;projects.&lt;/p&gt;
&lt;p&gt;Your homelab services are now reachable, fast, and — most importantly — secure. All without opening a single port on your&amp;nbsp;router.&lt;/p&gt;</content><category term="Networking"/><category term="cloudflare tunnel"/><category term="cloudflared"/><category term="reverse proxy"/><category term="homelab networking"/><category term="port forwarding"/><category term="zero trust"/></entry><entry><title>Home Assistant Docker Compose for Homelab 2026: From Container to Smart Home Stack</title><link href="https://steadypub.com/2026/06/home-assistant-docker-compose-homelab/" rel="alternate"/><published>2026-06-06T00:00:00+07:00</published><updated>2026-06-06T00:00:00+07:00</updated><author><name>WordForge Team</name></author><id>tag:steadypub.com,2026-06-06:/2026/06/home-assistant-docker-compose-homelab/</id><summary type="html">&lt;p&gt;Deploy Home Assistant with Docker Compose in your homelab. Step-by-step guide for Proxmox, mini PCs, and Raspberry Pi. Includes Zigbee dongle passthrough, reverse proxy, &lt;span class="caps"&gt;MQTT&lt;/span&gt;, and a Docker Compose vs &lt;span class="caps"&gt;HAOS&lt;/span&gt; decision&amp;nbsp;tree.&lt;/p&gt;</summary><content type="html">&lt;hr&gt;
&lt;h1&gt;Home Assistant Docker Compose for Homelab 2026: From Container to Smart Home&amp;nbsp;Stack&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~14 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab owners who want a self-hosted smart home without vendor&amp;nbsp;lock-in&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Introduction: Docker Compose for Home Assistant — Why It Makes Sense in&amp;nbsp;2026&lt;/h2&gt;
&lt;p&gt;Home Assistant has grown from a hobbyist project into the most popular open-source smart home platform on the planet. The r/homeassistant subreddit sits at over 250,000 members, and every major smart device manufacturer now either supports Home Assistant directly or has a community integration that works better than the official app. But there is one persistent debate that trips up newcomers: &lt;strong&gt;should you run Home Assistant &lt;span class="caps"&gt;OS&lt;/span&gt; (&lt;span class="caps"&gt;HAOS&lt;/span&gt;), Home Assistant Container (Docker), or Home Assistant Core (bare&amp;nbsp;Python)?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you already run a homelab — Proxmox, a mini &lt;span class="caps"&gt;PC&lt;/span&gt;, or even a Raspberry Pi 5 with a handful of Docker containers — the answer leans strongly toward &lt;strong&gt;Docker Compose&lt;/strong&gt;. Here is why: you already have Docker running for your media server, reverse proxy, &lt;span class="caps"&gt;DNS&lt;/span&gt; filter, and monitoring stack. Adding Home Assistant as another Compose service keeps your infrastructure uniform, your management tooling consistent, and your backup strategy identical across every&amp;nbsp;service.&lt;/p&gt;
&lt;p&gt;This guide covers the complete stack: Home Assistant Core in Docker, Mosquitto &lt;span class="caps"&gt;MQTT&lt;/span&gt;, Zigbee2MQTT for &lt;span class="caps"&gt;USB&lt;/span&gt; dongle integration, an optional Node-&lt;span class="caps"&gt;RED&lt;/span&gt; automation sidecar, reverse proxy with Nginx Proxy Manager, remote access via Cloudflare Tunnel, and Proxmox &lt;span class="caps"&gt;LXC&lt;/span&gt; &lt;span class="caps"&gt;USB&lt;/span&gt; passthrough. Every code block is copy-paste ready for&amp;nbsp;2026.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why Docker Compose for Home Assistant in a&amp;nbsp;Homelab?&lt;/h2&gt;
&lt;p&gt;Before writing a single &lt;span class="caps"&gt;YAML&lt;/span&gt; line, you need to understand the tradeoffs. Home Assistant offers three official installation methods, and they are not&amp;nbsp;interchangeable.&lt;/p&gt;
&lt;h3&gt;&lt;span class="caps"&gt;HAOS&lt;/span&gt; vs Docker Compose vs Core: The Decision&amp;nbsp;Tree&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;What It Is&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;Watch Out For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;HAOS&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Full &lt;span class="caps"&gt;OS&lt;/span&gt; image (rootfs or &lt;span class="caps"&gt;VM&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;Raspberry Pi dedicated, &lt;span class="caps"&gt;VM&lt;/span&gt;-only homelab&lt;/td&gt;
&lt;td&gt;Steals an entire device or &lt;span class="caps"&gt;VM&lt;/span&gt;; can&amp;#8217;t run other Docker containers alongside&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Docker Compose&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;homeassistant/home-assistant&lt;/code&gt; container&lt;/td&gt;
&lt;td&gt;Homelab with existing Docker stack&lt;/td&gt;
&lt;td&gt;No add-on store; replace add-ons with separate containers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Home Assistant Core&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pip install homeassistant&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Python developers, custom integrations&lt;/td&gt;
&lt;td&gt;No supervisor; manual &lt;span class="caps"&gt;OS&lt;/span&gt; dependency management&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Choose &lt;span class="caps"&gt;HAOS&lt;/span&gt; if:&lt;/strong&gt; You want a dedicated appliance, do not run other server workloads, and want the one-click add-on store for things like Node-&lt;span class="caps"&gt;RED&lt;/span&gt;, ESPHome, and&amp;nbsp;DuckDNS.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Choose Docker Compose if:&lt;/strong&gt; You already run Docker for other services (Jellyfin, Nginx Proxy Manager, Pihole, Grafana), you use Portainer or Dockge for container management, and you are comfortable running companion services as separate containers instead of&amp;nbsp;add-ons.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Choose Core if:&lt;/strong&gt; You are developing custom integrations in Python and need direct filesystem access without container&amp;nbsp;isolation.&lt;/p&gt;
&lt;h3&gt;The Add-On Question (and the Docker&amp;nbsp;Workaround)&lt;/h3&gt;
&lt;p&gt;The number-one reason people hesitate to use Docker is the &lt;strong&gt;add-on store&lt;/strong&gt;. In &lt;span class="caps"&gt;HAOS&lt;/span&gt;, add-ons are pre-packaged Docker containers that Home Assistant manages for you — Node-&lt;span class="caps"&gt;RED&lt;/span&gt;, ESPHome, Mosquitto, Zigbee2MQTT, and file editors all install with one&amp;nbsp;click.&lt;/p&gt;
&lt;p&gt;In Docker Compose, you simply run each add-on as a &lt;strong&gt;separate container&lt;/strong&gt; in the same Compose stack. The result is identical — Mosquitto still talks to Home Assistant over the internal Docker network; Zigbee2MQTT still publishes to &lt;span class="caps"&gt;MQTT&lt;/span&gt; — but you manage them&amp;nbsp;through &lt;code&gt;docker compose pull &amp;amp;&amp;amp; docker compose up -d&lt;/code&gt; instead of the Supervisor &lt;span class="caps"&gt;UI&lt;/span&gt;. For homelabbers already managing 20 containers, this is a feature, not a bug: &lt;strong&gt;one workflow, one update cadence, no split-brain management&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;For the few add-ons that do not have standalone Docker images (like the Google Drive Backup add-on), you use &lt;strong&gt;&lt;span class="caps"&gt;HACS&lt;/span&gt; (Home Assistant Community Store)&lt;/strong&gt; to install equivalent custom integrations directly inside the Home Assistant container — no Supervisor&amp;nbsp;required.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What You&amp;#8217;ll&amp;nbsp;Need&lt;/h2&gt;
&lt;h3&gt;Hardware&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tier&lt;/th&gt;
&lt;th&gt;Hardware&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Storage&lt;/th&gt;
&lt;th&gt;Power&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Budget&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Raspberry Pi 5 (8 &lt;span class="caps"&gt;GB&lt;/span&gt;) + 128 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;8 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;128 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;8–12W&lt;/td&gt;
&lt;td&gt;Starter smart home (lights, sensors, 1–2 cameras)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Standard&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Intel N100 Mini &lt;span class="caps"&gt;PC&lt;/span&gt; (Beelink S12 Pro, Minisforum &lt;span class="caps"&gt;UN100&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;16 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;256 &lt;span class="caps"&gt;GB&lt;/span&gt; NVMe&lt;/td&gt;
&lt;td&gt;12–18W&lt;/td&gt;
&lt;td&gt;Full smart home + Frigate &lt;span class="caps"&gt;NVR&lt;/span&gt; + 4–8 cameras&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Enthusiast&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Proxmox &lt;span class="caps"&gt;VM&lt;/span&gt; (4 vCPU, 8 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;) on existing homelab server&lt;/td&gt;
&lt;td&gt;8 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;64 &lt;span class="caps"&gt;GB&lt;/span&gt; virtual disk&lt;/td&gt;
&lt;td&gt;Shared&lt;/td&gt;
&lt;td&gt;Consolidation — run &lt;span class="caps"&gt;HA&lt;/span&gt; alongside other VMs/CTs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Power User&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Intel N305 or &lt;span class="caps"&gt;AMD&lt;/span&gt; Ryzen 5825U Mini &lt;span class="caps"&gt;PC&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;32 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;512 &lt;span class="caps"&gt;GB&lt;/span&gt; NVMe&lt;/td&gt;
&lt;td&gt;25–40W&lt;/td&gt;
&lt;td&gt;Frigate &lt;span class="caps"&gt;AI&lt;/span&gt; object detection, Whisper voice, Matter controller&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Zigbee/Z-Wave &lt;span class="caps"&gt;USB&lt;/span&gt; Dongle Recommendations&amp;nbsp;(2026):&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Sonoff ZBDongle-P (&lt;span class="caps"&gt;CC2652P&lt;/span&gt;)&lt;/strong&gt; — ~$15, excellent range, Zigbee2MQTT and &lt;span class="caps"&gt;ZHA&lt;/span&gt;&amp;nbsp;compatible&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ConBee &lt;span class="caps"&gt;III&lt;/span&gt; (RaspBee &lt;span class="caps"&gt;III&lt;/span&gt; for Pi &lt;span class="caps"&gt;GPIO&lt;/span&gt;)&lt;/strong&gt; — ~$40, deCONZ or Zigbee2MQTT, very&amp;nbsp;mature&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Home Assistant SkyConnect (&lt;span class="caps"&gt;EFR32MG21&lt;/span&gt;)&lt;/strong&gt; — ~$30, official Nabu Casa hardware, Thread/Matter ready, &lt;span class="caps"&gt;ZHA&lt;/span&gt;&amp;nbsp;native&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Aeotec Z-Stick 7 (Z-Wave 700 series)&lt;/strong&gt; — ~$50, best Z-Wave dongle, 700-series for long&amp;nbsp;range&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Software&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Docker Engine&lt;/strong&gt; 24+ and &lt;strong&gt;Docker Compose&lt;/strong&gt; v2 (bundled with&amp;nbsp;Docker)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Git&lt;/strong&gt; for version-tracking your Compose&amp;nbsp;files&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Static &lt;span class="caps"&gt;IP&lt;/span&gt;&lt;/strong&gt; or mDNS (Avahi) on the host so integrations can discover it&amp;nbsp;reliably&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Project&amp;nbsp;Structure&lt;/h2&gt;
&lt;p&gt;Create a clean directory on your Docker host. Version-control it with Git — your Compose file is infrastructure as code, and you will thank yourself after the first&amp;nbsp;accidental &lt;code&gt;docker compose down&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;~/docker/homeassistant/
├── .env                  # Version tags and secrets
├── docker-compose.yml    # Main stack
├── mosquitto/
│   └── config/
│       └── mosquitto.conf
├── zigbee2mqtt/
│   └── data/
│       └── configuration.yaml
├── node-red/
│   └── data/
└── homeassistant/
    └── config/           # Auto-created on first run
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;.env&lt;/code&gt; file pins exact versions so you control when updates&amp;nbsp;happen:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# .env — Version pins for Home Assistant smart home stack&lt;/span&gt;
&lt;span class="c1"&gt;# Update these manually and review changelogs before bumping&lt;/span&gt;
&lt;span class="nv"&gt;HA_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2026&lt;/span&gt;.6.0
&lt;span class="nv"&gt;MOSQUITTO_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;.0.18
&lt;span class="nv"&gt;Z2M_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.37.0
&lt;span class="nv"&gt;NODE_RED_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;.0.2
&lt;span class="nv"&gt;TZ&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Asia/Jakarta
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Volume strategy: every container gets a bind-mounted directory&amp;nbsp;under &lt;code&gt;~/docker/homeassistant/&lt;/code&gt;. This keeps backups simple&amp;nbsp;— &lt;code&gt;rsync -a ~/docker/homeassistant/ /mnt/nas/backups/homeassistant/&lt;/code&gt; captures your entire smart home config in one&amp;nbsp;command.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The Docker Compose&amp;nbsp;File&lt;/h2&gt;
&lt;p&gt;Below is the&amp;nbsp;complete &lt;code&gt;docker-compose.yml&lt;/code&gt;. Each service is explained after the&amp;nbsp;block.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# docker-compose.yml — Home Assistant Smart Home Stack&lt;/span&gt;
&lt;span class="c1"&gt;# Deploy: docker compose up -d&lt;/span&gt;
&lt;span class="c1"&gt;# Update: docker compose pull &amp;amp;&amp;amp; docker compose up -d&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# ── Core: Home Assistant ──────────────────────────────&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;homeassistant&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;homeassistant/home-assistant:${HA_VERSION}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;homeassistant&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;network_mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;host&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;privileged&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Required for USB device access&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TZ=${TZ}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./homeassistant/config:/config&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/run/dbus:/run/dbus:ro&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Bluetooth (optional)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# If using bridge network instead of host, add:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# ports:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#   - &amp;quot;8123:8123&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# and comment out network_mode: host&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# ── MQTT Broker: Mosquitto ────────────────────────────&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;mosquitto&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;eclipse-mosquitto:${MOSQUITTO_VERSION}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;mosquitto&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1883:1883&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;# MQTT&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;9001:9001&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;# WebSockets&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./mosquitto/config/mosquitto.conf:/mosquitto/config/mosquitto.conf:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;mosquitto_data:/mosquitto/data&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;mosquitto_log:/mosquitto/log&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# ── Zigbee Bridge: Zigbee2MQTT ────────────────────────&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;zigbee2mqtt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;koenkk/zigbee2mqtt:${Z2M_VERSION}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;zigbee2mqtt&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;mosquitto&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;devices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/dev/serial/by-id/usb-Silicon_Labs_CP2102N_USB_to_UART_Bridge_Controller_XXXXXXXX:/dev/ttyUSB0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./zigbee2mqtt/data:/app/data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TZ=${TZ}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# network_mode: host  # Uncomment if discovery fails on bridge&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# ── Optional: Node-RED Automation ─────────────────────&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;node-red&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nodered/node-red:${NODE_RED_VERSION}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;node-red&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1880:1880&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./node-red/data:/data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TZ=${TZ}&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;mosquitto_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;mosquitto_log&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Service-by-Service&amp;nbsp;Explanation&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Home Assistant&amp;nbsp;(&lt;code&gt;network_mode: host&lt;/code&gt;)&lt;/strong&gt;: Using host networking is the officially recommended approach for the Docker container because Home Assistant relies on mDNS (Bonjour/Avahi), UPnP, and &lt;span class="caps"&gt;DHCP&lt;/span&gt; discovery to find devices on your &lt;span class="caps"&gt;LAN&lt;/span&gt;. Without host mode, many auto-discovered integrations (Google Cast, Apple HomeKit, Philips Hue, Sonos) silently break.&amp;nbsp;The &lt;code&gt;privileged: true&lt;/code&gt; flag gives the container access to &lt;span class="caps"&gt;USB&lt;/span&gt; devices — essential for Zigbee/Z-Wave dongles. If your security policy forbids host networking, use a bridge network with explicit port mappings and accept that device discovery will be&amp;nbsp;manual.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mosquitto (bridge network)&lt;/strong&gt;: This is a standard &lt;span class="caps"&gt;MQTT&lt;/span&gt; broker. It runs on the default bridge network so Home Assistant can reach it&amp;nbsp;at &lt;code&gt;mosquitto:1883&lt;/code&gt; (Docker &lt;span class="caps"&gt;DNS&lt;/span&gt;) if needed, but since Home Assistant is on host mode, you configure the &lt;span class="caps"&gt;MQTT&lt;/span&gt; integration&amp;nbsp;with &lt;code&gt;localhost:1883&lt;/code&gt; instead. The bridge mode keeps Mosquitto isolated while still being reachable from the &lt;span class="caps"&gt;LAN&lt;/span&gt; for non-Docker &lt;span class="caps"&gt;MQTT&lt;/span&gt;&amp;nbsp;clients.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Zigbee2MQTT (bridge with device passthrough)&lt;/strong&gt;:&amp;nbsp;The &lt;code&gt;devices:&lt;/code&gt; block maps the physical &lt;span class="caps"&gt;USB&lt;/span&gt; dongle into the container. Find your dongle&amp;#8217;s stable path&amp;nbsp;with &lt;code&gt;ls -la /dev/serial/by-id/&lt;/code&gt; — this symlink survives reboots,&amp;nbsp;unlike &lt;code&gt;/dev/ttyUSB0&lt;/code&gt; which can change&amp;nbsp;numbering.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Node-&lt;span class="caps"&gt;RED&lt;/span&gt; (bridge network, optional)&lt;/strong&gt;: If you prefer visual flow-based automation over Home Assistant&amp;#8217;s built-in &lt;span class="caps"&gt;YAML&lt;/span&gt; automations, Node-&lt;span class="caps"&gt;RED&lt;/span&gt; is the gold standard. It connects to Home Assistant via the Home Assistant WebSocket &lt;span class="caps"&gt;API&lt;/span&gt; and to &lt;span class="caps"&gt;MQTT&lt;/span&gt; via the&amp;nbsp;broker.&lt;/p&gt;
&lt;h3&gt;Mosquitto&amp;nbsp;Configuration&lt;/h3&gt;
&lt;p&gt;Create &lt;code&gt;./mosquitto/config/mosquitto.conf&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="na"&gt;listener 1883&lt;/span&gt;
&lt;span class="na"&gt;allow_anonymous false&lt;/span&gt;
&lt;span class="na"&gt;password_file /mosquitto/config/passwd&lt;/span&gt;
&lt;span class="na"&gt;persistence true&lt;/span&gt;
&lt;span class="na"&gt;persistence_location /mosquitto/data&lt;/span&gt;
&lt;span class="na"&gt;log_dest stdout&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Set the &lt;span class="caps"&gt;MQTT&lt;/span&gt; credentials (run this after the&amp;nbsp;first &lt;code&gt;docker compose up -d mosquitto&lt;/code&gt;):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mosquitto&lt;span class="w"&gt; &lt;/span&gt;mosquitto_passwd&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;/mosquitto/config/passwd&lt;span class="w"&gt; &lt;/span&gt;homeassistant
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Use these credentials when configuring the &lt;span class="caps"&gt;MQTT&lt;/span&gt; integration in Home&amp;nbsp;Assistant.&lt;/p&gt;
&lt;h3&gt;Zigbee2MQTT&amp;nbsp;Configuration&lt;/h3&gt;
&lt;p&gt;Create &lt;code&gt;./zigbee2mqtt/data/configuration.yaml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;homeassistant&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="nt"&gt;permit_join&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;false&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Enable only when pairing new devices&lt;/span&gt;
&lt;span class="nt"&gt;mqtt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;mqtt://localhost:1883&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;homeassistant&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;your_password_here&lt;/span&gt;
&lt;span class="nt"&gt;serial&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/dev/ttyUSB0&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;adapter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;zstack&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# For Sonoff ZBDongle-P. Use &amp;#39;deconz&amp;#39; for ConBee&lt;/span&gt;
&lt;span class="nt"&gt;frontend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;8080&lt;/span&gt;
&lt;span class="nt"&gt;advanced&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;network_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;GENERATE_A_RANDOM_KEY&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Generate&amp;nbsp;the &lt;code&gt;network_key&lt;/code&gt; with &lt;code&gt;openssl rand -hex 16&lt;/code&gt; — this encrypts your Zigbee network and must be the same if you ever re-pair devices. Save it somewhere&amp;nbsp;safe.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step-by-Step&amp;nbsp;Installation&lt;/h2&gt;
&lt;h3&gt;Step 1 — Prepare Your&amp;nbsp;Host&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;On Proxmox (&lt;span class="caps"&gt;LXC&lt;/span&gt; container):&lt;/strong&gt;
Create an unprivileged &lt;span class="caps"&gt;LXC&lt;/span&gt; container with Debian 12,&amp;nbsp;enable &lt;code&gt;nesting=1&lt;/code&gt; and &lt;code&gt;keyctl=1&lt;/code&gt; in the container options. Install Docker inside the &lt;span class="caps"&gt;LXC&lt;/span&gt;. For &lt;span class="caps"&gt;USB&lt;/span&gt; passthrough, add the &lt;span class="caps"&gt;LXC&lt;/span&gt; device mapping in Proxmox: select the container → Resources → Add → Device Passthrough&amp;nbsp;→ &lt;code&gt;/dev/serial/by-id/usb-Silicon_Labs_...&lt;/code&gt; — no reboot needed. If you haven&amp;#8217;t set up Proxmox yet, see our &lt;a href="https://wordforge.fifoenix.com/2026/06/proxmox-beginner-guide-2026/"&gt;Proxmox beginner guide&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;On Ubuntu/Debian (bare metal or &lt;span class="caps"&gt;VM&lt;/span&gt;):&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Install Docker (official repo method, 2026)&lt;/span&gt;
curl&lt;span class="w"&gt; &lt;/span&gt;-fsSL&lt;span class="w"&gt; &lt;/span&gt;https://get.docker.com&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;sh
sudo&lt;span class="w"&gt; &lt;/span&gt;usermod&lt;span class="w"&gt; &lt;/span&gt;-aG&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$USER&lt;/span&gt;
newgrp&lt;span class="w"&gt; &lt;/span&gt;docker

&lt;span class="c1"&gt;# Verify&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;--version
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;version
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;On Raspberry Pi&amp;nbsp;5:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Same Docker install, then verify ARM architecture&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;info&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;Architecture&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Should show aarch64&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Pi users: Use an &lt;span class="caps"&gt;SSD&lt;/span&gt; via &lt;span class="caps"&gt;USB&lt;/span&gt; 3.0 or NVMe &lt;span class="caps"&gt;HAT&lt;/span&gt;, not a microSD card. Home Assistant writes recorder data continuously; an &lt;span class="caps"&gt;SD&lt;/span&gt; card will fail within 6–12 months under that write&amp;nbsp;load.&lt;/p&gt;
&lt;h3&gt;Step 2 — Create Directories and Set&amp;nbsp;Permissions&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;~/docker/homeassistant/&lt;span class="o"&gt;{&lt;/span&gt;homeassistant/config,mosquitto/config,zigbee2mqtt/data,node-red/data&lt;span class="o"&gt;}&lt;/span&gt;
chown&lt;span class="w"&gt; &lt;/span&gt;-R&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;:1000&lt;span class="w"&gt; &lt;/span&gt;~/docker/homeassistant/node-red/data
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Node-&lt;span class="caps"&gt;RED&lt;/span&gt; runs as &lt;span class="caps"&gt;UID&lt;/span&gt; 1000 by default. Home Assistant and Zigbee2MQTT create their own directory structures on first&amp;nbsp;run.&lt;/p&gt;
&lt;h3&gt;Step 3 — Write the Docker Compose&amp;nbsp;File&lt;/h3&gt;
&lt;p&gt;Copy&amp;nbsp;the &lt;code&gt;docker-compose.yml&lt;/code&gt; and &lt;code&gt;.env&lt;/code&gt; from the sections above&amp;nbsp;into &lt;code&gt;~/docker/homeassistant/&lt;/code&gt;. Adjust your Zigbee dongle path&amp;nbsp;under &lt;code&gt;devices:&lt;/code&gt; in the Zigbee2MQTT service. If you don&amp;#8217;t have a Zigbee dongle yet, comment out the&amp;nbsp;entire &lt;code&gt;zigbee2mqtt&lt;/code&gt; service — you can add it later without rebuilding the&amp;nbsp;stack.&lt;/p&gt;
&lt;h3&gt;Step 4 — Start the&amp;nbsp;Stack&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/docker/homeassistant
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d

&lt;span class="c1"&gt;# Watch logs to confirm startup&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;logs&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;homeassistant
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Wait 2–3 minutes for the first-run initialization. Home Assistant downloads several Python wheels and builds the frontend on first start. You will know it&amp;#8217;s ready when the logs&amp;nbsp;show &lt;code&gt;"Home Assistant initialized in X seconds"&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Step 5 — First-Run&amp;nbsp;Configuration&lt;/h3&gt;
&lt;p&gt;Open &lt;code&gt;http://&amp;lt;host-ip&amp;gt;:8123&lt;/code&gt; in a browser. Home Assistant walks you&amp;nbsp;through:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Create owner account&lt;/strong&gt; — This is your admin user. Use a strong&amp;nbsp;password.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Name your home&lt;/strong&gt; — Pick the location for timezone, sunrise/sunset, and weather&amp;nbsp;automations.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Device discovery&lt;/strong&gt; — Home Assistant auto-scans for devices on your network (printers, Chromecasts, Roku, Philips Hue bridges). Accept or&amp;nbsp;skip.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Integrations&lt;/strong&gt; — You will be prompted to install discovered integrations. At minimum, install &lt;strong&gt;&lt;span class="caps"&gt;MQTT&lt;/span&gt;&lt;/strong&gt; and point it&amp;nbsp;to &lt;code&gt;localhost:1883&lt;/code&gt; with the credentials you set in&amp;nbsp;Mosquitto.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Step 6 — Install &lt;span class="caps"&gt;HACS&lt;/span&gt; (Home Assistant Community&amp;nbsp;Store)&lt;/h3&gt;
&lt;p&gt;&lt;span class="caps"&gt;HACS&lt;/span&gt; is the Docker user&amp;#8217;s replacement for the add-on store. It gives you access to thousands of custom integrations and Lovelace dashboard themes — install once, then browse and one-click install&amp;nbsp;forever.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;homeassistant&lt;span class="w"&gt; &lt;/span&gt;bash
wget&lt;span class="w"&gt; &lt;/span&gt;-O&lt;span class="w"&gt; &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;https://get.hacs.xyz&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bash&lt;span class="w"&gt; &lt;/span&gt;-
&lt;span class="nb"&gt;exit&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;restart&lt;span class="w"&gt; &lt;/span&gt;homeassistant
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After restart, go to &lt;strong&gt;Settings → Devices &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; Services → Add Integration → &lt;span class="caps"&gt;HACS&lt;/span&gt;&lt;/strong&gt;. You will need a free GitHub account to authenticate. Once &lt;span class="caps"&gt;HACS&lt;/span&gt; is installed, use it to add integrations like &lt;strong&gt;Frigate&lt;/strong&gt; (&lt;span class="caps"&gt;NVR&lt;/span&gt;), &lt;strong&gt;Adaptive Lighting&lt;/strong&gt;, and &lt;strong&gt;Browser Mod&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;Step 7 — Add Zigbee2MQTT&amp;nbsp;Integration&lt;/h3&gt;
&lt;p&gt;After the Zigbee2MQTT container is running (check&amp;nbsp;at &lt;code&gt;http://&amp;lt;host-ip&amp;gt;:8080&lt;/code&gt;), enable the frontend, then in Home Assistant go to &lt;strong&gt;Settings → Devices &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; Services → Add Integration → &lt;span class="caps"&gt;MQTT&lt;/span&gt;&lt;/strong&gt;. Home Assistant auto-discovers the Zigbee2MQTT bridge and all paired devices appear&amp;nbsp;automatically.&lt;/p&gt;
&lt;p&gt;To pair your first Zigbee device:&amp;nbsp;set &lt;code&gt;permit_join: true&lt;/code&gt; in &lt;code&gt;zigbee2mqtt/data/configuration.yaml&lt;/code&gt;, restart the container&amp;nbsp;(&lt;code&gt;docker compose restart zigbee2mqtt&lt;/code&gt;), then put your device in pairing mode (usually hold a button for 5 seconds). The device appears in the Home Assistant dashboard within seconds. &lt;strong&gt;Disable &lt;code&gt;permit_join&lt;/code&gt; immediately&amp;nbsp;afterward.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;Step 8 — Backup&amp;nbsp;Strategy&lt;/h3&gt;
&lt;p&gt;Your entire configuration lives&amp;nbsp;in &lt;code&gt;~/docker/homeassistant/&lt;/code&gt;. Back it up&amp;nbsp;with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Stop containers to ensure consistent backups&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/docker/homeassistant&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;stop
rsync&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;~/docker/homeassistant/&lt;span class="w"&gt; &lt;/span&gt;/mnt/nas/backups/homeassistant/&lt;span class="k"&gt;$(&lt;/span&gt;date&lt;span class="w"&gt; &lt;/span&gt;+%Y-%m-%d&lt;span class="k"&gt;)&lt;/span&gt;/
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Automate this with a cron job or a Proxmox Backup Server job (if your Docker host is a Proxmox &lt;span class="caps"&gt;VM&lt;/span&gt;/&lt;span class="caps"&gt;LXC&lt;/span&gt;). The Home Assistant container also has a built-in backup service accessible at &lt;strong&gt;Settings → System → Backups&lt;/strong&gt; — use it to create snapshots that include add-on and integration&amp;nbsp;data.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Reverse Proxy &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; Remote&amp;nbsp;Access&lt;/h2&gt;
&lt;p&gt;Exposing Home Assistant directly on port 8123 to the internet is a bad idea. Use a reverse proxy — it gives you &lt;span class="caps"&gt;HTTPS&lt;/span&gt;, path-based routing, and access control in one&amp;nbsp;place.&lt;/p&gt;
&lt;h3&gt;Option 1: Nginx Proxy Manager&amp;nbsp;(Recommended)&lt;/h3&gt;
&lt;p&gt;If you already use Nginx Proxy Manager (and you should — see our &lt;a href="https://wordforge.fifoenix.com/2026/06/nginx-proxy-manager-docker-compose/"&gt;&lt;span class="caps"&gt;NPM&lt;/span&gt; Docker Compose guide&lt;/a&gt;), adding Home Assistant is a 30-second&amp;nbsp;task:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;In &lt;span class="caps"&gt;NPM&lt;/span&gt;, add a new &lt;strong&gt;Proxy Host&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Domain:&lt;/strong&gt; &lt;code&gt;home.example.com&lt;/code&gt; (or whatever subdomain you&amp;nbsp;use).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Forward Hostname/&lt;span class="caps"&gt;IP&lt;/span&gt;:&lt;/strong&gt; &lt;code&gt;&amp;lt;host-ip&amp;gt;&lt;/code&gt; and &lt;strong&gt;Port:&lt;/strong&gt; &lt;code&gt;8123&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Enable &lt;strong&gt;WebSocket Support&lt;/strong&gt; (critical — Home Assistant uses WebSockets for real-time state&amp;nbsp;updates).&lt;/li&gt;
&lt;li&gt;Request an &lt;span class="caps"&gt;SSL&lt;/span&gt; certificate via Let&amp;#8217;s&amp;nbsp;Encrypt.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That is it. Your Home Assistant is now accessible&amp;nbsp;at &lt;code&gt;https://home.example.com&lt;/code&gt; with automatic &lt;span class="caps"&gt;HTTPS&lt;/span&gt;&amp;nbsp;renewal.&lt;/p&gt;
&lt;h3&gt;Option 2: Cloudflare Tunnel (No Port&amp;nbsp;Forwarding)&lt;/h3&gt;
&lt;p&gt;If your &lt;span class="caps"&gt;ISP&lt;/span&gt; uses &lt;span class="caps"&gt;CGNAT&lt;/span&gt; or you want zero open ports, use Cloudflare Tunnel. See our &lt;a href="https://wordforge.fifoenix.com/2026/06/cloudflare-tunnel-homelab/"&gt;Cloudflare Tunnel homelab guide&lt;/a&gt; for the full setup, but the Home Assistant-specific config looks&amp;nbsp;like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# In your cloudflared config.yml&lt;/span&gt;
&lt;span class="nt"&gt;tunnel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;&amp;lt;tunnel-id&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;credentials-file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/etc/cloudflared/&amp;lt;tunnel-id&amp;gt;.json&lt;/span&gt;

&lt;span class="nt"&gt;ingress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;home.example.com&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;http://&amp;lt;host-ip&amp;gt;:8123&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;http_status:404&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Cloudflare Tunnel wraps your Home Assistant in Cloudflare&amp;#8217;s &lt;span class="caps"&gt;CDN&lt;/span&gt; and DDoS protection. Bonus: you get free analytics on who accesses your smart home (and from&amp;nbsp;where).&lt;/p&gt;
&lt;h3&gt;Option 3: Tailscale Mesh &lt;span class="caps"&gt;VPN&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;For maximum security with zero exposed ports, install Tailscale on both your Docker host and your phone/laptop. Access Home Assistant&amp;nbsp;at &lt;code&gt;http://&amp;lt;tailscale-hostname&amp;gt;:8123&lt;/code&gt; from anywhere. No reverse proxy, no &lt;span class="caps"&gt;DNS&lt;/span&gt; records, no &lt;span class="caps"&gt;TLS&lt;/span&gt; certificates needed. Combine this with Tailscale&amp;#8217;s subnet routing to access your entire &lt;span class="caps"&gt;LAN&lt;/span&gt; remotely through one&amp;nbsp;node.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Zigbee/Z-Wave &lt;span class="caps"&gt;USB&lt;/span&gt; Dongle&amp;nbsp;Passthrough&lt;/h2&gt;
&lt;p&gt;This is the section that trips up most Docker users. Passing a &lt;span class="caps"&gt;USB&lt;/span&gt; device into a container is straightforward on bare metal and slightly more involved on Proxmox &lt;span class="caps"&gt;LXC&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;Bare Metal / &lt;span class="caps"&gt;VM&lt;/span&gt;&amp;nbsp;Host&lt;/h3&gt;
&lt;p&gt;Use&amp;nbsp;the &lt;code&gt;devices:&lt;/code&gt; block&amp;nbsp;in &lt;code&gt;docker-compose.yml&lt;/code&gt; as shown above. Find your dongle&amp;#8217;s stable&amp;nbsp;symlink:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-la&lt;span class="w"&gt; &lt;/span&gt;/dev/serial/by-id/
&lt;span class="c1"&gt;# Output: usb-Silicon_Labs_CP2102N_USB_to_UART_Bridge_Controller_XXXXXXXX -&amp;gt; ../../ttyUSB0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Use&amp;nbsp;the &lt;code&gt;/dev/serial/by-id/...&lt;/code&gt; path in your Compose file — it survives &lt;span class="caps"&gt;USB&lt;/span&gt; port changes and&amp;nbsp;reboots.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Permission fix:&lt;/strong&gt; If Zigbee2MQTT logs&amp;nbsp;show &lt;code&gt;"Error: cannot open /dev/ttyUSB0"&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;usermod&lt;span class="w"&gt; &lt;/span&gt;-aG&lt;span class="w"&gt; &lt;/span&gt;dialout&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$USER&lt;/span&gt;
&lt;span class="c1"&gt;# Log out and back in, or reboot&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;privileged: true&lt;/code&gt; flag on the Home Assistant container usually handles this, but the Zigbee2MQTT container needs&amp;nbsp;the &lt;code&gt;dialout&lt;/code&gt; group access on the&amp;nbsp;host.&lt;/p&gt;
&lt;h3&gt;Proxmox &lt;span class="caps"&gt;LXC&lt;/span&gt; &lt;span class="caps"&gt;USB&lt;/span&gt;&amp;nbsp;Passthrough&lt;/h3&gt;
&lt;p&gt;In the Proxmox web &lt;span class="caps"&gt;UI&lt;/span&gt;:
1. Select your &lt;span class="caps"&gt;LXC&lt;/span&gt; container → &lt;strong&gt;Resources&lt;/strong&gt; → &lt;strong&gt;Add&lt;/strong&gt; → &lt;strong&gt;Device Passthrough&lt;/strong&gt;.
2.&amp;nbsp;Choose &lt;code&gt;/dev/serial/by-id/usb-Silicon_Labs_...&lt;/code&gt; from the dropdown.
3. Restart the &lt;span class="caps"&gt;LXC&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Inside the &lt;span class="caps"&gt;LXC&lt;/span&gt;, the device appears at the same path. No&amp;nbsp;container-level &lt;code&gt;devices:&lt;/code&gt; block is needed — the Proxmox host-level passthrough supersedes&amp;nbsp;it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Common issue:&lt;/strong&gt; If the device does not appear inside the &lt;span class="caps"&gt;LXC&lt;/span&gt;, check that the &lt;span class="caps"&gt;LXC&lt;/span&gt; is &lt;strong&gt;privileged&lt;/strong&gt; (not recommended for security) or add the device&amp;#8217;s cgroup permissions&amp;nbsp;in &lt;code&gt;/etc/pve/lxc/&amp;lt;container-id&amp;gt;.conf&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;lxc.cgroup2.devices.allow: c 188:* rwm
lxc.mount.entry: /dev/serial/by-id/usb-Silicon_Labs_CP2102N_USB_to_UART_Bridge_Controller_XXXXXXXX dev/serial/by-id/usb-Silicon_Labs_CP2102N_USB_to_UART_Bridge_Controller_XXXXXXXX none bind,optional,create=file
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Updating &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;Maintenance&lt;/h2&gt;
&lt;h3&gt;Docker Compose Update&amp;nbsp;Workflow&lt;/h3&gt;
&lt;p&gt;Home Assistant releases a new version every month. Update your stack&amp;nbsp;with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/docker/homeassistant

&lt;span class="c1"&gt;# Pull new images (respects version pins in .env)&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;pull

&lt;span class="c1"&gt;# Recreate containers with new images&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d

&lt;span class="c1"&gt;# Remove old dangling images&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;image&lt;span class="w"&gt; &lt;/span&gt;prune&lt;span class="w"&gt; &lt;/span&gt;-f
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Version Pinning&amp;nbsp;Strategy&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;.env&lt;/code&gt; file pins major.minor.patch versions. &lt;strong&gt;Never use&amp;nbsp;the &lt;code&gt;latest&lt;/code&gt; tag&lt;/strong&gt; — Home Assistant introduces breaking changes in minor releases (e.g., a Python version bump, an integration deprecation). Before bumping a&amp;nbsp;version:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Read the &lt;a href="https://www.home-assistant.io/blog/"&gt;Home Assistant release notes&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Check the &lt;strong&gt;Breaking Changes&lt;/strong&gt;&amp;nbsp;section.&lt;/li&gt;
&lt;li&gt;Review your active integrations for deprecation&amp;nbsp;warnings.&lt;/li&gt;
&lt;li&gt;Bump the version&amp;nbsp;in &lt;code&gt;.env&lt;/code&gt;, pull, and&amp;nbsp;restart.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Portainer-Managed&amp;nbsp;Updates&lt;/h3&gt;
&lt;p&gt;If you use Portainer (and you should — see our &lt;a href="https://wordforge.fifoenix.com/2026/06/portainer-docker-management/"&gt;Portainer Docker management guide&lt;/a&gt;), you can manage the entire Home Assistant stack through the Portainer &lt;span class="caps"&gt;UI&lt;/span&gt;. Add the stack via &lt;strong&gt;Stacks → Add Stack → Web Editor&lt;/strong&gt;, paste your Compose file, and deploy. Portainer shows container logs, resource usage, and update status — useful when you are on mobile and need to restart Home Assistant without &lt;span class="caps"&gt;SSH&lt;/span&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Troubleshooting Common&amp;nbsp;Issues&lt;/h2&gt;
&lt;h3&gt;Home Assistant Not Discovering Devices (mDNS/&lt;span class="caps"&gt;DLNA&lt;/span&gt;/UPnP)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; Google Cast, Sonos, Philips Hue, or Apple HomeKit devices do not appear in&amp;nbsp;auto-discovery.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&amp;nbsp;Verify &lt;code&gt;network_mode: host&lt;/code&gt; is set on&amp;nbsp;the &lt;code&gt;homeassistant&lt;/code&gt; service. If you must use bridge mode for security reasons, you lose auto-discovery — add devices manually by &lt;span class="caps"&gt;IP&lt;/span&gt; address in the integration&amp;nbsp;settings.&lt;/p&gt;
&lt;h3&gt;Zigbee2MQTT Cannot Access &lt;span class="caps"&gt;USB&lt;/span&gt;&amp;nbsp;Dongle&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; Logs&amp;nbsp;show &lt;code&gt;"Error: Error: cannot open /dev/ttyUSB0 (Permission denied)"&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; On the&amp;nbsp;host: &lt;code&gt;sudo usermod -aG dialout $USER &amp;amp;&amp;amp; newgrp docker&lt;/code&gt;. Also verify the device path&amp;nbsp;with &lt;code&gt;ls /dev/serial/by-id/&lt;/code&gt; — the symlink may have changed after a kernel&amp;nbsp;update.&lt;/p&gt;
&lt;h3&gt;Container Not Starting After&amp;nbsp;Reboot&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; After a host&amp;nbsp;reboot, &lt;code&gt;docker compose ps&lt;/code&gt; shows containers&amp;nbsp;as &lt;code&gt;exited&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&amp;nbsp;Ensure &lt;code&gt;restart: unless-stopped&lt;/code&gt; is set on every service. If containers still do not auto-start, check that Docker itself starts on&amp;nbsp;boot: &lt;code&gt;sudo systemctl enable docker&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Database Corruption&amp;nbsp;Recovery&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; Home Assistant starts but history/logbook pages are&amp;nbsp;blank.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; The default SQLite database can corrupt after unexpected power loss. Purge&amp;nbsp;it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;stop&lt;span class="w"&gt; &lt;/span&gt;homeassistant
rm&lt;span class="w"&gt; &lt;/span&gt;~/docker/homeassistant/homeassistant/config/home-assistant_v2.db
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;homeassistant
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You lose history data (entity states, logbook entries) but your configuration (automations, scripts, dashboards) is unaffected — those live in separate &lt;span class="caps"&gt;YAML&lt;/span&gt; files. Consider switching to a MariaDB or PostgreSQL recorder for production&amp;nbsp;setups.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;&lt;span class="caps"&gt;FAQ&lt;/span&gt;: Docker Compose vs &lt;span class="caps"&gt;HAOS&lt;/span&gt; vs&amp;nbsp;Core&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Q: Can I use add-ons with Docker?&lt;/strong&gt;
No. Add-ons are exclusive to &lt;span class="caps"&gt;HAOS&lt;/span&gt; and Supervisor. In Docker, you run each add-on as a separate container in the same Compose stack. This is a lateral move: Mosquitto as a container works identically to the Mosquitto add-on; it just appears in Portainer instead of the Supervisor &lt;span class="caps"&gt;UI&lt;/span&gt;. For add-ons that do not have standalone Docker images, use &lt;span class="caps"&gt;HACS&lt;/span&gt; custom&amp;nbsp;integrations.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: Is Docker less stable than &lt;span class="caps"&gt;HAOS&lt;/span&gt;?&lt;/strong&gt;
No. Under the hood, &lt;span class="caps"&gt;HAOS&lt;/span&gt; runs the&amp;nbsp;same &lt;code&gt;homeassistant/home-assistant&lt;/code&gt; Docker image. The Supervisor is a separate container that manages add-ons and snapshots — it does not affect core stability. The stability difference is zero. What changes is who manages the companion services: you (Docker) or the Supervisor (&lt;span class="caps"&gt;HAOS&lt;/span&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: Should I run Home Assistant in a &lt;span class="caps"&gt;VM&lt;/span&gt; instead?&lt;/strong&gt;
If you want &lt;span class="caps"&gt;HAOS&lt;/span&gt; features (add-ons, one-click backups, Google Drive backup) without dedicating a physical machine, a Proxmox &lt;span class="caps"&gt;VM&lt;/span&gt; running &lt;span class="caps"&gt;HAOS&lt;/span&gt; is an excellent middle ground. You get the full &lt;span class="caps"&gt;HAOS&lt;/span&gt; experience while your other Docker containers run in separate VMs or LXCs on the same Proxmox host. The downside: you reserve &lt;span class="caps"&gt;RAM&lt;/span&gt; and &lt;span class="caps"&gt;CPU&lt;/span&gt; for the &lt;span class="caps"&gt;VM&lt;/span&gt; instead of sharing via&amp;nbsp;containers.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: How do I back up Home Assistant in Docker?&lt;/strong&gt;
Two methods:&amp;nbsp;(1) &lt;code&gt;rsync&lt;/code&gt; the&amp;nbsp;entire &lt;code&gt;~/docker/homeassistant/&lt;/code&gt; directory while containers are stopped — this captures everything including your Compose file, &lt;span class="caps"&gt;MQTT&lt;/span&gt; config, and Zigbee2MQTT data. (2) Use Home Assistant&amp;#8217;s built-in backup tool at &lt;strong&gt;Settings → System → Backups&lt;/strong&gt; to create&amp;nbsp;a &lt;code&gt;.tar&lt;/code&gt; snapshot, then copy it off-host with &lt;span class="caps"&gt;SCP&lt;/span&gt; or rsync. Either method works; method 1 is more complete because it captures non-&lt;span class="caps"&gt;HA&lt;/span&gt; data&amp;nbsp;too.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: Can I run Home Assistant on a Raspberry Pi 5 with Docker?&lt;/strong&gt;
Yes, and it works well — with one caveat. Use an NVMe &lt;span class="caps"&gt;SSD&lt;/span&gt; (via a &lt;span class="caps"&gt;HAT&lt;/span&gt; or &lt;span class="caps"&gt;USB&lt;/span&gt; 3.0 enclosure), not a microSD card. Home Assistant&amp;#8217;s recorder writes to the database continuously; &lt;span class="caps"&gt;SD&lt;/span&gt; cards wear out in 6–12 months under that load. With an &lt;span class="caps"&gt;SSD&lt;/span&gt;, a Raspberry Pi 5 (8 &lt;span class="caps"&gt;GB&lt;/span&gt;) handles a modest smart home of 20–30 Zigbee devices and a few Wi-Fi integrations without breaking a&amp;nbsp;sweat.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion: Your Smart Home, Your&amp;nbsp;Rules&lt;/h2&gt;
&lt;p&gt;Running Home Assistant with Docker Compose gives you the best of both worlds: the power and flexibility of the world&amp;#8217;s best open-source smart home platform, plus the infrastructure consistency of your existing homelab stack. You manage Home Assistant the same way you manage Jellyfin, Pihole, and Nginx Proxy Manager — one Compose file, one update workflow, one backup&amp;nbsp;strategy.&lt;/p&gt;
&lt;p&gt;The tradeoff — no add-on store — is smaller than it appears. &lt;span class="caps"&gt;HACS&lt;/span&gt; fills the integration gap, and running companion services as separate containers gives you finer control over versions, resource limits, and networking. For a homelabber already comfortable with Docker, it is the natural&amp;nbsp;choice.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Next steps from&amp;nbsp;here:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://wordforge.fifoenix.com/2026/06/nginx-proxy-manager-docker-compose/"&gt;Set up Nginx Proxy Manager&lt;/a&gt; to expose Home Assistant securely with &lt;span class="caps"&gt;HTTPS&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wordforge.fifoenix.com/2026/06/cloudflare-tunnel-homelab/"&gt;Deploy Cloudflare Tunnel&lt;/a&gt; for remote access without opening&amp;nbsp;ports&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wordforge.fifoenix.com/2026/06/best-nas-os-homelab-2026/"&gt;Choose the best &lt;span class="caps"&gt;NAS&lt;/span&gt; &lt;span class="caps"&gt;OS&lt;/span&gt;&lt;/a&gt; for storing Home Assistant backups, media, and camera&amp;nbsp;footage&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wordforge.fifoenix.com/2026/06/grafana-prometheus-setup/"&gt;Monitor your entire homelab with Grafana and Prometheus&lt;/a&gt; — track &lt;span class="caps"&gt;CPU&lt;/span&gt;, &lt;span class="caps"&gt;RAM&lt;/span&gt;, and disk usage of your Home Assistant&amp;nbsp;host&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wordforge.fifoenix.com/2026/06/ollama-proxmox-homelab/"&gt;Run Ollama on Proxmox&lt;/a&gt; to add local &lt;span class="caps"&gt;AI&lt;/span&gt;-powered voice assistants to your smart&amp;nbsp;home&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Happy automating — and remember: &lt;strong&gt;permit_join: false&lt;/strong&gt;.&lt;/p&gt;</content><category term="Tutorials"/><category term="home-assistant"/><category term="docker"/><category term="docker-compose"/><category term="homelab"/><category term="self-hosted"/><category term="smart-home"/><category term="proxmox"/><category term="zigbee"/><category term="mqtt"/><category term="nginx-proxy-manager"/><category term="cloudflare-tunnel"/><category term="iot"/><category term="home-automation"/><category term="portainer"/><category term="raspberry-pi"/><category term="mini-pc"/></entry><entry><title>Nginx Proxy Manager Docker Compose: The Beginner’s Guide to Homelab Reverse Proxies</title><link href="https://steadypub.com/2026/06/nginx-proxy-manager-docker-compose/" rel="alternate"/><published>2026-06-06T00:00:00+07:00</published><updated>2026-06-06T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-06:/2026/06/nginx-proxy-manager-docker-compose/</id><summary type="html">&lt;p&gt;Deploy Nginx Proxy Manager with Docker Compose in under 15 minutes. Free &lt;span class="caps"&gt;SSL&lt;/span&gt; certificates, custom domains, and secure access to all your self-hosted apps — no command-line expertise&amp;nbsp;required.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~14 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelabbers who want clean domains and &lt;span class="caps"&gt;HTTPS&lt;/span&gt; for all their Docker&amp;nbsp;services&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why You Need a Reverse&amp;nbsp;Proxy&lt;/h2&gt;
&lt;p&gt;You&amp;#8217;ve got 10 Docker containers running — Nextcloud on port 8080, Pi-hole on port 8180, Portainer on port 9443 — and you&amp;#8217;re&amp;nbsp;typing &lt;code&gt;http://192.168.1.50:32400&lt;/code&gt; to access Plex. Every service has a different port, you have no &lt;span class="caps"&gt;HTTPS&lt;/span&gt;, and your browser keeps screaming &amp;#8220;Not Secure.&amp;#8221; There&amp;#8217;s a better&amp;nbsp;way.&lt;/p&gt;
&lt;p&gt;A reverse proxy sits at the edge of your network, receives all incoming requests, and routes them to the correct backend service. Instead of memorizing ports, you&amp;nbsp;access &lt;code&gt;cloud.yourdomain.com&lt;/code&gt;, &lt;code&gt;admin.yourdomain.com&lt;/code&gt;,&amp;nbsp;and &lt;code&gt;photos.yourdomain.com&lt;/code&gt; — all on standard port 443 with valid &lt;span class="caps"&gt;SSL&lt;/span&gt;&amp;nbsp;certificates.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Nginx Proxy Manager (&lt;span class="caps"&gt;NPM&lt;/span&gt;)&lt;/strong&gt; is the most beginner-friendly reverse proxy for homelab use. It wraps the powerful Nginx engine in a clean web &lt;span class="caps"&gt;GUI&lt;/span&gt;. No configuration files to edit. No &lt;span class="caps"&gt;CLI&lt;/span&gt; flags to memorize. Let&amp;#8217;s Encrypt integration is built-in — one click and you have &lt;span class="caps"&gt;HTTPS&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;By the end of this guide, you&amp;#8217;ll&amp;nbsp;have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A running Nginx Proxy Manager instance on&amp;nbsp;Docker&lt;/li&gt;
&lt;li&gt;Custom subdomains for all your services&amp;nbsp;(&lt;code&gt;*&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Auto-renewing free &lt;span class="caps"&gt;SSL&lt;/span&gt; certificates from Let&amp;#8217;s&amp;nbsp;Encrypt&lt;/li&gt;
&lt;li&gt;Portainer integration for easy stack&amp;nbsp;management&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;What Is Nginx Proxy&amp;nbsp;Manager?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Nginx Proxy Manager is an open-source web interface for managing Nginx reverse proxy hosts. It was created by Jamie Curnow (&lt;a href="https://github.com/NginxProxyManager/nginx-proxy-manager"&gt;jc21&lt;/a&gt;) and has grown to over 33,000 GitHub stars. The goal: make Nginx accessible to people who don&amp;#8217;t want to write config&amp;nbsp;files.&lt;/p&gt;
&lt;p&gt;Instead of&amp;nbsp;hand-editing &lt;code&gt;nginx.conf&lt;/code&gt; blocks, you fill in a web form: domain name, backend &lt;span class="caps"&gt;IP&lt;/span&gt; and port, select &lt;span class="caps"&gt;SSL&lt;/span&gt; options — done. The &lt;span class="caps"&gt;GUI&lt;/span&gt; updates Nginx configuration automatically and reloads the&amp;nbsp;service.&lt;/p&gt;
&lt;h3&gt;Key&amp;nbsp;Features&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;GUI&lt;/span&gt; Proxy Host Manager&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Add, edit, and delete proxy hosts through a web dashboard&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Automatic Let&amp;#8217;s Encrypt &lt;span class="caps"&gt;SSL&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;HTTP&lt;/span&gt; and &lt;span class="caps"&gt;DNS&lt;/span&gt; challenge support; wildcard certificates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Access Lists&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;IP&lt;/span&gt;-based allow/deny rules for individual proxy hosts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;404 Redirects&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Custom landing pages for unconfigured subdomains&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Stream Proxies&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Proxy raw &lt;span class="caps"&gt;TCP&lt;/span&gt;/&lt;span class="caps"&gt;UDP&lt;/span&gt; streams (ideal for game servers, &lt;span class="caps"&gt;SSH&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Custom Nginx Snippets&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Inject raw Nginx config for advanced headers, &lt;span class="caps"&gt;CORS&lt;/span&gt;, or WebSocket&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Let&amp;#8217;s Encrypt Auto-Renewal&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Certificates renew automatically every 60 days&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Docker Healthcheck&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Built-in health status endpoint&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;&lt;span class="caps"&gt;NPM&lt;/span&gt; vs Traefik vs Caddy: Which Reverse&amp;nbsp;Proxy?&lt;/h3&gt;
&lt;p&gt;&lt;span class="caps"&gt;NPM&lt;/span&gt; isn&amp;#8217;t the only reverse proxy for homelab use. Here&amp;#8217;s how the three main contenders&amp;nbsp;compare:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Nginx Proxy Manager&lt;/th&gt;
&lt;th&gt;Traefik&lt;/th&gt;
&lt;th&gt;Caddy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;GUI&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Full web &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;❌ Config files only&lt;/td&gt;
&lt;td&gt;❌ Config files only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Learning curve&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Docker auto-discovery&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Manual setup&lt;/td&gt;
&lt;td&gt;✅ Native Docker label discovery&lt;/td&gt;
&lt;td&gt;❌ Manual (or Caddy-Docker-Proxy plugin)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Let&amp;#8217;s Encrypt&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Built-in (+ &lt;span class="caps"&gt;DNS&lt;/span&gt; Challenge)&lt;/td&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;td&gt;Built-in (automatic)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Configuration syntax&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Web form&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;YAML&lt;/span&gt; / labels&lt;/td&gt;
&lt;td&gt;Caddyfile (simple &lt;span class="caps"&gt;DSL&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Stream proxy (&lt;span class="caps"&gt;TCP&lt;/span&gt;/&lt;span class="caps"&gt;UDP&lt;/span&gt;)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅ (Caddy L4)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Beginners, mixed teams, quick setup&lt;/td&gt;
&lt;td&gt;Kubernetes, Docker Swarm, auto-scaling&lt;/td&gt;
&lt;td&gt;Developers who like Caddyfile simplicity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GitHub Stars&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;33k+&lt;/td&gt;
&lt;td&gt;55k+&lt;/td&gt;
&lt;td&gt;60k+&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;When to pick &lt;span class="caps"&gt;NPM&lt;/span&gt;:&lt;/strong&gt; You want a &lt;span class="caps"&gt;GUI&lt;/span&gt;, you&amp;#8217;re managing a handful of services, you don&amp;#8217;t need automatic Docker container discovery, and you want to stop editing config&amp;nbsp;files.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;When to pick Traefik:&lt;/strong&gt; You run dozens of containers, want auto-discovery via Docker labels, and are comfortable with &lt;span class="caps"&gt;YAML&lt;/span&gt;&amp;nbsp;configuration.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;When to pick Caddy:&lt;/strong&gt; You like a simple config language&amp;nbsp;(&lt;code&gt;Caddyfile&lt;/code&gt;), want automatic &lt;span class="caps"&gt;HTTPS&lt;/span&gt; with zero configuration, and don&amp;#8217;t need a web &lt;span class="caps"&gt;GUI&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;For 90% of homelabbers, &lt;strong&gt;Nginx Proxy Manager is the right choice&lt;/strong&gt;. It&amp;#8217;s fast to set up, forgiving of mistakes, and the &lt;span class="caps"&gt;GUI&lt;/span&gt; means you&amp;#8217;ll actually remember how it works when you come back to it six months&amp;nbsp;later.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;h3&gt;Hardware&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Any x86_64 or &lt;span class="caps"&gt;ARM64&lt;/span&gt; device running Docker (mini &lt;span class="caps"&gt;PC&lt;/span&gt;, Raspberry Pi 4/5, Proxmox &lt;span class="caps"&gt;LXC&lt;/span&gt;, or old&amp;nbsp;laptop)&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;512MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; minimum (&lt;span class="caps"&gt;1GB&lt;/span&gt;&amp;nbsp;recommended)&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;2GB&lt;/span&gt; storage for configuration and certificate&amp;nbsp;data&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Software&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Docker Engine 24.x+ with Docker Compose&amp;nbsp;v2+&lt;/li&gt;
&lt;li&gt;Linux host (Debian 12, Ubuntu 22.04/24.04, or Proxmox &lt;span class="caps"&gt;LXC&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;Firewall rules allowing ports 80 and 443 (if using &lt;span class="caps"&gt;HTTP&lt;/span&gt; challenge or public&amp;nbsp;access)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Networking&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;A domain name (e.g., from Cloudflare, Namecheap, or Porkbun) — or local &lt;span class="caps"&gt;DNS&lt;/span&gt; via Pi-hole for internal-only&amp;nbsp;use&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;DHCP&lt;/span&gt; reservation or static &lt;span class="caps"&gt;IP&lt;/span&gt; for your Docker&amp;nbsp;host&lt;/li&gt;
&lt;li&gt;Ports 80 and 443 forwarded on your router (if exposing services publicly) — or use Cloudflare Tunnel to skip port forwarding&amp;nbsp;entirely&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Create the Docker Compose&amp;nbsp;File&lt;/h2&gt;
&lt;p&gt;First, create a dedicated directory and the compose&amp;nbsp;file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;~/nginx-proxy-manager&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/nginx-proxy-manager
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Create &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;3.8&amp;#39;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;nginx-proxy-manager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;jc21/nginx-proxy-manager:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;npm&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="c1"&gt;# Auto-restart on crash or host reboot&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;80:80&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;                       &lt;/span&gt;&lt;span class="c1"&gt;# HTTP — Let&amp;#39;s Encrypt HTTP challenge&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;443:443&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;                     &lt;/span&gt;&lt;span class="c1"&gt;# HTTPS — secure traffic to your services&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;81:81&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;                       &lt;/span&gt;&lt;span class="c1"&gt;# Admin web UI (accessible at http://host:81)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./data:/data&lt;/span&gt;&lt;span class="w"&gt;                  &lt;/span&gt;&lt;span class="c1"&gt;# NPM configuration (proxy hosts, SSL certs, settings)&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./letsencrypt:/etc/letsencrypt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# Let&amp;#39;s Encrypt certificate storage&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;DISABLE_IPV6=true&lt;/span&gt;&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="c1"&gt;# Set to false if you use IPv6&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;npm_network&lt;/span&gt;&lt;span class="w"&gt;                   &lt;/span&gt;&lt;span class="c1"&gt;# Custom bridge for inter-container communication&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;healthcheck&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;CMD&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;curl&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-f&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://localhost:81&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;30s&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;10s&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;retries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;3&lt;/span&gt;

&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;npm_network&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;bridge&lt;/span&gt;&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="c1"&gt;# Isolated network for NPM + your services&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;What each piece&amp;nbsp;does:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;jc21/nginx-proxy-manager:latest&lt;/code&gt;&lt;/strong&gt; — Official upstream image from the project&amp;#8217;s Docker Hub, maintained by the &lt;span class="caps"&gt;NPM&lt;/span&gt;&amp;nbsp;creator.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;restart: unless-stopped&lt;/code&gt;&lt;/strong&gt; — Ensures &lt;span class="caps"&gt;NPM&lt;/span&gt; comes back up after a power outage or host&amp;nbsp;reboot.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Port 81&lt;/strong&gt; — The admin dashboard. Change the host port if 81 is already in use&amp;nbsp;(e.g., &lt;code&gt;"8081:81"&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;npm_network&lt;/code&gt;&lt;/strong&gt; — A custom Docker bridge network. All containers you want &lt;span class="caps"&gt;NPM&lt;/span&gt; to reach must join this same network. Without it, &lt;span class="caps"&gt;NPM&lt;/span&gt; can&amp;#8217;t resolve container&amp;nbsp;names.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;healthcheck&lt;/code&gt;&lt;/strong&gt; — Docker checks the admin &lt;span class="caps"&gt;UI&lt;/span&gt; every 30 seconds. The container status&amp;nbsp;in &lt;code&gt;docker ps&lt;/code&gt; reflects actual health, not just&amp;nbsp;&amp;#8220;running.&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Important:&lt;/strong&gt; If you&amp;#8217;re running Pi-hole or another service that binds port 80, stop it first. &lt;span class="caps"&gt;NPM&lt;/span&gt; &lt;em&gt;must&lt;/em&gt; own ports 80 and 443. Pi-hole can use alternative ports — adjust its compose file to&amp;nbsp;map &lt;code&gt;"8180:80"&lt;/code&gt; and &lt;code&gt;"8143:443"&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;Step 2: Deploy and Log&amp;nbsp;In&lt;/h2&gt;
&lt;p&gt;Start the&amp;nbsp;stack:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Check that it&amp;#8217;s&amp;nbsp;running:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;ps
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You should&amp;nbsp;see &lt;code&gt;npm&lt;/code&gt; with status &amp;#8220;healthy&amp;#8221; after a few&amp;nbsp;seconds.&lt;/p&gt;
&lt;p&gt;Open your browser and navigate&amp;nbsp;to &lt;code&gt;http://[your-host-ip]:81&lt;/code&gt;. Log in with the default&amp;nbsp;credentials:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Email:&lt;/strong&gt; &lt;code&gt;admin@example.com&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Password:&lt;/strong&gt; &lt;code&gt;changeme&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Change the password immediately.&lt;/strong&gt; Click your email address in the top-right corner → &lt;strong&gt;Edit Details&lt;/strong&gt; → enter your full name, a real email address, and a strong&amp;nbsp;password.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🛡️ &lt;strong&gt;Security tip:&lt;/strong&gt; Change the default admin email to a real one. Let&amp;#8217;s Encrypt sends expiration warnings to this email address. If you leave it&amp;nbsp;as &lt;code&gt;admin@example.com&lt;/code&gt;, you&amp;#8217;ll never get renewal failure&amp;nbsp;alerts.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Dashboard&amp;nbsp;Overview&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Section&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Proxy Hosts&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Main view — add and manage domain-to-backend mappings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Redirection Hosts&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;HTTP&lt;/span&gt;-to-&lt;span class="caps"&gt;HTTPS&lt;/span&gt; redirects or domain-to-other-domain redirects&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Streams&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Raw &lt;span class="caps"&gt;TCP&lt;/span&gt;/&lt;span class="caps"&gt;UDP&lt;/span&gt; forwarding (&lt;span class="caps"&gt;SSH&lt;/span&gt;, game servers, &lt;span class="caps"&gt;RTMP&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;404 Hosts&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Custom &amp;#8220;page not found&amp;#8221; landings for unknown subdomains&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;SSL&lt;/span&gt; Certificates&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Request, renew, and manage Let&amp;#8217;s Encrypt certificates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Access Lists&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;IP&lt;/span&gt;-based allow/deny rules you can attach to proxy hosts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Users&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Create additional admin or viewer accounts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Audit Log&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;See who changed what and when&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Step 3: Add Your First Proxy&amp;nbsp;Host&lt;/h2&gt;
&lt;p&gt;Let&amp;#8217;s expose a service at a clean subdomain. We&amp;#8217;ll use a Nextcloud container as an example — assume it&amp;#8217;s running on the same Docker host with container&amp;nbsp;name &lt;code&gt;nextcloud&lt;/code&gt;, listening on port 80&amp;nbsp;internally.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Make sure Nextcloud is on the same Docker network.&lt;/strong&gt; Attach it&amp;nbsp;to &lt;code&gt;npm_network&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;network&lt;span class="w"&gt; &lt;/span&gt;connect&lt;span class="w"&gt; &lt;/span&gt;npm_network&lt;span class="w"&gt; &lt;/span&gt;nextcloud
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Or, better, define the network in every&amp;nbsp;service&amp;#8217;s &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# In your Nextcloud&amp;#39;s docker-compose.yml:&lt;/span&gt;
&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;npm_network&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;external&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;# Use the pre-existing NPM network&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, in the &lt;span class="caps"&gt;NPM&lt;/span&gt; admin&amp;nbsp;dashboard:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Click &lt;strong&gt;Proxy Hosts&lt;/strong&gt; → &lt;strong&gt;Add Proxy&amp;nbsp;Host&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Domain&amp;nbsp;Names:&lt;/strong&gt; &lt;code&gt;cloud.yourdomain.com&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scheme:&lt;/strong&gt; &lt;code&gt;http&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Forward Hostname / &lt;span class="caps"&gt;IP&lt;/span&gt;:&lt;/strong&gt; &lt;code&gt;nextcloud&lt;/code&gt; (Docker container name resolves automatically on the shared bridge&amp;nbsp;network)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Forward&amp;nbsp;Port:&lt;/strong&gt; &lt;code&gt;80&lt;/code&gt; (the port inside the container, not the host-mapped&amp;nbsp;port)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cache Assets:&lt;/strong&gt; Leave off (Nextcloud handles its own&amp;nbsp;caching)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Block Common Exploits:&lt;/strong&gt; ✅ Enable this — it&amp;#8217;s a one-click &lt;span class="caps"&gt;SQL&lt;/span&gt; injection and path traversal&amp;nbsp;guard&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Websockets Support:&lt;/strong&gt; Enable if the app requires live updates (Portainer, Home Assistant, Immich, Uptime&amp;nbsp;Kuma)&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Save&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You can now&amp;nbsp;access &lt;code&gt;http://cloud.yourdomain.com&lt;/code&gt; and &lt;span class="caps"&gt;NPM&lt;/span&gt; routes traffic to Nextcloud. No port number&amp;nbsp;needed.&lt;/p&gt;
&lt;h3&gt;Enabling WebSockets for Real-Time&amp;nbsp;Apps&lt;/h3&gt;
&lt;p&gt;Some apps need WebSocket connections to function properly. If you see &amp;#8220;Connection lost&amp;#8221; or blank dashboards, enable &lt;strong&gt;Websockets Support&lt;/strong&gt; in the Advanced tab of that proxy host&amp;nbsp;entry.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;App&lt;/th&gt;
&lt;th&gt;Needs WebSockets?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Portainer&lt;/td&gt;
&lt;td&gt;✅ Yes (live container logs)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Home Assistant&lt;/td&gt;
&lt;td&gt;✅ Yes (real-time state updates)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Uptime Kuma&lt;/td&gt;
&lt;td&gt;✅ Yes (monitor status pulses)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Immich&lt;/td&gt;
&lt;td&gt;✅ Yes (live photo uploads)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Grafana&lt;/td&gt;
&lt;td&gt;✅ Yes (dashboard refresh)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nextcloud&lt;/td&gt;
&lt;td&gt;❌ No (standard &lt;span class="caps"&gt;HTTP&lt;/span&gt; is fine)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pi-hole&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Plex / Jellyfin&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Custom Nginx Location&amp;nbsp;Snippets&lt;/h3&gt;
&lt;p&gt;For advanced setups, the &lt;strong&gt;Advanced&lt;/strong&gt; tab lets you paste raw Nginx directives. This is useful&amp;nbsp;for:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Override upload size limit (Nextcloud needs this)&lt;/span&gt;
&lt;span class="k"&gt;client_max_body_size&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;10G&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;# Add security headers&lt;/span&gt;
&lt;span class="k"&gt;add_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;X-Frame-Options&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;SAMEORIGIN&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;add_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;X-Content-Type-Options&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;nosniff&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;add_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;Referrer-Policy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;strict-origin-when-cross-origin&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;# Allow Home Assistant ingress&lt;/span&gt;
&lt;span class="k"&gt;proxy_buffering&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 4: Enable Free &lt;span class="caps"&gt;SSL&lt;/span&gt; with Let&amp;#8217;s&amp;nbsp;Encrypt&lt;/h2&gt;
&lt;p&gt;&lt;span class="caps"&gt;HTTP&lt;/span&gt; is fine for testing, but production services need &lt;span class="caps"&gt;HTTPS&lt;/span&gt;. Nginx Proxy Manager makes &lt;span class="caps"&gt;SSL&lt;/span&gt; certificates dead simple with two challenge&amp;nbsp;options.&lt;/p&gt;
&lt;h3&gt;Option A: &lt;span class="caps"&gt;HTTP&lt;/span&gt; Challenge (Simplest, Requires Port 80&amp;nbsp;Forwarded)&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Go to your proxy host → &lt;strong&gt;&lt;span class="caps"&gt;SSL&lt;/span&gt;&lt;/strong&gt;&amp;nbsp;tab&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Request a new &lt;span class="caps"&gt;SSL&lt;/span&gt;&amp;nbsp;Certificate&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Choose &lt;strong&gt;&lt;span class="caps"&gt;HTTP&lt;/span&gt;&amp;nbsp;Challenge&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Enter your email address (for Let&amp;#8217;s Encrypt expiry&amp;nbsp;alerts)&lt;/li&gt;
&lt;li&gt;Agree to the Let&amp;#8217;s Encrypt Terms of&amp;nbsp;Service&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Save&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span class="caps"&gt;NPM&lt;/span&gt; handles the &lt;span class="caps"&gt;ACME&lt;/span&gt; challenge, fetches the certificate, and auto-reloads Nginx. Your service now responds&amp;nbsp;on &lt;code&gt;https://cloud.yourdomain.com&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Option B: &lt;span class="caps"&gt;DNS&lt;/span&gt; Challenge (Better — Works Without Public Ports, Supports&amp;nbsp;Wildcards)&lt;/h3&gt;
&lt;p&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt; Challenge is the preferred method&amp;nbsp;because:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It works even if your &lt;span class="caps"&gt;ISP&lt;/span&gt; blocks ports&amp;nbsp;80/443&lt;/li&gt;
&lt;li&gt;You can request &lt;strong&gt;wildcard certificates&lt;/strong&gt;&amp;nbsp;(&lt;code&gt;*.yourdomain.com&lt;/code&gt;) and use one cert for all&amp;nbsp;subdomains&lt;/li&gt;
&lt;li&gt;No &lt;span class="caps"&gt;HTTP&lt;/span&gt; listener needed on the public&amp;nbsp;internet&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Step-by-step for&amp;nbsp;Cloudflare:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://dash.cloudflare.com/"&gt;Cloudflare Dashboard&lt;/a&gt; → your domain → &lt;strong&gt;&lt;span class="caps"&gt;API&lt;/span&gt;&amp;nbsp;Tokens&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Create a token with&amp;nbsp;permissions: &lt;code&gt;Zone:Read&lt;/code&gt; + &lt;code&gt;DNS:Edit&lt;/code&gt; for your&amp;nbsp;zone&lt;/li&gt;
&lt;li&gt;Copy the&amp;nbsp;token&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Back in &lt;span class="caps"&gt;NPM&lt;/span&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Navigate to &lt;strong&gt;&lt;span class="caps"&gt;SSL&lt;/span&gt; Certificates&lt;/strong&gt; → &lt;strong&gt;Add &lt;span class="caps"&gt;SSL&lt;/span&gt; Certificate&lt;/strong&gt; → &lt;strong&gt;Let&amp;#8217;s&amp;nbsp;Encrypt&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Enter &lt;code&gt;*.yourdomain.com&lt;/code&gt; and &lt;code&gt;yourdomain.com&lt;/code&gt; in the Domain Names field (wildcard +&amp;nbsp;apex)&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Use a &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;Challenge&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Choose &lt;strong&gt;Cloudflare&lt;/strong&gt; as the &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;provider&lt;/li&gt;
&lt;li&gt;Paste your &lt;span class="caps"&gt;API&lt;/span&gt; token into the credentials&amp;nbsp;field&lt;/li&gt;
&lt;li&gt;Agree to the Terms of&amp;nbsp;Service&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Save&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span class="caps"&gt;NPM&lt;/span&gt; creates a &lt;span class="caps"&gt;TXT&lt;/span&gt; record in your Cloudflare &lt;span class="caps"&gt;DNS&lt;/span&gt;, validates it with Let&amp;#8217;s Encrypt, and stores the wildcard certificate. This process takes about 15&amp;nbsp;seconds.&lt;/p&gt;
&lt;p&gt;Now apply it: go back to any proxy host → &lt;strong&gt;&lt;span class="caps"&gt;SSL&lt;/span&gt;&lt;/strong&gt; tab → select your&amp;nbsp;new &lt;code&gt;*.yourdomain.com&lt;/code&gt; certificate from the dropdown → &lt;strong&gt;Save&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;Force &lt;span class="caps"&gt;SSL&lt;/span&gt; (&lt;span class="caps"&gt;HTTP&lt;/span&gt; → &lt;span class="caps"&gt;HTTPS&lt;/span&gt;&amp;nbsp;Redirect)&lt;/h3&gt;
&lt;p&gt;In the &lt;strong&gt;&lt;span class="caps"&gt;SSL&lt;/span&gt;&lt;/strong&gt; tab of each proxy host, enable &lt;strong&gt;Force &lt;span class="caps"&gt;SSL&lt;/span&gt;&lt;/strong&gt;. This adds an automatic &lt;span class="caps"&gt;HTTP&lt;/span&gt;-to-&lt;span class="caps"&gt;HTTPS&lt;/span&gt; redirect so nobody accidentally uses the insecure &lt;span class="caps"&gt;URL&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;Certificate&amp;nbsp;Auto-Renewal&lt;/h3&gt;
&lt;p&gt;&lt;span class="caps"&gt;NPM&lt;/span&gt; automatically attempts renewal 30 days before expiry. Renewals use the &lt;strong&gt;same challenge method&lt;/strong&gt; as the original request. If a renewal fails, &lt;span class="caps"&gt;NPM&lt;/span&gt; logs the error and retries daily. Let&amp;#8217;s Encrypt also sends expiry warnings to the email you&amp;nbsp;provided.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Check renewal logs&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;logs&lt;span class="w"&gt; &lt;/span&gt;npm&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;renew&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 5: Integrate with Portainer&amp;nbsp;(Optional)&lt;/h2&gt;
&lt;p&gt;If you run Portainer for container management, you can deploy &lt;span class="caps"&gt;NPM&lt;/span&gt; as a Portainer stack for a unified&amp;nbsp;workflow.&lt;/p&gt;
&lt;p&gt;In&amp;nbsp;Portainer:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;Stacks&lt;/strong&gt; → &lt;strong&gt;Add&amp;nbsp;Stack&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Name: &lt;code&gt;npm&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Paste&amp;nbsp;the &lt;code&gt;docker-compose.yml&lt;/code&gt; from Step&amp;nbsp;1&lt;/li&gt;
&lt;li&gt;Under &lt;strong&gt;Network&lt;/strong&gt;, ensure the stack is attached to an external network&amp;nbsp;(&lt;code&gt;npm_network&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Deploy the&amp;nbsp;stack&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Portainer now shows &lt;span class="caps"&gt;NPM&lt;/span&gt;&amp;#8217;s container status, logs, and resource usage in one dashboard. You can restart or update &lt;span class="caps"&gt;NPM&lt;/span&gt; without touching the &lt;span class="caps"&gt;CLI&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;For services managed via Portainer stacks, add them to the &lt;span class="caps"&gt;NPM&lt;/span&gt; network by editing their stack&amp;#8217;s compose&amp;nbsp;file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;npm_network&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;external&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This ensures every service in the stack can be reached by &lt;span class="caps"&gt;NPM&lt;/span&gt; via its container&amp;nbsp;name.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Pro tip:&lt;/strong&gt; Keep &lt;span class="caps"&gt;NPM&lt;/span&gt; in its own stack, separate from your application stacks. This way, you can restart or update services without affecting the reverse&amp;nbsp;proxy.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;Troubleshooting &lt;span class="caps"&gt;FAQ&lt;/span&gt;&lt;/h2&gt;
&lt;h3&gt;Q: &amp;#8220;502 Bad Gateway&amp;#8221; when I try to access my&amp;nbsp;service&lt;/h3&gt;
&lt;p&gt;This is the most common error and almost always means &lt;span class="caps"&gt;NPM&lt;/span&gt; can&amp;#8217;t reach the backend&amp;nbsp;container.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Checklist:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Are both containers on the same Docker network?&amp;nbsp;Run &lt;code&gt;docker network inspect npm_network&lt;/code&gt; and confirm both containers are&amp;nbsp;listed.&lt;/li&gt;
&lt;li&gt;Is the Forward Port correct? Use the &lt;strong&gt;internal&lt;/strong&gt; container port&amp;nbsp;(e.g., &lt;code&gt;80&lt;/code&gt;), not the host-mapped port&amp;nbsp;(e.g., &lt;code&gt;8080&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Is the container actually&amp;nbsp;running? &lt;code&gt;docker ps | grep your-container&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Can &lt;span class="caps"&gt;NPM&lt;/span&gt; resolve the container name?&amp;nbsp;Try &lt;code&gt;docker exec npm ping nextcloud&lt;/code&gt; — if it fails, they&amp;#8217;re not on the same&amp;nbsp;network.&lt;/li&gt;
&lt;li&gt;Use the &lt;span class="caps"&gt;IP&lt;/span&gt; address instead of container name&amp;nbsp;temporarily: &lt;code&gt;docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' nextcloud&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Q: My &lt;span class="caps"&gt;SSL&lt;/span&gt; certificate shows as invalid or&amp;nbsp;expired&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Check the &lt;span class="caps"&gt;NPM&lt;/span&gt;&amp;nbsp;logs: &lt;code&gt;docker logs npm 2&amp;gt;&amp;amp;1 | grep -i "error\|ssl\|cert"&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;For &lt;span class="caps"&gt;DNS&lt;/span&gt; challenges: verify the &lt;span class="caps"&gt;API&lt;/span&gt; token still&amp;nbsp;has &lt;code&gt;Zone:Read&lt;/code&gt; and &lt;code&gt;DNS:Edit&lt;/code&gt; permissions&lt;/li&gt;
&lt;li&gt;For &lt;span class="caps"&gt;HTTP&lt;/span&gt; challenges: verify port 80 is accessible from the internet (use &lt;a href="https://canyouseeme.org"&gt;canyouseeme.org&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Force manual renewal: in &lt;strong&gt;&lt;span class="caps"&gt;SSL&lt;/span&gt; Certificates&lt;/strong&gt; → click the three-dot menu → &lt;strong&gt;Renew&amp;nbsp;Now&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Check the email address on your &lt;span class="caps"&gt;SSL&lt;/span&gt; certificate entry — Let&amp;#8217;s Encrypt sends warnings to&amp;nbsp;it&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Q: WebSockets not working for Portainer / Home&amp;nbsp;Assistant&lt;/h3&gt;
&lt;p&gt;In the proxy host&amp;#8217;s &lt;strong&gt;Advanced&lt;/strong&gt; tab, you need both the WebSockets Support toggle &lt;strong&gt;and&lt;/strong&gt; sometimes additional&amp;nbsp;headers:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;proxy_set_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;Upgrade&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$http_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;proxy_set_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;Connection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;upgrade&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;proxy_read_timeout&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;86400&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Q: Can&amp;#8217;t access &lt;span class="caps"&gt;NPM&lt;/span&gt; admin panel on port&amp;nbsp;81&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Check if another service is using port&amp;nbsp;81: &lt;code&gt;sudo lsof -i :81&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Verify your&amp;nbsp;firewall: &lt;code&gt;sudo ufw status&lt;/code&gt; — if &lt;span class="caps"&gt;UFW&lt;/span&gt; is active, allow port&amp;nbsp;81: &lt;code&gt;sudo ufw allow 81&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;If the host firewall is iptables-based, check Docker&amp;#8217;s&amp;nbsp;rules: &lt;code&gt;sudo iptables -L DOCKER&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Try mapping a different port&amp;nbsp;in &lt;code&gt;docker-compose.yml&lt;/code&gt;:&amp;nbsp;change &lt;code&gt;"81:81"&lt;/code&gt; to &lt;code&gt;"8181:81"&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Q: Do I need &lt;span class="caps"&gt;NPM&lt;/span&gt; if I use Cloudflare&amp;nbsp;Tunnel?&lt;/h3&gt;
&lt;p&gt;They solve different&amp;nbsp;problems:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cloudflare Tunnel&lt;/strong&gt; securely exposes your services to the public internet without opening router ports. It runs as a daemon on your server and proxies traffic through Cloudflare&amp;#8217;s&amp;nbsp;edge.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Nginx Proxy Manager&lt;/strong&gt; routes traffic &lt;strong&gt;within your &lt;span class="caps"&gt;LAN&lt;/span&gt;&lt;/strong&gt; and provides local &lt;span class="caps"&gt;HTTPS&lt;/span&gt; with custom&amp;nbsp;domains.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Real-world combo:&lt;/strong&gt; Use Cloudflare Tunnel for public access&amp;nbsp;(&lt;code&gt;cloud.yourdomain.com&lt;/code&gt; from anywhere), and &lt;span class="caps"&gt;NPM&lt;/span&gt; for local access&amp;nbsp;(&lt;code&gt;cloud.home&lt;/code&gt;) — both pointing at the same backend containers. Best of both&amp;nbsp;worlds.&lt;/p&gt;
&lt;h3&gt;Q: How do I back up my &lt;span class="caps"&gt;NPM&lt;/span&gt;&amp;nbsp;configuration?&lt;/h3&gt;
&lt;p&gt;Back up two&amp;nbsp;directories:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Stop NPM first (optional but safer)&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;down

&lt;span class="c1"&gt;# Copy the data and certificate volumes&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;cp&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="w"&gt; &lt;/span&gt;~/nginx-proxy-manager/data&lt;span class="w"&gt; &lt;/span&gt;~/backups/npm-data-&lt;span class="k"&gt;$(&lt;/span&gt;date&lt;span class="w"&gt; &lt;/span&gt;+%Y%m%d&lt;span class="k"&gt;)&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;cp&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="w"&gt; &lt;/span&gt;~/nginx-proxy-manager/letsencrypt&lt;span class="w"&gt; &lt;/span&gt;~/backups/npm-letsencrypt-&lt;span class="k"&gt;$(&lt;/span&gt;date&lt;span class="w"&gt; &lt;/span&gt;+%Y%m%d&lt;span class="k"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Restart&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Restoring is the reverse: copy the directories back and start the container. &lt;span class="caps"&gt;NPM&lt;/span&gt; picks up all proxy hosts and &lt;span class="caps"&gt;SSL&lt;/span&gt; certificates&amp;nbsp;automatically.&lt;/p&gt;
&lt;h3&gt;Q: Can I use &lt;span class="caps"&gt;NPM&lt;/span&gt; for local-only services (no public&amp;nbsp;domain)?&lt;/h3&gt;
&lt;p&gt;Yes. Use Pi-hole or AdGuard Home for local &lt;span class="caps"&gt;DNS&lt;/span&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;In Pi-hole: &lt;strong&gt;Local &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/strong&gt; → &lt;strong&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;Records&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Add: &lt;code&gt;cloud.home&lt;/code&gt; → &lt;code&gt;192.168.1.50&lt;/code&gt; (your Docker host &lt;span class="caps"&gt;IP&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;In &lt;span class="caps"&gt;NPM&lt;/span&gt;: add a proxy host&amp;nbsp;for &lt;code&gt;cloud.home&lt;/code&gt; pointing at your&amp;nbsp;container&lt;/li&gt;
&lt;li&gt;Request an &lt;span class="caps"&gt;SSL&lt;/span&gt; certificate using &lt;strong&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt; Challenge&lt;/strong&gt; (no public port 80&amp;nbsp;needed)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This gives you valid &lt;span class="caps"&gt;HTTPS&lt;/span&gt; for internal-only services — even&amp;nbsp;on &lt;code&gt;.home&lt;/code&gt; or &lt;code&gt;.local&lt;/code&gt; domains — using &lt;span class="caps"&gt;DNS&lt;/span&gt; Challenge with Cloudflare or&amp;nbsp;DuckDNS.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Next&amp;nbsp;Steps&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[internal_link] Secure your &lt;span class="caps"&gt;DNS&lt;/span&gt; with &lt;a href="https://steadypub.com/2026/06/pihole-vs-adguard-home/"&gt;Pi-hole vs AdGuard&amp;nbsp;Home&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[internal_link] Deploy a monitoring stack with &lt;a href="https://steadypub.com/2026/06/grafana-prometheus-setup/"&gt;Grafana +&amp;nbsp;Prometheus&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[internal_link] Manage all your containers with &lt;a href="https://steadypub.com/2026/06/portainer-docker-management/"&gt;Portainer Docker&amp;nbsp;Management&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[internal_link] Run Proxmox as your hypervisor with the &lt;a href="https://steadypub.com/2026/06/proxmox-beginner-guide-2026/"&gt;Proxmox Beginner Guide&amp;nbsp;2026&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[internal_link] Self-host Google Photos alternative with &lt;a href="https://steadypub.com/2026/06/immich-reverse-proxy/"&gt;Immich Reverse Proxy&amp;nbsp;Setup&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/NginxProxyManager/nginx-proxy-manager"&gt;Nginx Proxy Manager&amp;nbsp;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nginxproxymanager.com/"&gt;Official&amp;nbsp;Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://letsencrypt.org/docs/"&gt;Let&amp;#8217;s Encrypt&amp;nbsp;Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.cloudflare.com/fundamentals/api/get-started/create-token/"&gt;Cloudflare &lt;span class="caps"&gt;API&lt;/span&gt; Token&amp;nbsp;Guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Have questions or want to share your &lt;span class="caps"&gt;NPM&lt;/span&gt; setup? Join us in the &lt;a href="https://reddit.com/r/selfhosted"&gt;r/selfhosted&lt;/a&gt; community. If this guide helped you, check out our other Docker Compose tutorials — every one is copy-paste&amp;nbsp;ready.&lt;/em&gt;&lt;/p&gt;</content><category term="Tutorials"/><category term="nginx-proxy-manager"/><category term="docker"/><category term="docker-compose"/><category term="reverse-proxy"/><category term="homelab"/><category term="self-hosted"/><category term="ssl"/><category term="lets-encrypt"/><category term="portainer"/><category term="cloudflare"/></entry><entry><title>Self-Hosted Media Server 2026: Jellyfin vs Plex vs Emby — The Complete Homelab Guide</title><link href="https://steadypub.com/2026/06/self-hosted-media-server-jellyfin-plex-emby/" rel="alternate"/><published>2026-06-06T00:00:00+07:00</published><updated>2026-06-06T00:00:00+07:00</updated><author><name>WordForge Team</name></author><id>tag:steadypub.com,2026-06-06:/2026/06/self-hosted-media-server-jellyfin-plex-emby/</id><summary type="html">&lt;p&gt;Compare Jellyfin, Plex, and Emby for your 2026 homelab. Includes Docker Compose setup for all three, hardware transcoding requirements, 4K streaming benchmarks, remote access strategies, and a decision tree to pick the right media&amp;nbsp;server.&lt;/p&gt;</summary><content type="html">&lt;hr&gt;
&lt;h1&gt;Self-Hosted Media Server 2026: Jellyfin vs Plex vs Emby — The Complete Homelab&amp;nbsp;Guide&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~16 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab owners building their first media server&amp;nbsp;stack&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Introduction: Why Self-Host Your Media in&amp;nbsp;2026?&lt;/h2&gt;
&lt;p&gt;Streaming subscriptions have become cable &lt;span class="caps"&gt;TV&lt;/span&gt; in disguise. Between Netflix ($17.99), Disney+ ($15.99), Max ($16.99), Hulu ($18.99), and a half-dozen others, the monthly bill easily crosses $100 — and you still do not own anything. Shows vanish overnight when licensing deals expire. Regional restrictions block content you paid for. And every platform now injects ads into their &amp;#8220;ad-free&amp;#8221;&amp;nbsp;tiers.&lt;/p&gt;
&lt;p&gt;Building a self-hosted media server solves all three problems: &lt;strong&gt;you own your media&lt;/strong&gt;, &lt;strong&gt;you control access&lt;/strong&gt;, and &lt;strong&gt;you pay once for hardware that lasts years&lt;/strong&gt;. A full media server setup — a refurbished mini &lt;span class="caps"&gt;PC&lt;/span&gt;, a couple of 8 &lt;span class="caps"&gt;TB&lt;/span&gt; hard drives, and free open-source software — pays for itself in under 12 months compared to streaming subscriptions. After that, it is pure&amp;nbsp;savings.&lt;/p&gt;
&lt;p&gt;In 2026, the self-hosted media server landscape has three clear contenders: &lt;strong&gt;Jellyfin&lt;/strong&gt; (fully open-source and free), &lt;strong&gt;Plex&lt;/strong&gt; (commercial, polished, widely supported), and &lt;strong&gt;Emby&lt;/strong&gt; (the middle ground with an open core and optional premium). This guide compares all three — something no other article does — with real Docker Compose files you can copy and paste, hardware transcoding requirements for 4K streaming, and a decision tree that tells you which to pick in under a&amp;nbsp;minute.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The Three Contenders at a&amp;nbsp;Glance&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Jellyfin&lt;/th&gt;
&lt;th&gt;Plex&lt;/th&gt;
&lt;th&gt;Emby&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;License&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;GPL&lt;/span&gt; (fully open-source)&lt;/td&gt;
&lt;td&gt;Proprietary (freemium)&lt;/td&gt;
&lt;td&gt;Proprietary (open-core)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Completely free&lt;/td&gt;
&lt;td&gt;Free base; Plex Pass $6.99/mo&lt;/td&gt;
&lt;td&gt;Free base; Emby Premiere $4.99/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cloud dependency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;None — fully local&lt;/td&gt;
&lt;td&gt;Required for authentication&lt;/td&gt;
&lt;td&gt;Optional (local auth available)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hardware transcoding&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Free (&lt;span class="caps"&gt;VAAPI&lt;/span&gt;, &lt;span class="caps"&gt;QSV&lt;/span&gt;, &lt;span class="caps"&gt;NVENC&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;Requires Plex Pass&lt;/td&gt;
&lt;td&gt;Requires Emby Premiere&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Client apps&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Good (Android, iOS, web, Roku, Apple &lt;span class="caps"&gt;TV&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;Excellent (every platform)&lt;/td&gt;
&lt;td&gt;Very good (most platforms)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Plugin ecosystem&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Growing community plugins&lt;/td&gt;
&lt;td&gt;Official channels + agents&lt;/td&gt;
&lt;td&gt;Plugin catalog&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Live &lt;span class="caps"&gt;TV&lt;/span&gt; / &lt;span class="caps"&gt;DVR&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Free (HDHomeRun, m3u)&lt;/td&gt;
&lt;td&gt;Plex Pass required&lt;/td&gt;
&lt;td&gt;Emby Premiere required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;User management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Built-in, no limits&lt;/td&gt;
&lt;td&gt;Built-in, managed users free&lt;/td&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mobile sync/download&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Not native (3rd-party)&lt;/td&gt;
&lt;td&gt;Plex Pass required&lt;/td&gt;
&lt;td&gt;Emby Premiere required&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The short version: pick Jellyfin if you want everything free and do not mind occasional rough edges. Pick Plex if you want Netflix-like polish and are willing to pay for premium features. Pick Emby if you want more customization than Plex but better app support than&amp;nbsp;Jellyfin.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Deep Dive: How Each Platform&amp;nbsp;Works&lt;/h2&gt;
&lt;h3&gt;Jellyfin — The Open-Source&amp;nbsp;Purist&lt;/h3&gt;
&lt;p&gt;Jellyfin is a fork of Emby 3.5.2, created in December 2018 when Emby closed its source code. Since then, the Jellyfin community has built a fully open-source media server under the &lt;span class="caps"&gt;GPL&lt;/span&gt; license. There is no premium tier, no paywall, and no cloud authentication server phoning home. Everything runs locally on your&amp;nbsp;hardware.&lt;/p&gt;
&lt;p&gt;Jellyfin&amp;#8217;s plugin ecosystem is community-driven and covers metadata fetching (TheMovieDB, TheTVDB, OpenSubtitles), client-side features (Kodi Sync, Intro Skipper), and advanced tools (Bookshelf for ebooks, Tautulli-style analytics). Hardware transcoding works out of the box with Intel Quick Sync (&lt;span class="caps"&gt;QSV&lt;/span&gt;), &lt;span class="caps"&gt;AMD&lt;/span&gt; &lt;span class="caps"&gt;VAAPI&lt;/span&gt;, and &lt;span class="caps"&gt;NVIDIA&lt;/span&gt; &lt;span class="caps"&gt;NVENC&lt;/span&gt; — no license key&amp;nbsp;required.&lt;/p&gt;
&lt;p&gt;The trade-off: Jellyfin&amp;#8217;s client apps, while solid, are not as polished as Plex. The Apple &lt;span class="caps"&gt;TV&lt;/span&gt; app is community-maintained (Swiftfin). The Roku app occasionally lags behind the web client in features. For power users comfortable with a bit of rough-around-the-edges software, Jellyfin is the obvious choice. It is the only option that respects your privacy&amp;nbsp;unconditionally.&lt;/p&gt;
&lt;h3&gt;Plex — The Polished Commercial&amp;nbsp;Option&lt;/h3&gt;
&lt;p&gt;Plex is the most mature media server platform, with over 15 years of development. It offers a freemium model: the core server and playback are free, but premium features — hardware transcoding, Live &lt;span class="caps"&gt;TV&lt;/span&gt;/&lt;span class="caps"&gt;DVR&lt;/span&gt;, mobile sync, skip intro, and Plexamp — require a Plex Pass subscription ($6.99/month, $39.99/year, or $149.99&amp;nbsp;lifetime).&lt;/p&gt;
&lt;p&gt;Plex&amp;#8217;s biggest strength is its client app ecosystem. There is a native app for every device imaginable: every smart &lt;span class="caps"&gt;TV&lt;/span&gt; platform, every streaming stick, every game console, and every mobile &lt;span class="caps"&gt;OS&lt;/span&gt;. The Plexamp music player is genuinely excellent. Plex&amp;#8217;s metadata matching is best-in-class, and the discovery features (&lt;span class="caps"&gt;AI&lt;/span&gt;-powered recommendations, &amp;#8220;Plex Discover&amp;#8221; universal watchlist, cross-service search) feel like a commercial streaming&amp;nbsp;service.&lt;/p&gt;
&lt;p&gt;The trade-off: Plex requires cloud authentication for user sign-in. When Plex&amp;#8217;s auth servers go down — and they do, a few times a year — you cannot sign into your own server. The mobile apps require a one-time $5.99 activation fee (or Plex Pass) for full playback. And Plex has been gradually layering in their own ad-supported content, which purists find distasteful on a self-hosted&amp;nbsp;server.&lt;/p&gt;
&lt;h3&gt;Emby — The Middle&amp;nbsp;Ground&lt;/h3&gt;
&lt;p&gt;Emby occupies the space between Jellyfin&amp;#8217;s open-source purity and Plex&amp;#8217;s commercial polish. Its core server is proprietary but exposes enough configuration for power users. Emby Premiere ($4.99/month, $54/year, or $149 lifetime) unlocks hardware transcoding, Live &lt;span class="caps"&gt;TV&lt;/span&gt;/&lt;span class="caps"&gt;DVR&lt;/span&gt;, mobile sync, cover art customization, and Cinema Intros — roughly equivalent to Plex Pass at a slightly lower subscription&amp;nbsp;price.&lt;/p&gt;
&lt;p&gt;Emby&amp;#8217;s unique strengths: local authentication is a first-class feature (unlike Plex), the metadata manager is more flexible than Plex&amp;#8217;s, and the plugin architecture supports deeper customization. Emby also has better parental controls than Jellyfin and a more configurable home screen layout. Client support covers all major platforms, though the app ecosystem is smaller than&amp;nbsp;Plex.&lt;/p&gt;
&lt;p&gt;The trade-off: Emby&amp;#8217;s community is the smallest of the three. Fewer plugins, fewer third-party tools, and fewer community-written guides exist compared to Jellyfin or Plex. Documentation quality varies. And like Jellyfin, the premium features are behind a paywall — though unlike Plex, Emby does not require cloud&amp;nbsp;authentication.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Hardware Transcoding: What Your Homelab&amp;nbsp;Needs&lt;/h2&gt;
&lt;p&gt;Hardware transcoding converts video from one format to another in real time using a &lt;span class="caps"&gt;GPU&lt;/span&gt; or integrated graphics. Without it, the &lt;span class="caps"&gt;CPU&lt;/span&gt; must handle transcoding in software, which is slow and power-hungry. For a single 1080p stream, any modern &lt;span class="caps"&gt;CPU&lt;/span&gt; handles software transcoding fine. For 4K &lt;span class="caps"&gt;HDR&lt;/span&gt; with tone mapping, hardware transcoding is&amp;nbsp;mandatory.&lt;/p&gt;
&lt;h3&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt; Requirements Per&amp;nbsp;Stream&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Stream Type&lt;/th&gt;
&lt;th&gt;Software (&lt;span class="caps"&gt;CPU&lt;/span&gt; only)&lt;/th&gt;
&lt;th&gt;Hardware (&lt;span class="caps"&gt;GPU&lt;/span&gt;/iGPU)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1080p → 1080p&lt;/td&gt;
&lt;td&gt;~2,000 PassMark per stream&lt;/td&gt;
&lt;td&gt;Minimal &lt;span class="caps"&gt;GPU&lt;/span&gt; usage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1080p → 720p&lt;/td&gt;
&lt;td&gt;~1,500 PassMark per stream&lt;/td&gt;
&lt;td&gt;Minimal &lt;span class="caps"&gt;GPU&lt;/span&gt; usage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4K → 1080p (&lt;span class="caps"&gt;SDR&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;~12,000 PassMark per stream&lt;/td&gt;
&lt;td&gt;Intel &lt;span class="caps"&gt;QSV&lt;/span&gt; or &lt;span class="caps"&gt;NVIDIA&lt;/span&gt; &lt;span class="caps"&gt;NVENC&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4K &lt;span class="caps"&gt;HDR&lt;/span&gt; → 1080p &lt;span class="caps"&gt;SDR&lt;/span&gt; (tone mapping)&lt;/td&gt;
&lt;td&gt;~17,000 PassMark per stream&lt;/td&gt;
&lt;td&gt;Intel &lt;span class="caps"&gt;QSV&lt;/span&gt; (7th-gen+) or &lt;span class="caps"&gt;NVIDIA&lt;/span&gt; 1050+&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;A practical example: an Intel Core i3-12100 (PassMark ~13,400) can handle roughly one 4K software transcode or 6+ 1080p software transcodes. Add Intel Quick Sync, and that same i3-12100 handles 4-5 simultaneous 4K &lt;span class="caps"&gt;HDR&lt;/span&gt;-to-1080p &lt;span class="caps"&gt;SDR&lt;/span&gt; transcodes with tone mapping — a 5x&amp;nbsp;improvement.&lt;/p&gt;
&lt;h3&gt;&lt;span class="caps"&gt;GPU&lt;/span&gt;/iGPU Recommendations for Hardware&amp;nbsp;Transcoding&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Hardware&lt;/th&gt;
&lt;th&gt;Transcode Engine&lt;/th&gt;
&lt;th&gt;4K Performance&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Intel Quick Sync (7th-gen+)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;QSV&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;4-8 simultaneous 4K transcodes&lt;/td&gt;
&lt;td&gt;Most homelab builds; free with Intel &lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Intel Arc A310/A380&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;QSV&lt;/span&gt; (discrete)&lt;/td&gt;
&lt;td&gt;8+ simultaneous 4K transcodes&lt;/td&gt;
&lt;td&gt;Dedicated transcoding box; &lt;span class="caps"&gt;AV1&lt;/span&gt; encode&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;NVIDIA&lt;/span&gt; &lt;span class="caps"&gt;GTX&lt;/span&gt; 1050 Ti+&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;NVENC&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;3-5 simultaneous 4K transcodes&lt;/td&gt;
&lt;td&gt;Existing gaming &lt;span class="caps"&gt;GPU&lt;/span&gt; reuse&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;NVIDIA&lt;/span&gt; Quadro P400&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;NVENC&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;2-3 simultaneous 4K transcodes&lt;/td&gt;
&lt;td&gt;Low-power, no external power needed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;AMD&lt;/span&gt; Ryzen &lt;span class="caps"&gt;APU&lt;/span&gt; (Vega)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;VCN&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1-2 simultaneous 4K transcodes&lt;/td&gt;
&lt;td&gt;Budget builds; Linux &lt;span class="caps"&gt;VAAPI&lt;/span&gt; support improving&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;The homelab sweet spot:&lt;/strong&gt; An Intel N100 mini &lt;span class="caps"&gt;PC&lt;/span&gt; (~$150) with Quick Sync handles 2-3 simultaneous 4K transcodes while drawing 6W idle. Pair it with a &lt;span class="caps"&gt;NAS&lt;/span&gt; for storage, and you have a media server that rivals a $2,000 prebuilt &lt;span class="caps"&gt;NAS&lt;/span&gt; in transcoding&amp;nbsp;capability.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Docker Compose Setup: Get Running in 10&amp;nbsp;Minutes&lt;/h2&gt;
&lt;p&gt;All three media servers run beautifully in Docker. The key is passing through the hardware transcoding device&amp;nbsp;(&lt;code&gt;/dev/dri&lt;/code&gt;) and mapping your media directories&amp;nbsp;correctly.&lt;/p&gt;
&lt;h3&gt;Jellyfin Docker&amp;nbsp;Compose&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;3.8&amp;#39;&lt;/span&gt;
&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;jellyfin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;jellyfin/jellyfin:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;jellyfin&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;network_mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;host&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Simplifies DLNA and discovery&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;PUID=1000&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;PGID=1000&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TZ=Asia/Jakarta&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./config:/config&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./cache:/cache&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/mnt/media/tv:/data/tvshows&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/mnt/media/movies:/data/movies&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/mnt/media/music:/data/music&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;devices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/dev/dri:/dev/dri&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Intel Quick Sync hardware transcoding&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# For NVIDIA GPUs, add:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# deploy:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#   resources:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#     reservations:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#       devices:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#         - driver: nvidia&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#           count: 1&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#           capabilities: [gpu]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After &lt;code&gt;docker compose up -d&lt;/code&gt;, Jellyfin is available&amp;nbsp;at &lt;code&gt;http://your-server-ip:8096&lt;/code&gt;. Complete the setup wizard, add your media libraries, and enable hardware transcoding under &lt;strong&gt;Dashboard → Playback → Hardware Acceleration → Intel Quick Sync (&lt;span class="caps"&gt;QSV&lt;/span&gt;)&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;Plex Docker&amp;nbsp;Compose&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;3.8&amp;#39;&lt;/span&gt;
&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;plex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;lscr.io/linuxserver/plex:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;plex&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;network_mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;host&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;PUID=1000&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;PGID=1000&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TZ=Asia/Jakarta&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;VERSION=docker&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;PLEX_CLAIM=claim-xxxxxxxxxxxxx&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Get from https://plex.tv/claim&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./config:/config&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/mnt/media/tv:/tv&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/mnt/media/movies:/movies&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/mnt/media/music:/music&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;devices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/dev/dri:/dev/dri&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; &lt;code&gt;PLEX_CLAIM&lt;/code&gt; is a one-time token that links your server to your Plex account. It expires in 4 minutes — generate it at &lt;a href="https://plex.tv/claim"&gt;plex.tv/claim&lt;/a&gt; right before&amp;nbsp;running &lt;code&gt;docker compose up -d&lt;/code&gt;. The claim token is only needed for first-run; remove it after&amp;nbsp;setup.&lt;/p&gt;
&lt;p&gt;Plex is available&amp;nbsp;at &lt;code&gt;http://your-server-ip:32400/web&lt;/code&gt;. Hardware transcoding is enabled under &lt;strong&gt;Settings → Transcoder → Use hardware acceleration when available&lt;/strong&gt; — but remember, &lt;strong&gt;this requires Plex Pass&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;Emby Docker&amp;nbsp;Compose&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;3.8&amp;#39;&lt;/span&gt;
&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;emby&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;emby/embyserver:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;emby&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;network_mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;host&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;UID=1000&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;GID=1000&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;GIDLIST=1000,44,109&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# 44=video, 109=render for hardware transcoding&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TZ=Asia/Jakarta&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./config:/config&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/mnt/media/tv:/mnt/share1&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/mnt/media/movies:/mnt/share2&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/mnt/media/music:/mnt/share3&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;devices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/dev/dri:/dev/dri&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Emby is available&amp;nbsp;at &lt;code&gt;http://your-server-ip:8096&lt;/code&gt;.&amp;nbsp;The &lt;code&gt;GIDLIST&lt;/code&gt; environment variable includes group IDs&amp;nbsp;for &lt;code&gt;video&lt;/code&gt; (44)&amp;nbsp;and &lt;code&gt;render&lt;/code&gt; (109), which are required for hardware transcoding access on Linux. Enable hardware transcoding in &lt;strong&gt;Settings → Transcoding → Enable hardware acceleration&lt;/strong&gt;. &lt;strong&gt;Requires Emby&amp;nbsp;Premiere.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;Reverse Proxy&amp;nbsp;Integration&lt;/h3&gt;
&lt;p&gt;Once your media server is running, you probably want to access it with a proper domain. Here is an example Nginx Proxy Manager (&lt;span class="caps"&gt;NPM&lt;/span&gt;)&amp;nbsp;config:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Domain:&lt;/strong&gt; &lt;code&gt;jellyfin.yourdomain.com&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scheme:&lt;/strong&gt; &lt;code&gt;http&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Forward &lt;span class="caps"&gt;IP&lt;/span&gt;:&lt;/strong&gt; &lt;code&gt;192.168.1.50&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Forward&amp;nbsp;Port:&lt;/strong&gt; &lt;code&gt;8096&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;SSL&lt;/span&gt;:&lt;/strong&gt; Request Let&amp;#8217;s Encrypt&amp;nbsp;certificate&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WebSocket Support:&lt;/strong&gt; Enable (required for playback progress&amp;nbsp;reporting)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you are using Cloudflare Tunnel instead of port forwarding, add a public hostname pointing&amp;nbsp;to &lt;code&gt;http://localhost:8096&lt;/code&gt; inside&amp;nbsp;the &lt;code&gt;cloudflared&lt;/code&gt; configuration. See our &lt;a href="/cloudflare-tunnel-homelab/"&gt;Cloudflare Tunnel guide&lt;/a&gt; for the full walkthrough. For detailed &lt;span class="caps"&gt;NPM&lt;/span&gt; configuration, refer to our &lt;a href="/nginx-proxy-manager-docker-compose/"&gt;Nginx Proxy Manager tutorial&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;4K Streaming &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; Real-World&amp;nbsp;Performance&lt;/h2&gt;
&lt;p&gt;4K is where media servers earn their keep. Direct Play — streaming without any transcoding — is the ideal path: the client device decodes the original file, and the server does almost no work. A Raspberry Pi 4 can Direct Play 4K to a modern smart &lt;span class="caps"&gt;TV&lt;/span&gt; all&amp;nbsp;day.&lt;/p&gt;
&lt;p&gt;The challenge is &lt;strong&gt;transcoding&lt;/strong&gt;: when the client cannot play the original format (wrong codec, insufficient bandwidth, burned subtitles), the server must convert the stream in real&amp;nbsp;time.&lt;/p&gt;
&lt;h3&gt;Bandwidth&amp;nbsp;Requirements&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Quality&lt;/th&gt;
&lt;th&gt;Direct Play (per stream)&lt;/th&gt;
&lt;th&gt;Transcode Target&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;4K Blu-ray remux&lt;/td&gt;
&lt;td&gt;60-100 Mbps&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4K streaming (web-dl)&lt;/td&gt;
&lt;td&gt;25-40 Mbps&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4K → 1080p (10 Mbps)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;~10 Mbps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1080p Blu-ray remux&lt;/td&gt;
&lt;td&gt;25-35 Mbps&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1080p streaming&lt;/td&gt;
&lt;td&gt;8-15 Mbps&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Network recommendation:&lt;/strong&gt; Gigabit Ethernet (1 Gbps) for your media server and any wired clients. A single 4K remux (~80 Mbps average, bursting higher) will saturate a 100 Mbps link. For Wi-Fi clients, ensure a strong 5 GHz signal and expect occasional buffering on high-bitrate 4K files. If you are &lt;a href="/homelab-networking-basics/"&gt;setting up your homelab network&lt;/a&gt;, invest in a managed switch with at least Gigabit ports on every&amp;nbsp;link.&lt;/p&gt;
&lt;h3&gt;Jellyfin-Specific: Tone&amp;nbsp;Mapping&lt;/h3&gt;
&lt;p&gt;Jellyfin&amp;#8217;s 4K &lt;span class="caps"&gt;HDR&lt;/span&gt;-to-&lt;span class="caps"&gt;SDR&lt;/span&gt; tone mapping is entirely free and works with Intel Quick Sync on 7th-gen CPUs and newer, plus &lt;span class="caps"&gt;NVIDIA&lt;/span&gt; GPUs. This is a massive advantage over Plex and Emby, both of which gate hardware tone mapping behind their premium&amp;nbsp;tiers.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Remote Access: How to Stream from&amp;nbsp;Anywhere&lt;/h2&gt;
&lt;p&gt;Once your media server is running locally, the next question is how to access it outside your&amp;nbsp;home.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Security&lt;/th&gt;
&lt;th&gt;Complexity&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;WireGuard / Tailscale &lt;span class="caps"&gt;VPN&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Excellent&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;You + a few trusted users; no public exposure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cloudflare Tunnel&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Very good&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Public access without opening ports; &lt;span class="caps"&gt;HTTPS&lt;/span&gt; included&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Reverse proxy + Let&amp;#8217;s Encrypt&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Full public access with domain + &lt;span class="caps"&gt;SSL&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Port forwarding&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Poor&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Last resort; exposes your home &lt;span class="caps"&gt;IP&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For the privacy-focused approach, install Tailscale on your media server and every client device. You get encrypted WireGuard tunnels, a private &lt;span class="caps"&gt;IP&lt;/span&gt; range (100.x.x.x), and zero ports exposed to the internet. Tailscale&amp;#8217;s free plan supports up to 100&amp;nbsp;devices.&lt;/p&gt;
&lt;p&gt;For sharing with family members who are not technical, use Cloudflare Tunnel. It creates an outbound-only connection from your homelab to Cloudflare&amp;#8217;s edge — no open ports, no &lt;span class="caps"&gt;DDNS&lt;/span&gt;, and free &lt;span class="caps"&gt;SSL&lt;/span&gt;. Combine it with Cloudflare Access policies to require a one-time email code or Google login before anyone reaches your server. Our &lt;a href="/cloudflare-tunnel-homelab/"&gt;Cloudflare Tunnel guide&lt;/a&gt; covers the full&amp;nbsp;setup.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Decision Tree: Which Media Server Is Right for&amp;nbsp;You?&lt;/h2&gt;
&lt;p&gt;Answer these questions to find your match in under a&amp;nbsp;minute:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Do you want everything completely free and are willing to accept slightly less polished client apps?&lt;/strong&gt;
   → &lt;strong&gt;Jellyfin.&lt;/strong&gt; Free hardware transcoding, free Live &lt;span class="caps"&gt;TV&lt;/span&gt;/&lt;span class="caps"&gt;DVR&lt;/span&gt;, no cloud dependency, no accounts to create. The open-source purist&amp;#8217;s&amp;nbsp;choice.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Do you want the closest thing to a self-hosted Netflix with the best apps on every device, and are you okay paying for premium features?&lt;/strong&gt;
   → &lt;strong&gt;Plex.&lt;/strong&gt; Pay for Plex Pass ($149 lifetime is the best value), and you get a polished experience that your family will actually use without&amp;nbsp;complaining.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Do you want more customization than Plex, better app support than Jellyfin, and the option to keep authentication fully local?&lt;/strong&gt;
   → &lt;strong&gt;Emby.&lt;/strong&gt; Emby Premiere ($149 lifetime) unlocks hardware transcoding. The middle ground that many homelabbers overlook — but should&amp;nbsp;not.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Still undecided?&lt;/strong&gt; You do not have to choose just one. Many homelabbers run Jellyfin as their primary server and keep Plex installed for the rare family member who insists on the Plex app. Both can point at the same media directories. Try Jellyfin first — it is free and takes 10 minutes with the Docker Compose file above. If you hit a wall with client support, try Plex or Emby alongside&amp;nbsp;it.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;&lt;span class="caps"&gt;FAQ&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Can I migrate from Plex to Jellyfin?&lt;/strong&gt;
Yes — and it is surprisingly easy. Both servers read the same media files. Your watch history is the main thing that does not transfer. Use the community tool &lt;a href="https://github.com/taxigps/jellyfin-plex-trakt-sync"&gt;Jellyfin-Plex-Trakt-Sync&lt;/a&gt; to sync watch status via Trakt.tv as a bridge. For metadata, Jellyfin rescans your libraries and fetches cover art, descriptions, and cast information from the same sources Plex uses (TheMovieDB,&amp;nbsp;TheTVDB).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Does Jellyfin work on Apple &lt;span class="caps"&gt;TV&lt;/span&gt;?&lt;/strong&gt;
Yes, via the &lt;a href="https://apps.apple.com/app/swiftfin/id1604098728"&gt;Swiftfin&lt;/a&gt; app (community-maintained, free, App Store). It handles Direct Play beautifully and supports 4K &lt;span class="caps"&gt;HDR&lt;/span&gt;. Transcoding-heavy use cases may encounter occasional issues. An official Jellyfin Apple &lt;span class="caps"&gt;TV&lt;/span&gt; app is in development but not yet&amp;nbsp;released.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Is hardware transcoding really free on Jellyfin?&lt;/strong&gt;
Yes. Completely. Jellyfin includes &lt;span class="caps"&gt;VAAPI&lt;/span&gt;, Intel Quick Sync, &lt;span class="caps"&gt;NVIDIA&lt;/span&gt; &lt;span class="caps"&gt;NVENC&lt;/span&gt;, and &lt;span class="caps"&gt;AMD&lt;/span&gt; &lt;span class="caps"&gt;VCN&lt;/span&gt; hardware acceleration with no license, no subscription, and no activation required. This alone saves you $149 (Plex Pass lifetime) or $149 (Emby Premiere lifetime). Jellyfin&amp;#8217;s &lt;span class="caps"&gt;HDR&lt;/span&gt;-to-&lt;span class="caps"&gt;SDR&lt;/span&gt; tone mapping is also free — a feature both competitors&amp;nbsp;paywall.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Can I run multiple media servers on the same hardware?&lt;/strong&gt;
Absolutely. Point Jellyfin, Plex, and Emby at the same media directories. As long as each runs on a different port (8096, 32400, 8096 respectively — note Jellyfin and Emby default to the same port, so change one), they coexist without conflict. This is common in the homelab community: run Jellyfin as the daily driver, keep Plex installed for testing or for a family member who insists on the Plex&amp;nbsp;app.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Jellyfin, Plex, and Emby each serve a distinct audience within the homelab community. Jellyfin delivers a fully open-source, zero-cost media server that respects your privacy absolutely — at the cost of slightly rougher client apps. Plex offers a polished, Netflix-like experience across every device imaginable, backed by 15 years of development — but locks its best features behind a paywall and requires cloud authentication. Emby strikes a middle ground with local auth, flexible customization, and solid app support — but has the smallest&amp;nbsp;community.&lt;/p&gt;
&lt;p&gt;No matter which you choose, Docker Compose makes setup trivially easy. Copy&amp;nbsp;the &lt;code&gt;docker-compose.yml&lt;/code&gt; above, set your media paths,&amp;nbsp;run &lt;code&gt;docker compose up -d&lt;/code&gt;, and you have a media server in under 10 minutes. Pair it with a &lt;a href="/mini-pc-home-server-2025/"&gt;low-power mini &lt;span class="caps"&gt;PC&lt;/span&gt;&lt;/a&gt; for always-on operation, store your media on a &lt;a href="/best-nas-os-homelab-2026/"&gt;proper &lt;span class="caps"&gt;NAS&lt;/span&gt; &lt;span class="caps"&gt;OS&lt;/span&gt;&lt;/a&gt;, and &lt;a href="/cloudflare-tunnel-homelab/"&gt;secure remote access&lt;/a&gt; with Cloudflare Tunnel or&amp;nbsp;Tailscale.&lt;/p&gt;
&lt;p&gt;The $100/month streaming bill ends today. Your self-hosted media server starts&amp;nbsp;now.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Want more homelab guides? Check out our &lt;a href="/proxmox-beginner-guide-2026/"&gt;Proxmox beginner guide&lt;/a&gt; for running your media server in a &lt;span class="caps"&gt;VM&lt;/span&gt; or &lt;span class="caps"&gt;LXC&lt;/span&gt;, our &lt;a href="/docker-compose-for-beginners/"&gt;Docker Compose for beginners&lt;/a&gt; tutorial, and our guide to the &lt;a href="/best-self-hosted-apps-2026/"&gt;best self-hosted apps of 2026&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;</content><category term="Guides"/><category term="jellyfin"/><category term="plex"/><category term="emby"/><category term="media server"/><category term="self-hosted"/><category term="homelab"/><category term="docker"/><category term="docker-compose"/><category term="transcoding"/><category term="4k"/><category term="streaming"/><category term="nas"/><category term="hardware"/></entry><entry><title>Best European VPS for Homelab 2026: Self-Hosting on EU Servers</title><link href="https://steadypub.com/2026/06/best-europe-vps-homelab/" rel="alternate"/><published>2026-06-05T00:33:00+07:00</published><updated>2026-06-05T00:33:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/best-europe-vps-homelab/</id><summary type="html">&lt;p&gt;Compared and ranked the top European &lt;span class="caps"&gt;VPS&lt;/span&gt; providers for homelab self-hosting. Real specs, pricing, and use-case recommendations for Docker, &lt;span class="caps"&gt;VPN&lt;/span&gt;, and backup&amp;nbsp;nodes.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~14 minutes&lt;br&gt;
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab users who need an offsite &lt;span class="caps"&gt;VPS&lt;/span&gt; for public-facing services, backups, or &lt;span class="caps"&gt;VPN&lt;/span&gt; endpoints&lt;br&gt;
&lt;strong&gt;Last updated:&lt;/strong&gt; June&amp;nbsp;2026&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why Use a European &lt;span class="caps"&gt;VPS&lt;/span&gt; for Your&amp;nbsp;Homelab?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;A European &lt;span class="caps"&gt;VPS&lt;/span&gt; bridges the gap between your local homelab and the public internet. It gives you a static &lt;span class="caps"&gt;IP&lt;/span&gt;, DDoS protection, and reliable uptime for services that cannot run behind a residential &lt;span class="caps"&gt;NAT&lt;/span&gt; or dynamic &lt;span class="caps"&gt;IP&lt;/span&gt;. Common homelab &lt;span class="caps"&gt;VPS&lt;/span&gt; use cases&amp;nbsp;include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Public reverse proxy / tunnel:&lt;/strong&gt; Expose local services through a &lt;span class="caps"&gt;VPS&lt;/span&gt; with a stable &lt;span class="caps"&gt;IP&lt;/span&gt; (e.g., &lt;span class="caps"&gt;FRP&lt;/span&gt;, WireGuard reverse tunnel, Cloudflare&amp;nbsp;Tunnel)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Offsite backup target:&lt;/strong&gt; Run Restic, BorgBackup, or rsync.net-compatible&amp;nbsp;storage&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mail server relay:&lt;/strong&gt; Host your own email without risking your residential &lt;span class="caps"&gt;IP&lt;/span&gt;&amp;nbsp;reputation&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Monitoring beacon:&lt;/strong&gt; Uptime Kuma or Nagios checking your home services from&amp;nbsp;outside&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;VPN&lt;/span&gt; hub:&lt;/strong&gt; WireGuard or Tailscale coordination server for road-warrior&amp;nbsp;access&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Evaluation&amp;nbsp;Criteria&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Criterion&lt;/th&gt;
&lt;th&gt;Weight&lt;/th&gt;
&lt;th&gt;Why It Matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Price-to-performance&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Homelabs run on tight budgets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network quality&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Low latency to &lt;span class="caps"&gt;EU&lt;/span&gt;, generous bandwidth&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Privacy / &lt;span class="caps"&gt;GDPR&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;EU&lt;/span&gt;-based means stronger data protection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IPv6 support&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Future-proofing and simpler &lt;span class="caps"&gt;NAT&lt;/span&gt; bypass&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;API&lt;/span&gt; &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; automation&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Terraform, Ansible, and &lt;span class="caps"&gt;CI&lt;/span&gt;/&lt;span class="caps"&gt;CD&lt;/span&gt; integration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Support quality&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Homelab users typically self-support&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;#1:&amp;nbsp;Hetzner&lt;/h2&gt;
&lt;h3&gt;Why It Tops Our&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;Hetzner is the undisputed king of price-to-performance in the European &lt;span class="caps"&gt;VPS&lt;/span&gt; market. Their &lt;span class="caps"&gt;ARM64&lt;/span&gt; and x86_64 cloud instances undercut most competitors by 30–50% while delivering consistent performance on modern &lt;span class="caps"&gt;AMD&lt;/span&gt; &lt;span class="caps"&gt;EPYC&lt;/span&gt; and Ampere Altra&amp;nbsp;hardware.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plan&lt;/th&gt;
&lt;th&gt;vCPU&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Traffic&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;CX11&lt;/span&gt; (x86)&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;20 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;20 &lt;span class="caps"&gt;TB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;€4.51/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;CPX11&lt;/span&gt; (x86)&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;40 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;20 &lt;span class="caps"&gt;TB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;€5.35/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;CAX11&lt;/span&gt; (&lt;span class="caps"&gt;ARM&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;4 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;40 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;20 &lt;span class="caps"&gt;TB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;€3.29/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;CPX31&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;8 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;160 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;20 &lt;span class="caps"&gt;TB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;€13.10/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Best price/&lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt; in Europe; &lt;span class="caps"&gt;ARM&lt;/span&gt; instances are exceptionally&amp;nbsp;cheap&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;20 &lt;span class="caps"&gt;TB&lt;/span&gt; traffic&lt;/strong&gt; on all plans (essentially unmetered for homelab&amp;nbsp;scale)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Falkenstein (&lt;span class="caps"&gt;FSN1&lt;/span&gt;)&lt;/strong&gt; and &lt;strong&gt;Nuremberg (&lt;span class="caps"&gt;NBG1&lt;/span&gt;)&lt;/strong&gt; datacenters with excellent &lt;span class="caps"&gt;EU&lt;/span&gt;&amp;nbsp;peering&lt;/li&gt;
&lt;li&gt;Native IPv6, floating IPs, and load&amp;nbsp;balancers&lt;/li&gt;
&lt;li&gt;Robust &lt;span class="caps"&gt;REST&lt;/span&gt; &lt;span class="caps"&gt;API&lt;/span&gt; and Terraform&amp;nbsp;provider&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No traditional &amp;#8220;support&amp;#8221;&lt;/strong&gt; for hobbyists; community forums and documentation&amp;nbsp;only&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Setup fee&lt;/strong&gt; (€5.11) for new customers on some&amp;nbsp;plans&lt;/li&gt;
&lt;li&gt;Strict abuse policy; port scanning or Tor exit nodes can trigger account&amp;nbsp;review&lt;/li&gt;
&lt;li&gt;No &lt;span class="caps"&gt;GUI&lt;/span&gt; backup tool; you manage snapshots via &lt;span class="caps"&gt;API&lt;/span&gt;/&lt;span class="caps"&gt;CLI&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;p&gt;Budget-conscious homelabbers running Docker stacks, VPNs, and reverse proxies. The &lt;span class="caps"&gt;CAX11&lt;/span&gt; &lt;span class="caps"&gt;ARM&lt;/span&gt; instance is the best value for lightweight Compose&amp;nbsp;deployments.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;#2:&amp;nbsp;Netcup&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;Netcup is a German provider renowned for &lt;span class="caps"&gt;VPS&lt;/span&gt; deals during seasonal sales (Black Friday, Easter). Their &amp;#8220;Root Server&amp;#8221; &lt;span class="caps"&gt;VPS&lt;/span&gt; line offers dedicated-core-like performance at shared-core prices, and their control panel is&amp;nbsp;homelab-friendly.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plan&lt;/th&gt;
&lt;th&gt;vCPU&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Traffic&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt; 200 G10s&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;40 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;40 &lt;span class="caps"&gt;TB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;€3.69/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt; 500 G10s&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;4 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;80 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;80 &lt;span class="caps"&gt;TB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;€6.19/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RS&lt;/span&gt; 1000 G9.5&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;8 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;160 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;80 &lt;span class="caps"&gt;TB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;€9.39/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RS&lt;/span&gt; 2000 G9.5&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;16 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;320 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;80 &lt;span class="caps"&gt;TB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;€16.89/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Massive traffic allowances&lt;/strong&gt; (40–80 &lt;span class="caps"&gt;TB&lt;/span&gt;) — ideal for media streaming or backup&amp;nbsp;sync&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;German datacenters&lt;/strong&gt; (Nuremberg, Karlsruhe) with excellent DDoS&amp;nbsp;protection&lt;/li&gt;
&lt;li&gt;Web-based &lt;span class="caps"&gt;VNC&lt;/span&gt; console and &lt;span class="caps"&gt;ISO&lt;/span&gt; mounting directly from the control&amp;nbsp;panel&lt;/li&gt;
&lt;li&gt;No setup fees; monthly billing with no long-term&amp;nbsp;contracts&lt;/li&gt;
&lt;li&gt;Strong IPv6 support and rDNS&amp;nbsp;management&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt; is shared&lt;/strong&gt;, not dedicated; noisy neighbors can affect latency-sensitive&amp;nbsp;workloads&lt;/li&gt;
&lt;li&gt;English support exists but is slower than German-language&amp;nbsp;tickets&lt;/li&gt;
&lt;li&gt;No object storage (S3-compatible) offering — only block&amp;nbsp;storage&lt;/li&gt;
&lt;li&gt;The web &lt;span class="caps"&gt;UI&lt;/span&gt; feels dated compared to Hetzner&amp;#8217;s cloud&amp;nbsp;console&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;p&gt;Homelabbers who need huge monthly transfer quotas for backups, video streaming, or large file distribution. Also ideal if you prefer German &lt;span class="caps"&gt;GDPR&lt;/span&gt; jurisdiction with a native-language&amp;nbsp;provider.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;#3:&amp;nbsp;OVHcloud&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;OVHcloud is the largest European cloud provider by infrastructure footprint. Their &lt;span class="caps"&gt;VPS&lt;/span&gt; line is competitively priced, but the real value for homelabbers is the &lt;strong&gt;Advance dedicated server&lt;/strong&gt; outlet deals and the free DDoS protection included with every&amp;nbsp;service.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plan&lt;/th&gt;
&lt;th&gt;vCPU&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Traffic&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt; Starter&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;40 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Unmetered&lt;/td&gt;
&lt;td&gt;€3.50/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt; Value&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;4 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;80 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Unmetered&lt;/td&gt;
&lt;td&gt;€7.00/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt; Essential&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;8 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;160 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Unmetered&lt;/td&gt;
&lt;td&gt;€14.00/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt; Comfort&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;8 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;160 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Unmetered&lt;/td&gt;
&lt;td&gt;€22.50/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Unmetered traffic&lt;/strong&gt; on all &lt;span class="caps"&gt;VPS&lt;/span&gt; plans (fair-use policy&amp;nbsp;applies)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Anti-DDoS Game&lt;/strong&gt; protection included, scrubbing attacks up to ~1&amp;nbsp;Tbps&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;14 global datacenters&lt;/strong&gt;, including 4 in France, 1 in Poland, and 1 in the &lt;span class="caps"&gt;UK&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Public Cloud &lt;span class="caps"&gt;API&lt;/span&gt;, OpenStack compatibility, and Terraform&amp;nbsp;modules&lt;/li&gt;
&lt;li&gt;Snapshot and backup options via the control&amp;nbsp;panel&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Overprovisioning&lt;/strong&gt; is common; &lt;span class="caps"&gt;CPU&lt;/span&gt; performance can be inconsistent during peak&amp;nbsp;hours&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Support reputation&lt;/strong&gt; is mixed for low-tier plans; expect forum-based&amp;nbsp;self-help&lt;/li&gt;
&lt;li&gt;Account verification can be strict (&lt;span class="caps"&gt;ID&lt;/span&gt; document&amp;nbsp;required)&lt;/li&gt;
&lt;li&gt;The control panel is complex for beginners; navigation is not&amp;nbsp;intuitive&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;p&gt;Public-facing homelab services that need DDoS protection (game servers, public websites, WireGuard endpoints). Also good if you need a &lt;span class="caps"&gt;VPS&lt;/span&gt; outside Germany for geographic&amp;nbsp;redundancy.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;#4:&amp;nbsp;Contabo&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;Contabo is famous in the self-hosting community for offering &lt;strong&gt;absurd &lt;span class="caps"&gt;RAM&lt;/span&gt; and storage specs&lt;/strong&gt; at budget prices. A 4 vCPU / 8 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; / 200 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt; &lt;span class="caps"&gt;VPS&lt;/span&gt; for under €6/month is unmatched for raw resource&amp;nbsp;quantity.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plan&lt;/th&gt;
&lt;th&gt;vCPU&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Traffic&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cloud &lt;span class="caps"&gt;VPS&lt;/span&gt; S&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;8 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;200 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;32 &lt;span class="caps"&gt;TB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;€5.99/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloud &lt;span class="caps"&gt;VPS&lt;/span&gt; M&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;16 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;400 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;32 &lt;span class="caps"&gt;TB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;€10.49/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloud &lt;span class="caps"&gt;VPS&lt;/span&gt; L&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;30 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;800 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;32 &lt;span class="caps"&gt;TB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;€17.49/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloud &lt;span class="caps"&gt;VPS&lt;/span&gt; &lt;span class="caps"&gt;XL&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;60 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1.6 &lt;span class="caps"&gt;TB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;32 &lt;span class="caps"&gt;TB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;€31.49/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Best raw specs/price ratio&lt;/strong&gt; on the&amp;nbsp;market&lt;/li&gt;
&lt;li&gt;German and &lt;span class="caps"&gt;US&lt;/span&gt; datacenters&amp;nbsp;available&lt;/li&gt;
&lt;li&gt;Full root access, &lt;span class="caps"&gt;VNC&lt;/span&gt; console, and custom &lt;span class="caps"&gt;ISO&lt;/span&gt;&amp;nbsp;upload&lt;/li&gt;
&lt;li&gt;32 &lt;span class="caps"&gt;TB&lt;/span&gt; traffic on all&amp;nbsp;plans&lt;/li&gt;
&lt;li&gt;One-time setup fee is reasonable&amp;nbsp;(€4–8)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt; is heavily shared&lt;/strong&gt; (&lt;span class="caps"&gt;AMD&lt;/span&gt; &lt;span class="caps"&gt;EPYC&lt;/span&gt; 7282); sustained loads&amp;nbsp;suffer&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Network is rate-limited&lt;/strong&gt; to 200–400 Mbps per &lt;span class="caps"&gt;VPS&lt;/span&gt; despite the 32 &lt;span class="caps"&gt;TB&lt;/span&gt;&amp;nbsp;quota&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Support is ticket-only&lt;/strong&gt; with 24–48 hour response&amp;nbsp;times&lt;/li&gt;
&lt;li&gt;Reputation for strict abuse handling; read their &lt;span class="caps"&gt;AUP&lt;/span&gt;&amp;nbsp;carefully&lt;/li&gt;
&lt;li&gt;No &lt;span class="caps"&gt;API&lt;/span&gt; for automation; management is&amp;nbsp;control-panel-only&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;p&gt;Storage-heavy homelab workloads: Nextcloud with lots of users, photo backups (Immich), media servers (Jellyfin), or large BorgBackup repositories where &lt;span class="caps"&gt;RAM&lt;/span&gt; and disk matter more than &lt;span class="caps"&gt;CPU&lt;/span&gt; burst&amp;nbsp;performance.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;#5: Ionos&amp;nbsp;(1&amp;amp;1)&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;Ionos is a solid &amp;#8220;boring but reliable&amp;#8221; choice. Their &lt;span class="caps"&gt;VPS&lt;/span&gt; line does not win on price, but the included managed backup, Windows licensing options, and 24/7 phone support make it appealing for homelabbers who also run small business&amp;nbsp;workloads.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plan&lt;/th&gt;
&lt;th&gt;vCPU&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Traffic&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt; Linux S&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;10 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Unmetered&lt;/td&gt;
&lt;td&gt;€5.00/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt; Linux M&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;40 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Unmetered&lt;/td&gt;
&lt;td&gt;€8.00/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt; Linux L&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;4 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;80 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Unmetered&lt;/td&gt;
&lt;td&gt;€12.00/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt; Linux &lt;span class="caps"&gt;XL&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;8 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;160 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Unmetered&lt;/td&gt;
&lt;td&gt;€18.00/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;24/7 phone support&lt;/strong&gt; in English and&amp;nbsp;German&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Unmetered traffic&lt;/strong&gt; with clear fair-use&amp;nbsp;policy&lt;/li&gt;
&lt;li&gt;Datacenters in Germany, &lt;span class="caps"&gt;UK&lt;/span&gt;, Spain, and &lt;span class="caps"&gt;US&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Optional managed backup and Plesk control&amp;nbsp;panel&lt;/li&gt;
&lt;li&gt;Clean, modern cloud&amp;nbsp;console&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Price is higher&lt;/strong&gt; than Hetzner or Netcup for equivalent&amp;nbsp;specs&lt;/li&gt;
&lt;li&gt;Lower traffic/network priority compared to&amp;nbsp;Hetzner&lt;/li&gt;
&lt;li&gt;No &lt;span class="caps"&gt;ARM&lt;/span&gt;&amp;nbsp;instances&lt;/li&gt;
&lt;li&gt;Contract terms can be 1–12 months depending on&amp;nbsp;promotion&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;p&gt;Homelabbers who want a single provider for both personal projects and light business hosting, with the safety net of human phone&amp;nbsp;support.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Quick Comparison&amp;nbsp;Table&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;Best Deal&lt;/th&gt;
&lt;th&gt;Traffic&lt;/th&gt;
&lt;th&gt;Network&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;API&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Support&lt;/th&gt;
&lt;th&gt;Score&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hetzner&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;CAX11&lt;/span&gt; &lt;span class="caps"&gt;ARM&lt;/span&gt; €3.29&lt;/td&gt;
&lt;td&gt;20 &lt;span class="caps"&gt;TB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Excellent&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Forum&lt;/td&gt;
&lt;td&gt;9.5/10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Netcup&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt; 200 G10s €3.69&lt;/td&gt;
&lt;td&gt;40 &lt;span class="caps"&gt;TB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Ticket&lt;/td&gt;
&lt;td&gt;8.5/10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OVHcloud&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt; Starter €3.50&lt;/td&gt;
&lt;td&gt;Unmetered&lt;/td&gt;
&lt;td&gt;Variable&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Mixed&lt;/td&gt;
&lt;td&gt;8.0/10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Contabo&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cloud &lt;span class="caps"&gt;VPS&lt;/span&gt; S €5.99&lt;/td&gt;
&lt;td&gt;32 &lt;span class="caps"&gt;TB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Fair&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Slow&lt;/td&gt;
&lt;td&gt;7.5/10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ionos&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt; Linux S €5.00&lt;/td&gt;
&lt;td&gt;Unmetered&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Phone&lt;/td&gt;
&lt;td&gt;7.0/10&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Use &lt;span class="caps"&gt;ARM&lt;/span&gt; Instances Where&amp;nbsp;Possible&lt;/h3&gt;
&lt;p&gt;Hetzner&amp;#8217;s &lt;span class="caps"&gt;CAX11&lt;/span&gt; (&lt;span class="caps"&gt;ARM&lt;/span&gt; Ampere Altra) is €3.29 for 2 vCPU / 4 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;. Most self-hosted apps (Docker, Nextcloud, Pi-hole, WireGuard) have &lt;span class="caps"&gt;ARM64&lt;/span&gt; images. You save money and get better power&amp;nbsp;efficiency.&lt;/p&gt;
&lt;h3&gt;Tip 2: Combine &lt;span class="caps"&gt;VPS&lt;/span&gt; with Local&amp;nbsp;Homelab&lt;/h3&gt;
&lt;p&gt;Use the &lt;span class="caps"&gt;VPS&lt;/span&gt; as a &lt;strong&gt;public edge node&lt;/strong&gt; and keep heavy storage/&lt;span class="caps"&gt;CPU&lt;/span&gt; workloads local:
- &lt;span class="caps"&gt;VPS&lt;/span&gt;: WireGuard hub + reverse proxy + public &lt;span class="caps"&gt;DNS&lt;/span&gt;
- Homelab: Jellyfin transcode + &lt;span class="caps"&gt;ZFS&lt;/span&gt; &lt;span class="caps"&gt;NAS&lt;/span&gt; + Proxmox&amp;nbsp;cluster&lt;/p&gt;
&lt;h3&gt;Tip 3: Watch for Black Friday&amp;nbsp;Deals&lt;/h3&gt;
&lt;p&gt;Netcup and Contabo run aggressive seasonal promotions. Hetzner rarely discounts but occasionally waives setup fees. Set calendar reminders for&amp;nbsp;November.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;For most homelab users, &lt;strong&gt;Hetzner&lt;/strong&gt; offers the best balance of price, performance, and automation. If you need massive traffic quotas, &lt;strong&gt;Netcup&lt;/strong&gt; is the runner-up. For DDoS-protected public services, consider &lt;strong&gt;OVHcloud&lt;/strong&gt;. &lt;strong&gt;Contabo&lt;/strong&gt; wins on raw specs if you can tolerate shared &lt;span class="caps"&gt;CPU&lt;/span&gt;, and &lt;strong&gt;Ionos&lt;/strong&gt; is the safe, supported&amp;nbsp;choice.&lt;/p&gt;
&lt;h3&gt;Our&amp;nbsp;Recommendation&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Budget homelab (1–3 containers):&lt;/strong&gt; Hetzner &lt;span class="caps"&gt;CAX11&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Backup target / high traffic:&lt;/strong&gt; Netcup &lt;span class="caps"&gt;VPS&lt;/span&gt; 500&amp;nbsp;G10s&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Public-facing game server / website:&lt;/strong&gt; OVHcloud &lt;span class="caps"&gt;VPS&lt;/span&gt;&amp;nbsp;Value&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Nextcloud with 500 &lt;span class="caps"&gt;GB&lt;/span&gt;+ storage:&lt;/strong&gt; Contabo Cloud &lt;span class="caps"&gt;VPS&lt;/span&gt;&amp;nbsp;S&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Business + homelab hybrid:&lt;/strong&gt; Ionos &lt;span class="caps"&gt;VPS&lt;/span&gt; Linux&amp;nbsp;M&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Hetzner referral:&lt;/strong&gt; Some affiliate programs exist for cloud&amp;nbsp;credits&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Contabo:&lt;/strong&gt; Occasional referral promotions via partner&amp;nbsp;networks&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hardware cross-sell:&lt;/strong&gt; Mini PCs for local homelab paired with &lt;span class="caps"&gt;VPS&lt;/span&gt; for public&amp;nbsp;edge&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;why-vps&lt;/code&gt; → &lt;code&gt;/vps-vs-homelab-server&lt;/code&gt; for the architecture&amp;nbsp;decision&lt;/li&gt;
&lt;li&gt;&lt;code&gt;vpn&lt;/code&gt; → &lt;code&gt;/wireguard-vps-homelab-guide&lt;/code&gt; for tunnel&amp;nbsp;setup&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;/docker-compose-for-beginners&lt;/code&gt; for app deployment on the &lt;span class="caps"&gt;VPS&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Which European &lt;span class="caps"&gt;VPS&lt;/span&gt; powers your homelab?&lt;/strong&gt; Share your provider and monthly bill in the&amp;nbsp;comments!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Subscribe to the WordForge newsletter&lt;/strong&gt; for seasonal deal alerts and provider benchmarking&amp;nbsp;updates.&lt;/p&gt;
&lt;/blockquote&gt;</content><category term="Guides"/><category term="homelab"/><category term="vps"/><category term="europe"/><category term="self-hosted"/><category term="hosting"/><category term="hetzner"/><category term="ovh"/><category term="netcup"/></entry><entry><title>Docker Compose for Beginners: A Step-by-Step Homelab Guide 2026</title><link href="https://steadypub.com/2026/06/docker-compose-for-beginners/" rel="alternate"/><published>2026-06-05T00:33:00+07:00</published><updated>2026-06-05T00:33:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/docker-compose-for-beginners/</id><summary type="html">&lt;p&gt;Learn Docker Compose from scratch. Install Docker, write your first docker-compose.yml, and deploy a real multi-container stack with persistent storage and reverse proxy in under 30&amp;nbsp;minutes.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~15 minutes&lt;br&gt;
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab beginners who have installed Linux or Proxmox&lt;br&gt;
&lt;strong&gt;Prerequisites:&lt;/strong&gt; A Linux &lt;span class="caps"&gt;VM&lt;/span&gt; or &lt;span class="caps"&gt;LXC&lt;/span&gt; with root/sudo&amp;nbsp;access&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is Docker&amp;nbsp;Compose?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Docker Compose is a tool that lets you define and run &lt;strong&gt;multi-container applications&lt;/strong&gt; using a single &lt;span class="caps"&gt;YAML&lt;/span&gt; file&amp;nbsp;(&lt;code&gt;docker-compose.yml&lt;/code&gt;). Instead of running&amp;nbsp;long &lt;code&gt;docker run&lt;/code&gt; commands with dozens of flags, you declare your entire stack — services, networks, volumes, and environment variables — in one readable&amp;nbsp;file.&lt;/p&gt;
&lt;p&gt;For homelab users, Compose is the standard way to deploy self-hosted apps like Nextcloud, Immich, Jellyfin, Pi-hole, and Portainer. A typical homelab runs 10–30 containers orchestrated through Compose&amp;nbsp;files.&lt;/p&gt;
&lt;h3&gt;Key&amp;nbsp;Benefits&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Benefit&lt;/th&gt;
&lt;th&gt;Explanation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Declarative&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Define once, deploy repeatedly across machines&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Version controlled&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Your &lt;code&gt;docker-compose.yml&lt;/code&gt; is infrastructure-as-code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Isolated networks&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Services talk to each other without exposing ports to the host&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Persistent volumes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Data survives container deletion and updates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;One-command updates&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;docker compose pull &amp;amp;&amp;amp; docker compose up -d&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;h3&gt;Hardware&amp;nbsp;Requirements&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Setup&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Storage&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Minimal (5–10 containers)&lt;/td&gt;
&lt;td&gt;2 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;20 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Intel N100, Raspberry Pi 5, or old laptop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Comfortable (15–30 containers)&lt;/td&gt;
&lt;td&gt;4–8 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;64 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Recommended for most homelabs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Heavy (30+ with databases)&lt;/td&gt;
&lt;td&gt;16 &lt;span class="caps"&gt;GB&lt;/span&gt;+&lt;/td&gt;
&lt;td&gt;256 &lt;span class="caps"&gt;GB&lt;/span&gt; NVMe&lt;/td&gt;
&lt;td&gt;Include swap or &lt;span class="caps"&gt;ZFS&lt;/span&gt; compression&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Software&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Docker Engine 24.0+ and Docker Compose plugin&amp;nbsp;v2.20+&lt;/li&gt;
&lt;li&gt;A Linux distribution: Ubuntu 22.04/24.04 &lt;span class="caps"&gt;LTS&lt;/span&gt;, Debian 12, or Proxmox &lt;span class="caps"&gt;LXC&lt;/span&gt; (privileged or with nesting&amp;nbsp;enabled)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Knowledge&amp;nbsp;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Basic Linux command line (&lt;span class="caps"&gt;SSH&lt;/span&gt;, &lt;code&gt;cd&lt;/code&gt;, &lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;nano&lt;/code&gt; or &lt;code&gt;vim&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Understanding of &lt;span class="caps"&gt;YAML&lt;/span&gt; indentation (spaces, not&amp;nbsp;tabs)&lt;/li&gt;
&lt;li&gt;A static &lt;span class="caps"&gt;IP&lt;/span&gt; or local &lt;span class="caps"&gt;DNS&lt;/span&gt; name for your&amp;nbsp;server&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Install Docker and Docker&amp;nbsp;Compose&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Install the official Docker Engine and Compose&amp;nbsp;plugin.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Update your&amp;nbsp;system:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;upgrade&lt;span class="w"&gt; &lt;/span&gt;-y
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Install required&amp;nbsp;dependencies:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;ca-certificates&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;gnupg&lt;span class="w"&gt; &lt;/span&gt;lsb-release&lt;span class="w"&gt; &lt;/span&gt;-y
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Add Docker&amp;#8217;s official &lt;span class="caps"&gt;GPG&lt;/span&gt; key and&amp;nbsp;repository:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0755&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;/etc/apt/keyrings
curl&lt;span class="w"&gt; &lt;/span&gt;-fsSL&lt;span class="w"&gt; &lt;/span&gt;https://download.docker.com/linux/ubuntu/gpg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;gpg&lt;span class="w"&gt; &lt;/span&gt;--dearmor&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;/etc/apt/keyrings/docker.gpg

&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;deb [arch=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;dpkg&lt;span class="w"&gt; &lt;/span&gt;--print-architecture&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; signed-by=/etc/apt/keyrings/docker.gpg] \&lt;/span&gt;
&lt;span class="s2"&gt;  https://download.docker.com/linux/ubuntu \&lt;/span&gt;
&lt;span class="s2"&gt;  &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;lsb_release&lt;span class="w"&gt; &lt;/span&gt;-cs&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; stable&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;tee&lt;span class="w"&gt; &lt;/span&gt;/etc/apt/sources.list.d/docker.list&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/dev/null
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Install Docker Engine and&amp;nbsp;Compose:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;update
sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;docker-ce&lt;span class="w"&gt; &lt;/span&gt;docker-ce-cli&lt;span class="w"&gt; &lt;/span&gt;containerd.io&lt;span class="w"&gt; &lt;/span&gt;docker-buildx-plugin&lt;span class="w"&gt; &lt;/span&gt;docker-compose-plugin&lt;span class="w"&gt; &lt;/span&gt;-y
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Add your user to&amp;nbsp;the &lt;code&gt;docker&lt;/code&gt; group (log out and back in&amp;nbsp;after):&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;usermod&lt;span class="w"&gt; &lt;/span&gt;-aG&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$USER&lt;/span&gt;
newgrp&lt;span class="w"&gt; &lt;/span&gt;docker
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Verify:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;--version
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;version
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Expected&amp;nbsp;output:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Docker version 26.x.x
Docker Compose version v2.29.x
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 2: Write Your First&amp;nbsp;docker-compose.yml&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Create a Compose file that runs &lt;span class="caps"&gt;NGINX&lt;/span&gt; and a simple whoami&amp;nbsp;service.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Create a project&amp;nbsp;directory:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;~/compose-demo&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/compose-demo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Create &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;nginx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nginx:alpine&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nginx-demo&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8080:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./html:/usr/share/nginx/html:ro&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;whoami&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;traefik/whoami&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;whoami-demo&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Create a simple &lt;span class="caps"&gt;HTML&lt;/span&gt;&amp;nbsp;file:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;html
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;lt;h1&amp;gt;Hello from Docker Compose!&amp;lt;/h1&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;html/index.html
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Start the&amp;nbsp;stack:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Test:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;curl&lt;span class="w"&gt; &lt;/span&gt;http://localhost:8080
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You should see &amp;#8220;Hello from Docker&amp;nbsp;Compose!&amp;#8221;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;View running&amp;nbsp;containers:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;ps
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;logs&lt;span class="w"&gt; &lt;/span&gt;-f
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 3: Deploy a Real Homelab Stack (&lt;span class="caps"&gt;NGINX&lt;/span&gt; Proxy Manager + Uptime&amp;nbsp;Kuma)&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Deploy a practical two-app stack with persistent volumes and a custom bridge&amp;nbsp;network.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Create a new&amp;nbsp;directory:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;~/homelab-stack&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/homelab-stack
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Create &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;nginx-proxy-manager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;jc21/nginx-proxy-manager:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nginx-proxy-manager&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;80:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;81:81&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;443:443&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;npm-data:/data&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;npm-letsencrypt:/etc/letsencrypt&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;uptime-kuma&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;louislam/uptime-kuma:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;uptime-kuma&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;uptime-data:/app/data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Access via NPM reverse proxy on port 3001&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;npm-data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;npm-letsencrypt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;uptime-data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Launch:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Access &lt;span class="caps"&gt;NGINX&lt;/span&gt; Proxy Manager&amp;nbsp;at &lt;code&gt;http://your-server-ip:81&lt;/code&gt;. Default&amp;nbsp;login:&lt;/li&gt;
&lt;li&gt;Email: &lt;code&gt;admin@example.com&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Password: &lt;code&gt;changeme&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Access Uptime Kuma&amp;nbsp;at &lt;code&gt;http://your-server-ip:3001&lt;/code&gt;. Set it up to monitor your homelab&amp;nbsp;services.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pro Tip:&lt;/strong&gt; Use &lt;span class="caps"&gt;NGINX&lt;/span&gt; Proxy Manager to give each app a local subdomain&amp;nbsp;(e.g., &lt;code&gt;npm.lan&lt;/code&gt;, &lt;code&gt;kuma.lan&lt;/code&gt;) instead of remembering port&amp;nbsp;numbers.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;Step 4: Understanding Networks and Persistent&amp;nbsp;Storage&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Learn how Compose handles inter-container communication and data&amp;nbsp;persistence.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Default Bridge Network:&lt;/strong&gt;
By default, Compose creates a private network. Services can reach each other by their service name as a&amp;nbsp;hostname:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;mariadb:11&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;secret&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;MYSQL_HOST&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;db&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Resolves to the MariaDB container&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Named Volumes vs Bind&amp;nbsp;Mounts:&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Syntax&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Named volume&lt;/td&gt;
&lt;td&gt;&lt;code&gt;volumes: app-data:/var/lib/mysql&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Databases, app state&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bind mount&lt;/td&gt;
&lt;td&gt;&lt;code&gt;./config:/config&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Config files you edit by hand&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tmpfs&lt;/td&gt;
&lt;td&gt;&lt;code&gt;type: tmpfs, target: /cache&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Ephemeral cache&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Example with&amp;nbsp;both:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;immich&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ghcr.io/immich-app/immich-server:release&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;immich-upload:/usr/src/app/upload&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="c1"&gt;# Named volume&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/etc/localtime:/etc/localtime:ro&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c1"&gt;# Bind mount&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 5: Updating and Maintaining&amp;nbsp;Containers&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Safely update images without losing&amp;nbsp;data.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Navigate to your stack&amp;nbsp;directory:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/homelab-stack
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Pull new&amp;nbsp;images:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;pull
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Recreate containers with new&amp;nbsp;images:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Compose only restarts containers whose images changed. Named volumes are preserved&amp;nbsp;automatically.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Clean up old images to save disk&amp;nbsp;space:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;image&lt;span class="w"&gt; &lt;/span&gt;prune&lt;span class="w"&gt; &lt;/span&gt;-f
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;For a full system cleanup (unused volumes, networks,&amp;nbsp;images):&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;system&lt;span class="w"&gt; &lt;/span&gt;prune&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;--volumes
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt; This deletes unused named volumes. Ensure your data is backed&amp;nbsp;up.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1:&amp;nbsp;Use &lt;code&gt;.env&lt;/code&gt; Files for&amp;nbsp;Secrets&lt;/h3&gt;
&lt;p&gt;Never commit passwords to Git.&amp;nbsp;Create &lt;code&gt;.env&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;DB_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;supersecret
&lt;span class="nv"&gt;DOMAIN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;homelab.local
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Reference it&amp;nbsp;in &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;${DB_PASSWORD}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 2: Enable Docker Auto-Start on&amp;nbsp;Boot&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;docker
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Your containers will start automatically after a power outage if they&amp;nbsp;use &lt;code&gt;restart: unless-stopped&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Tip 3: Monitor Disk&amp;nbsp;Usage&lt;/h3&gt;
&lt;p&gt;Docker can consume GBs of log files. Limit log size per&amp;nbsp;container:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;json-file&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;max-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;10m&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;max-file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 4:&amp;nbsp;Use &lt;code&gt;docker compose -f&lt;/code&gt; for Multiple&amp;nbsp;Files&lt;/h3&gt;
&lt;p&gt;Split your homelab into logical&amp;nbsp;files:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;docker-compose.yml&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;docker-compose.prod.yml&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Troubleshooting Common&amp;nbsp;Issues&lt;/h2&gt;
&lt;h3&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;Permission Denied&amp;#8221; on Bind&amp;nbsp;Mounts&lt;/h3&gt;
&lt;p&gt;Docker runs as root by default. Either:
- Set folder ownership to your user &lt;span class="caps"&gt;UID&lt;/span&gt;/&lt;span class="caps"&gt;GID&lt;/span&gt;
- Or use named volumes instead of bind&amp;nbsp;mounts&lt;/p&gt;
&lt;h3&gt;Ports Already in&amp;nbsp;Use&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;lsof&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;:80
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Find the conflicting service and change the host port mapping (left&amp;nbsp;side):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8080:80&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Host 8080 → Container 80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Container Exits&amp;nbsp;Immediately&lt;/h3&gt;
&lt;p&gt;Check&amp;nbsp;logs:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;logs&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;service-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Common causes: missing environment variables, wrong architecture (&lt;span class="caps"&gt;ARM64&lt;/span&gt; vs &lt;span class="caps"&gt;AMD64&lt;/span&gt;), or port&amp;nbsp;conflicts.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Docker Compose turns complex multi-app deployments into readable, version-controlled &lt;span class="caps"&gt;YAML&lt;/span&gt; files. In this guide, you installed Docker, wrote your first Compose file, deployed a real reverse-proxy stack, and learned how networks and volumes&amp;nbsp;work.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/nextcloud-docker-compose"&gt;Deploy Nextcloud with Docker&amp;nbsp;Compose&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/portainer-setup-guide"&gt;Set up Portainer for visual container&amp;nbsp;management&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/self-hosted-media-server-setup"&gt;Build a self-hosted media server with&amp;nbsp;Jellyfin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/docker-compose-vs-podman"&gt;Compare Docker Compose vs&amp;nbsp;Podman&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mini PCs:&lt;/strong&gt; Intel N100 or N305 systems for low-power Docker&amp;nbsp;hosts&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;SSD&lt;/span&gt; Storage:&lt;/strong&gt; Reliable &lt;span class="caps"&gt;SATA&lt;/span&gt;/NVMe drives for container&amp;nbsp;volumes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;UPS&lt;/span&gt;:&lt;/strong&gt; &lt;span class="caps"&gt;APC&lt;/span&gt; Back-&lt;span class="caps"&gt;UPS&lt;/span&gt; for keeping your Docker host alive during&amp;nbsp;outages&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;prerequisites&lt;/code&gt; → &lt;code&gt;/proxmox-beginner-guide&lt;/code&gt; for readers needing a &lt;span class="caps"&gt;VM&lt;/span&gt;&amp;nbsp;host&lt;/li&gt;
&lt;li&gt;&lt;code&gt;real-stack&lt;/code&gt; → &lt;code&gt;/portainer-setup-guide&lt;/code&gt; for &lt;span class="caps"&gt;GUI&lt;/span&gt; management of Compose&amp;nbsp;stacks&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;/nextcloud-docker-compose&lt;/code&gt; as the next practical&amp;nbsp;project&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What are you self-hosting with Docker Compose?&lt;/strong&gt; Share your favorite stack in the&amp;nbsp;comments!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Subscribe to the WordForge newsletter&lt;/strong&gt; for weekly Docker and homelab&amp;nbsp;tutorials.&lt;/p&gt;
&lt;/blockquote&gt;</content><category term="Tutorials"/><category term="homelab"/><category term="self-hosted"/><category term="beginners"/><category term="docker"/><category term="docker compose"/><category term="containers"/></entry><entry><title>Pi-hole Docker Setup 2026: Network-Wide Ad Blocking for Homelabs</title><link href="https://steadypub.com/2026/06/homelab-ad-blocking-pihole/" rel="alternate"/><published>2026-06-05T00:33:00+07:00</published><updated>2026-06-05T00:33:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/homelab-ad-blocking-pihole/</id><summary type="html">&lt;p&gt;Deploy Pi-hole on Docker to block ads and trackers across your entire home network. Step-by-step guide with &lt;span class="caps"&gt;DHCP&lt;/span&gt; options, custom blocklists, and failover&amp;nbsp;configuration.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~12 minutes&lt;br&gt;
&lt;strong&gt;Audience:&lt;/strong&gt; Beginners who want cleaner browsing and reduced tracking on all home devices&lt;br&gt;
&lt;strong&gt;Last tested:&lt;/strong&gt; Pi-hole &lt;span class="caps"&gt;FTL&lt;/span&gt; v6.0, June&amp;nbsp;2026&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is&amp;nbsp;Pi-hole?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Pi-hole is a &lt;span class="caps"&gt;DNS&lt;/span&gt; sinkhole that blocks advertisements, trackers, and malicious domains at the network level. Instead of installing ad blockers on every browser and device, Pi-hole filters &lt;span class="caps"&gt;DNS&lt;/span&gt; requests for your entire household. Smart TVs, mobile apps, IoT devices, and game consoles all benefit without individual&amp;nbsp;configuration.&lt;/p&gt;
&lt;p&gt;Think of it as a &amp;#8220;network-wide ad blocker&amp;#8221; that runs on a small Linux container and consumes less than 512 &lt;span class="caps"&gt;MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;Key&amp;nbsp;Benefits&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Benefit&lt;/th&gt;
&lt;th&gt;Impact&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Network-wide blocking&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;One setup protects every device on your &lt;span class="caps"&gt;LAN&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Faster page loads&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Ads never download, saving bandwidth&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Privacy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Blocks trackers that follow you across websites&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Malware protection&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Known malicious domains are blocked before connection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Parental controls&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Block adult content or social media via blocklists&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Low resource&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Runs on a Raspberry Pi Zero 2 W or Docker container&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;h3&gt;Hardware&amp;nbsp;Requirements&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Setup&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Storage&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Minimal (1–2 users)&lt;/td&gt;
&lt;td&gt;512 &lt;span class="caps"&gt;MB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1 core&lt;/td&gt;
&lt;td&gt;4 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Raspberry Pi Zero 2 W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Standard (5–10 devices)&lt;/td&gt;
&lt;td&gt;512 &lt;span class="caps"&gt;MB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1 core&lt;/td&gt;
&lt;td&gt;8 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Docker on any Linux host&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Heavy (50+ devices, large lists)&lt;/td&gt;
&lt;td&gt;1 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;2 cores&lt;/td&gt;
&lt;td&gt;16 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Intel N100, old laptop&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Software&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Docker Engine and Docker Compose&amp;nbsp;plugin&lt;/li&gt;
&lt;li&gt;Access to your router&amp;#8217;s admin panel (to change &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;settings)&lt;/li&gt;
&lt;li&gt;A Linux host with a static local &lt;span class="caps"&gt;IP&lt;/span&gt;&amp;nbsp;(e.g., &lt;code&gt;192.168.1.10&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Network&amp;nbsp;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Your Pi-hole host needs a &lt;strong&gt;static &lt;span class="caps"&gt;IP&lt;/span&gt; address&lt;/strong&gt;. If your router uses &lt;span class="caps"&gt;DHCP&lt;/span&gt;, reserve the &lt;span class="caps"&gt;IP&lt;/span&gt; by &lt;span class="caps"&gt;MAC&lt;/span&gt;&amp;nbsp;address.&lt;/li&gt;
&lt;li&gt;Port 53 (&lt;span class="caps"&gt;DNS&lt;/span&gt;) must not be in use by another service on the&amp;nbsp;host.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Deploy Pi-hole with Docker&amp;nbsp;Compose&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Create a Compose file with persistent storage and the correct network&amp;nbsp;mode.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Create a project&amp;nbsp;directory:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;~/pihole&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/pihole
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Create &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;pihole&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pihole&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pihole/pihole:2025.07.0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Pin version for stability&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;53:53/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;53:53/udp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8080:80/tcp&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Admin UI; change if 80 is taken&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TZ=Europe/Berlin&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Change to your timezone&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;WEBPASSWORD=changeme&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Strong password for admin UI&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;FTLCONF_LOCAL_IPV4=192.168.1.10&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Your host&amp;#39;s static IP&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./etc-pihole:/etc/pihole&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./etc-dnsmasq.d:/etc/dnsmasq.d&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;cap_add&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;NET_ADMIN&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;dns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;127.0.0.1&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1.1.1.1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Port 80 conflict:&lt;/strong&gt; If your host already runs a web server on port 80, map Pi-hole to a different host port&amp;nbsp;(e.g., &lt;code&gt;8081:80&lt;/code&gt;).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Create data&amp;nbsp;directories:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;etc-pihole&lt;span class="w"&gt; &lt;/span&gt;etc-dnsmasq.d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Start&amp;nbsp;Pi-hole:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Verify it is&amp;nbsp;running:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;logs&lt;span class="w"&gt; &lt;/span&gt;-f
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Look for &amp;#8220;Blocking &amp;#8230; domains&amp;#8221; and &amp;#8220;&lt;span class="caps"&gt;FTL&lt;/span&gt;&amp;nbsp;started&amp;#8221;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 2: Point Your Router to&amp;nbsp;Pi-hole&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Redirect all &lt;span class="caps"&gt;DNS&lt;/span&gt; traffic on your network through&amp;nbsp;Pi-hole.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Option A: Router &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;(Recommended)&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Log in to your router&amp;#8217;s admin panel&amp;nbsp;(usually &lt;code&gt;192.168.1.1&lt;/code&gt; or &lt;code&gt;192.168.0.1&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Find the &lt;strong&gt;&lt;span class="caps"&gt;DHCP&lt;/span&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;span class="caps"&gt;LAN&lt;/span&gt;&lt;/strong&gt;&amp;nbsp;settings.&lt;/li&gt;
&lt;li&gt;Set the &lt;strong&gt;Primary &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/strong&gt; to your Pi-hole &lt;span class="caps"&gt;IP&lt;/span&gt;&amp;nbsp;(e.g., &lt;code&gt;192.168.1.10&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Set the &lt;strong&gt;Secondary &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/strong&gt; to a public resolver&amp;nbsp;like &lt;code&gt;1.1.1.1&lt;/code&gt; or leave blank (Pi-hole handles&amp;nbsp;upstream).&lt;/li&gt;
&lt;li&gt;Save and reboot the router or renew &lt;span class="caps"&gt;DHCP&lt;/span&gt; leases on&amp;nbsp;clients.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; If Pi-hole goes down and you set no secondary &lt;span class="caps"&gt;DNS&lt;/span&gt;, devices lose internet access. For redundancy, run a second Pi-hole or use a public &lt;span class="caps"&gt;DNS&lt;/span&gt; as secondary (ads will leak through the secondary, but internet stays&amp;nbsp;up).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Option B: Per-Device &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you cannot change router settings (&lt;span class="caps"&gt;ISP&lt;/span&gt;-locked devices), manually set &lt;span class="caps"&gt;DNS&lt;/span&gt; on each device:
- &lt;strong&gt;Windows:&lt;/strong&gt; Network settings → Adapter properties → IPv4 → Preferred &lt;span class="caps"&gt;DNS&lt;/span&gt;: &lt;code&gt;192.168.1.10&lt;/code&gt;
- &lt;strong&gt;macOS:&lt;/strong&gt; System Settings → Network → &lt;span class="caps"&gt;DNS&lt;/span&gt; →&amp;nbsp;Add &lt;code&gt;192.168.1.10&lt;/code&gt;
- &lt;strong&gt;Android/iOS:&lt;/strong&gt; Wi-Fi settings → Advanced → &lt;span class="caps"&gt;DNS&lt;/span&gt; →&amp;nbsp;Add &lt;code&gt;192.168.1.10&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 3: Configure Blocklists and&amp;nbsp;Whitelists&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Add aggressive blocklists and fix any broken&amp;nbsp;websites.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Open the Pi-hole admin&amp;nbsp;dashboard:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;http://your-server-ip:8080/admin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Log in with&amp;nbsp;the &lt;code&gt;WEBPASSWORD&lt;/code&gt; you&amp;nbsp;set.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Navigate to &lt;strong&gt;Group Management → Adlists&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add curated blocklists. Start with these reliable&amp;nbsp;sources:&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;List Name&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;URL&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Est. Domains&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;StevenBlack&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;150,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;OISD&lt;/span&gt; Full&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://dbl.oisd.nl/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;900,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Firebog Tick lists&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://v.firebog.net/hosts/lists.php?type=tick&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;400,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AdGuard &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://v.firebog.net/hosts/AdguardDNS.txt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;50,000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Click &lt;strong&gt;Tools → Update Gravity&lt;/strong&gt; to download and compile the&amp;nbsp;lists.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;After updating, check the dashboard for &amp;#8220;Total queries&amp;#8221; and &amp;#8220;Queries&amp;nbsp;blocked&amp;#8221;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Whitelisting broken&amp;nbsp;sites:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Some sites break when critical trackers are blocked (e.g., login callbacks, captchas). If a site fails:
1. Open Pi-hole dashboard → &lt;strong&gt;Query Log&lt;/strong&gt;
2. Find the blocked domain (highlighted in red)
3. Click &lt;strong&gt;Whitelist&lt;/strong&gt; next to it
4. Common&amp;nbsp;whitelists: &lt;code&gt;client-s.gateway.messenger.live&lt;/code&gt;, &lt;code&gt;app-analytics-v2.snapchat.com&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 4: Monitoring and&amp;nbsp;Maintenance&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Understand your dashboard and keep Pi-hole&amp;nbsp;updated.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Dashboard&amp;nbsp;Overview:&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Total queries&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt; requests processed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Queries blocked&lt;/td&gt;
&lt;td&gt;Requests matching blocklists&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Percent blocked&lt;/td&gt;
&lt;td&gt;Efficiency ratio (typically 10–30%)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Domains on blocklist&lt;/td&gt;
&lt;td&gt;Size of your combined lists&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Top permitted domains&lt;/td&gt;
&lt;td&gt;Most requested allowed sites&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Top blocked domains&lt;/td&gt;
&lt;td&gt;Most frequent ads/trackers caught&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Updating&amp;nbsp;Pi-hole:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/pihole
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;pull
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Your blocklists, whitelist, and settings persist&amp;nbsp;in &lt;code&gt;./etc-pihole&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Updating Gravity&amp;nbsp;(blocklists):&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In the web &lt;span class="caps"&gt;UI&lt;/span&gt;: &lt;strong&gt;Tools → Update Gravity&lt;/strong&gt;. Schedule this weekly via cron or the &lt;span class="caps"&gt;UI&lt;/span&gt;&amp;#8217;s automatic update&amp;nbsp;option.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Run Pi-hole in Host Network Mode for&amp;nbsp;IPv6&lt;/h3&gt;
&lt;p&gt;If your network uses IPv6 extensively, host mode simplifies &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;listening:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;network_mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;host&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Remove&amp;nbsp;the &lt;code&gt;ports:&lt;/code&gt; block when using host&amp;nbsp;mode.&lt;/p&gt;
&lt;h3&gt;Tip 2: Use Local &lt;span class="caps"&gt;DNS&lt;/span&gt; Records for Homelab&amp;nbsp;Services&lt;/h3&gt;
&lt;p&gt;Map local domains to internal IPs so you can access services by name:
- &lt;strong&gt;Local &lt;span class="caps"&gt;DNS&lt;/span&gt; → &lt;span class="caps"&gt;DNS&lt;/span&gt; Records:&lt;/strong&gt;&amp;nbsp;- &lt;code&gt;proxmox.lan&lt;/code&gt; → &lt;code&gt;192.168.1.5&lt;/code&gt;
  - &lt;code&gt;nas.lan&lt;/code&gt; → &lt;code&gt;192.168.1.20&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This works across all devices without editing&amp;nbsp;individual &lt;code&gt;/etc/hosts&lt;/code&gt; files.&lt;/p&gt;
&lt;h3&gt;Tip 3: Conditional Forwarding for Reverse &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;If you run Active Directory or want hostname resolution for local IPs:
- &lt;strong&gt;Settings → &lt;span class="caps"&gt;DNS&lt;/span&gt; → Conditional Forwarding:&lt;/strong&gt;
  - Router &lt;span class="caps"&gt;IP&lt;/span&gt;: &lt;code&gt;192.168.1.1&lt;/code&gt;
  - Local domain&amp;nbsp;name: &lt;code&gt;lan&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;Tip 4: Teleporter&amp;nbsp;Backups&lt;/h3&gt;
&lt;p&gt;Pi-hole includes a built-in backup/restore tool:
- &lt;strong&gt;Settings → Teleporter&lt;/strong&gt;
- Export your entire config (lists, whitelist, local &lt;span class="caps"&gt;DNS&lt;/span&gt;, groups)
- Store&amp;nbsp;the &lt;code&gt;.tar.gz&lt;/code&gt; in your backup&amp;nbsp;system&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Troubleshooting Common&amp;nbsp;Issues&lt;/h2&gt;
&lt;h3&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;DNS_PROBE_FINISHED_BAD_CONFIG&amp;#8221; on&amp;nbsp;Clients&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Pi-hole is not reachable. Verify the container is&amp;nbsp;running: &lt;code&gt;docker compose ps&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Check firewall rules: port 53/udp and 53/tcp must be&amp;nbsp;open&lt;/li&gt;
&lt;li&gt;Ensure the Pi-hole host &lt;span class="caps"&gt;IP&lt;/span&gt; is correct in router &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;settings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;YouTube Ads Still&amp;nbsp;Appearing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;YouTube serves ads from the same domains as videos&amp;nbsp;(&lt;code&gt;googlevideo.com&lt;/code&gt;). &lt;span class="caps"&gt;DNS&lt;/span&gt; blocking cannot distinguish&amp;nbsp;them.&lt;/li&gt;
&lt;li&gt;For YouTube ads, use a browser extension (uBlock Origin) or a client-side solution like SmartTube on Android &lt;span class="caps"&gt;TV&lt;/span&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Dashboard Shows 0&amp;nbsp;Queries&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Your devices are not using Pi-hole as their &lt;span class="caps"&gt;DNS&lt;/span&gt;. Double-check router settings or per-device &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;configuration.&lt;/li&gt;
&lt;li&gt;Restart devices to renew &lt;span class="caps"&gt;DHCP&lt;/span&gt; leases with the new &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;server.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;You now have Pi-hole running in Docker, filtering ads and trackers for every device on your network. Your browsing is faster, your privacy is improved, and your IoT devices are no longer phoning home to tracking&amp;nbsp;domains.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/pihole-unbound-dns"&gt;Pair Pi-hole with Unbound for recursive &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;privacy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/adguard-home-docker"&gt;Compare Pi-hole vs AdGuard&amp;nbsp;Home&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/pihole-ha-redundancy"&gt;Add a secondary Pi-hole for &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;redundancy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/grafana-loki-logs"&gt;Monitor &lt;span class="caps"&gt;DNS&lt;/span&gt; statistics with&amp;nbsp;Grafana&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Raspberry Pi:&lt;/strong&gt; Pi 4 or Pi 5 kits for dedicated low-power &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mini PCs:&lt;/strong&gt; Intel N100 systems for Pi-hole + other Docker&amp;nbsp;stacks&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;UPS&lt;/span&gt;:&lt;/strong&gt; &lt;span class="caps"&gt;APC&lt;/span&gt; Back-&lt;span class="caps"&gt;UPS&lt;/span&gt; to keep &lt;span class="caps"&gt;DNS&lt;/span&gt; alive during short&amp;nbsp;outages&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;what-is&lt;/code&gt; → &lt;code&gt;/dns-filtering-homelab&lt;/code&gt; for readers exploring &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;strategies&lt;/li&gt;
&lt;li&gt;&lt;code&gt;router&lt;/code&gt; → &lt;code&gt;/homelab-networking-basics&lt;/code&gt; for network&amp;nbsp;fundamentals&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;/pihole-unbound-dns&lt;/code&gt; for the next logical&amp;nbsp;upgrade&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What percentage of your &lt;span class="caps"&gt;DNS&lt;/span&gt; queries is Pi-hole blocking?&lt;/strong&gt; Share your block rate and favorite blocklists in the&amp;nbsp;comments!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Subscribe to the WordForge newsletter&lt;/strong&gt; for weekly homelab privacy and networking&amp;nbsp;guides.&lt;/p&gt;
&lt;/blockquote&gt;</content><category term="Tutorials"/><category term="pihole"/><category term="docker"/><category term="ad blocking"/><category term="dns"/><category term="homelab"/><category term="self-hosted"/><category term="network"/></entry><entry><title>Immich Docker Compose Setup 2026: Self-Hosted Photo Backup for Homelabs</title><link href="https://steadypub.com/2026/06/immich-docker-compose-setup/" rel="alternate"/><published>2026-06-05T00:33:00+07:00</published><updated>2026-06-05T00:33:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/immich-docker-compose-setup/</id><summary type="html">&lt;p&gt;Deploy Immich as a Google Photos replacement using Docker Compose. Includes PostgreSQL, Redis, machine learning features, mobile auto-upload, and reverse proxy&amp;nbsp;configuration.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~15 minutes&lt;br&gt;
&lt;strong&gt;Audience:&lt;/strong&gt; Users leaving Google Photos due to storage limits or privacy concerns&lt;br&gt;
&lt;strong&gt;Last tested:&lt;/strong&gt; Immich v1.131, PostgreSQL 16, Redis 7.4, June&amp;nbsp;2026&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is&amp;nbsp;Immich?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Immich is an open-source, self-hosted photo and video backup solution designed as a direct alternative to Google Photos, iCloud, and Amazon Photos. It offers automatic mobile uploads, &lt;span class="caps"&gt;AI&lt;/span&gt;-powered face recognition, duplicate detection, map-based browsing, and shared albums — all running on your own&amp;nbsp;server.&lt;/p&gt;
&lt;p&gt;Unlike Nextcloud&amp;#8217;s basic photo viewer, Immich is purpose-built for large media libraries (100,000+ photos) with fast scrolling, instant search, and &lt;span class="caps"&gt;RAW&lt;/span&gt; file&amp;nbsp;support.&lt;/p&gt;
&lt;h3&gt;Key&amp;nbsp;Benefits&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Immich&lt;/th&gt;
&lt;th&gt;Google Photos&lt;/th&gt;
&lt;th&gt;Nextcloud Photos&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cost&lt;/td&gt;
&lt;td&gt;Free (your hardware)&lt;/td&gt;
&lt;td&gt;$2–20/month&lt;/td&gt;
&lt;td&gt;Free (your hardware)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;AI&lt;/span&gt; face recognition&lt;/td&gt;
&lt;td&gt;✅ On-device or server&lt;/td&gt;
&lt;td&gt;✅ Cloud&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Auto-upload mobile&lt;/td&gt;
&lt;td&gt;✅ iOS &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; Android&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RAW&lt;/span&gt; / &lt;span class="caps"&gt;HEIC&lt;/span&gt; support&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Basic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Map timeline&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Duplicate detection&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Facial recognition privacy&lt;/td&gt;
&lt;td&gt;Local only&lt;/td&gt;
&lt;td&gt;Cloud processed&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;h3&gt;Hardware&amp;nbsp;Requirements&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Library Size&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Storage&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;GPU&lt;/span&gt; (Optional)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&amp;lt; 10,000 photos&lt;/td&gt;
&lt;td&gt;4 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;2 cores&lt;/td&gt;
&lt;td&gt;100 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Not needed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10,000–50,000&lt;/td&gt;
&lt;td&gt;8 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;4 cores&lt;/td&gt;
&lt;td&gt;500 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Intel &lt;span class="caps"&gt;UHD&lt;/span&gt; / &lt;span class="caps"&gt;NVIDIA&lt;/span&gt; for &lt;span class="caps"&gt;AI&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;50,000–200,000&lt;/td&gt;
&lt;td&gt;16 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;6 cores&lt;/td&gt;
&lt;td&gt;2 &lt;span class="caps"&gt;TB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Recommended&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;200,000+&lt;/td&gt;
&lt;td&gt;32 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;8+ cores&lt;/td&gt;
&lt;td&gt;4 &lt;span class="caps"&gt;TB&lt;/span&gt; NVMe&lt;/td&gt;
&lt;td&gt;Strongly recommended&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt; is the critical bottleneck.&lt;/strong&gt; PostgreSQL with pgvecto.rs (Immich&amp;#8217;s vector search extension) consumes significant memory during initial face recognition&amp;nbsp;scans.&lt;/p&gt;
&lt;h3&gt;Software&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Docker Engine 24.0+ and Docker Compose&amp;nbsp;plugin&lt;/li&gt;
&lt;li&gt;A Linux host with a static &lt;span class="caps"&gt;IP&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;(Optional) Reverse proxy for &lt;span class="caps"&gt;HTTPS&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Mobile device with the Immich app (iOS or&amp;nbsp;Android)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Create the Docker Compose&amp;nbsp;Stack&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Write a production-ready Compose file with all required Immich&amp;nbsp;services.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Create a project&amp;nbsp;directory:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;~/immich&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/immich
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Create &lt;code&gt;.env&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;cat&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;.env&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;&amp;lt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;EOF&amp;#39;&lt;/span&gt;
&lt;span class="c1"&gt;# Database&lt;/span&gt;
&lt;span class="nv"&gt;DB_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;change...hmod&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;600&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;.env
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Create &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;immich-server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;immich_server&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ghcr.io/immich-app/immich-server:release&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;2283:2283&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;${UPLOAD_LOCATION}:/usr/src/app/upload&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/etc/localtime:/etc/localtime:ro&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;env_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;.env&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;database&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;typesense&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;healthcheck&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;CMD&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;curl&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-f&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://localhost:2283/api/server/ping&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;30s&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;10s&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;retries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;3&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;immich-machine-learning&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;immich_machine_learning&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ghcr.io/immich-app/immich-machine-learning:release&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;model-cache:/cache&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;env_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;.env&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Uncomment for NVIDIA GPU acceleration:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# deploy:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#   resources:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#     reservations:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#       devices:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#         - driver: nvidia&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#           count: 1&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#           capabilities: [gpu]&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;typesense&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;immich_typesense&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;typesense/typesense:0.25.2&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TYPESENSE_API_KEY=${TYPESENSE_API_KEY}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TYPESENSE_DATA_DIR=/data&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;GLOG_minloglevel=1&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ts-data:/data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--data-dir&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;/data&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;--api-key&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;${TYPESENSE_API_KEY}&amp;quot;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;immich_redis&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis:7.4-alpine&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;database&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;immich_postgres&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;tensorchord/pgvecto-rs:pg16-v0.2.0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;${DB_PASSWORD}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;${DB_USERNAME}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;${DB_DATABASE_NAME}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;PGDATA&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/var/lib/postgresql/data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pgdata:/var/lib/postgresql/data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;healthcheck&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pg_isready -U ${DB_USERNAME} -d ${DB_DATABASE_NAME} || exit 1&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;10s&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;5s&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;retries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;5&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;start_period&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;30s&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;pgdata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;model-cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;ts-data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Start the&amp;nbsp;stack:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Verify all containers are&amp;nbsp;healthy:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;ps
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 2: Initial&amp;nbsp;Configuration&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Complete the web setup and create your admin&amp;nbsp;account.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Open your&amp;nbsp;browser:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;http://your-server-ip:2283
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Click &lt;strong&gt;&amp;#8220;Getting Started&amp;#8221;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Create the administrator&amp;nbsp;account:&lt;/li&gt;
&lt;li&gt;Email, password,&amp;nbsp;name&lt;/li&gt;
&lt;li&gt;Log in and explore the web &lt;span class="caps"&gt;UI&lt;/span&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Key settings to configure&amp;nbsp;first:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Administration → Settings → Storage Template:&lt;/strong&gt;
  Define how uploaded files are organized. Default&amp;nbsp;is &lt;code&gt;YYYY/MM/YYYY-MM-DD/filename&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Administration → Settings → External Libraries (Optional):&lt;/strong&gt;
  If you have an existing photo collection on disk, mount it read-only and add it as an external library. Immich will index it without moving&amp;nbsp;files.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Administration → Settings → Machine Learning:&lt;/strong&gt;
  Enable &lt;strong&gt;Face Recognition&lt;/strong&gt;, &lt;strong&gt;Smart Search&lt;/strong&gt;, and &lt;strong&gt;Duplicate Detection&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Step 3: Mobile Auto-Upload&amp;nbsp;Setup&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Configure the Immich mobile app to back up photos&amp;nbsp;automatically.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;iOS:&lt;/strong&gt;
1. Install Immich from the App Store.
2. Enter server &lt;span class="caps"&gt;URL&lt;/span&gt;: &lt;code&gt;http://your-server-ip:2283&lt;/code&gt; (or &lt;span class="caps"&gt;HTTPS&lt;/span&gt; domain)
3. Log in with your credentials.
4. Tap &lt;strong&gt;Profile (bottom right) → Backup&lt;/strong&gt;
5. Enable:
   - &lt;strong&gt;Backup&lt;/strong&gt;
   - &lt;strong&gt;Background backup&lt;/strong&gt;
   - &lt;strong&gt;Wi-Fi only&lt;/strong&gt; (recommended to save mobile data)
   - &lt;strong&gt;Albums to backup:&lt;/strong&gt; select Camera Roll or all&amp;nbsp;albums&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Android:&lt;/strong&gt;
1. Install Immich from F-Droid or Play Store.
2. Log in to your server.
3. Tap &lt;strong&gt;Albums → Backup&lt;/strong&gt;
4. Enable backup and select albums.
5. For reliable background sync, disable battery optimization for the Immich app in Android&amp;nbsp;settings.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pro Tip:&lt;/strong&gt; The first backup of 10,000+ photos can take days over Wi-Fi. Leave the app open and plugged in overnight for the initial&amp;nbsp;sync.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;Step 4: Reverse Proxy and &lt;span class="caps"&gt;HTTPS&lt;/span&gt;&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Secure remote access with a reverse&amp;nbsp;proxy.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;NGINX&lt;/span&gt; Proxy Manager&amp;nbsp;configuration:&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Domain Names&lt;/td&gt;
&lt;td&gt;&lt;code&gt;photos.yourdomain.com&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scheme&lt;/td&gt;
&lt;td&gt;&lt;code&gt;http&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Forward Hostname / &lt;span class="caps"&gt;IP&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;immich_server&lt;/code&gt; (if on same Docker network) or host &lt;span class="caps"&gt;IP&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Forward Port&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2283&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Websockets Support&lt;/td&gt;
&lt;td&gt;✅ Enabled&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Block Common Exploits&lt;/td&gt;
&lt;td&gt;✅ Enabled&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Custom &lt;span class="caps"&gt;NGINX&lt;/span&gt; snippet for large&amp;nbsp;uploads:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Immich uploads large video files. Increase the body size&amp;nbsp;limit:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;client_max_body_size&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;50G&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;proxy_read_timeout&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;600s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;proxy_send_timeout&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;600s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;proxy_request_buffering&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;proxy_buffering&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In &lt;span class="caps"&gt;NGINX&lt;/span&gt; Proxy Manager, add this to the &lt;strong&gt;Advanced&lt;/strong&gt; tab of the Proxy&amp;nbsp;Host.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 5: Running Face Recognition and Smart&amp;nbsp;Search&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Trigger the initial &lt;span class="caps"&gt;AI&lt;/span&gt; scan of your uploaded&amp;nbsp;photos.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;After uploading photos, go to &lt;strong&gt;Administration → Jobs&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click the &lt;strong&gt;Run&lt;/strong&gt; button next to each&amp;nbsp;job:&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Thumbnail Generation&lt;/strong&gt; (creates preview&amp;nbsp;images)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Metadata Extraction&lt;/strong&gt; (reads &lt;span class="caps"&gt;EXIF&lt;/span&gt;, &lt;span class="caps"&gt;GPS&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Smart Search&lt;/strong&gt; (&lt;span class="caps"&gt;AI&lt;/span&gt;-powered semantic&amp;nbsp;search)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Face Detection&lt;/strong&gt; (finds faces in&amp;nbsp;photos)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Face Recognition&lt;/strong&gt; (groups faces into&amp;nbsp;people)&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Duplicate Detection&lt;/strong&gt; (finds similar&amp;nbsp;images)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Monitor progress in the same panel. A library of 10,000 photos takes 2–4 hours on a 4-core &lt;span class="caps"&gt;CPU&lt;/span&gt;, or 30 minutes with &lt;span class="caps"&gt;GPU&lt;/span&gt;&amp;nbsp;acceleration.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;To enable &lt;span class="caps"&gt;GPU&lt;/span&gt; for machine&amp;nbsp;learning:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Uncomment&amp;nbsp;the &lt;code&gt;deploy&lt;/code&gt; block&amp;nbsp;in &lt;code&gt;immich-machine-learning&lt;/code&gt; service.&lt;/li&gt;
&lt;li&gt;Install &lt;span class="caps"&gt;NVIDIA&lt;/span&gt; Container Toolkit (see Jellyfin&amp;nbsp;guide).&lt;/li&gt;
&lt;li&gt;Restart the&amp;nbsp;stack:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;down
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Use External Libraries for Existing&amp;nbsp;Collections&lt;/h3&gt;
&lt;p&gt;If you have 500 &lt;span class="caps"&gt;GB&lt;/span&gt; of existing photos on a &lt;span class="caps"&gt;NAS&lt;/span&gt;, do not re-upload them. Mount the &lt;span class="caps"&gt;NAS&lt;/span&gt; folder read-only and add it as an external library in Immich. Run the metadata and thumbnail jobs to index&amp;nbsp;them.&lt;/p&gt;
&lt;h3&gt;Tip 2: Set Up Backup to a Second&amp;nbsp;Location&lt;/h3&gt;
&lt;p&gt;Immich stores originals in&amp;nbsp;the &lt;code&gt;UPLOAD_LOCATION&lt;/code&gt;. Back this up alongside the PostgreSQL&amp;nbsp;database:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;immich_postgres&lt;span class="w"&gt; &lt;/span&gt;pg_dump&lt;span class="w"&gt; &lt;/span&gt;-U&lt;span class="w"&gt; &lt;/span&gt;immich&lt;span class="w"&gt; &lt;/span&gt;immich&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;immich-backup_&lt;span class="k"&gt;$(&lt;/span&gt;date&lt;span class="w"&gt; &lt;/span&gt;+%Y%m%d&lt;span class="k"&gt;)&lt;/span&gt;.sql
rsync&lt;span class="w"&gt; &lt;/span&gt;-avP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;UPLOAD_LOCATION&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;/&lt;span class="w"&gt; &lt;/span&gt;/backup/immich-uploads/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 3: Shared Albums for&amp;nbsp;Family&lt;/h3&gt;
&lt;p&gt;Create user accounts for family members under &lt;strong&gt;Administration → Users&lt;/strong&gt;. Each user gets their own private library. Create shared albums and invite others to view or&amp;nbsp;contribute.&lt;/p&gt;
&lt;h3&gt;Tip 4: Handle &lt;span class="caps"&gt;HEIC&lt;/span&gt;&amp;nbsp;Efficiently&lt;/h3&gt;
&lt;p&gt;iPhones shoot &lt;span class="caps"&gt;HEIC&lt;/span&gt; by default. Immich stores the original &lt;span class="caps"&gt;HEIC&lt;/span&gt; and generates a &lt;span class="caps"&gt;JPEG&lt;/span&gt; thumbnail. This saves ~40% storage compared to storing &lt;span class="caps"&gt;JPEG&lt;/span&gt; originals. Do not convert &lt;span class="caps"&gt;HEIC&lt;/span&gt; to &lt;span class="caps"&gt;JPEG&lt;/span&gt; before&amp;nbsp;uploading.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Troubleshooting Common&amp;nbsp;Issues&lt;/h2&gt;
&lt;h3&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;Failed to connect to server&amp;#8221; on Mobile&amp;nbsp;App&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Ensure the server &lt;span class="caps"&gt;URL&lt;/span&gt; includes the&amp;nbsp;protocol: &lt;code&gt;http://&lt;/code&gt; or &lt;code&gt;https://&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;If using a reverse proxy, verify Websockets are&amp;nbsp;enabled&lt;/li&gt;
&lt;li&gt;Check&amp;nbsp;that &lt;code&gt;immich_server&lt;/code&gt; container is&amp;nbsp;healthy: &lt;code&gt;docker compose ps&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;High &lt;span class="caps"&gt;RAM&lt;/span&gt; Usage During&amp;nbsp;Scan&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;immich_machine_learning&lt;/code&gt; container can spike to 4–8 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; during initial face recognition. This is&amp;nbsp;normal.&lt;/li&gt;
&lt;li&gt;If the container is killed (&lt;span class="caps"&gt;OOM&lt;/span&gt;), increase Docker memory limits or add&amp;nbsp;swap:
  &lt;code&gt;bash
  sudo fallocate -l 8G /swapfile
  sudo chmod 600 /swapfile
  sudo mkswap /swapfile
  sudo swapon /swapfile&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Duplicate Detection Not Finding&amp;nbsp;Duplicates&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Duplicate detection only runs on images with similar perceptual hashes. Slightly cropped or re-encoded images may not&amp;nbsp;match.&lt;/li&gt;
&lt;li&gt;Adjust the similarity threshold in &lt;strong&gt;Administration → Settings → Machine Learning&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;You now have Immich running with PostgreSQL, Redis, Typesense, and optional &lt;span class="caps"&gt;GPU&lt;/span&gt;-accelerated machine learning. Your mobile devices can auto-upload, and you have &lt;span class="caps"&gt;AI&lt;/span&gt;-powered search, face recognition, and duplicate detection — all on hardware you&amp;nbsp;control.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/nextcloud-immich-comparison"&gt;Compare Immich vs Nextcloud for photo&amp;nbsp;backup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/homelab-backup-strategy"&gt;Set up a backup target with BorgBackup or&amp;nbsp;Restic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/immich-hardware-transcoding"&gt;Add hardware transcoding for video&amp;nbsp;previews&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/docker-monitoring-grafana-prometheus"&gt;Monitor your Immich stack with&amp;nbsp;Grafana&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;SSD&lt;/span&gt; Storage:&lt;/strong&gt; Samsung 990 &lt;span class="caps"&gt;PRO&lt;/span&gt; or &lt;span class="caps"&gt;WD&lt;/span&gt; Black &lt;span class="caps"&gt;SN850X&lt;/span&gt; for photo&amp;nbsp;libraries&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mini PCs:&lt;/strong&gt; Intel N305 with 32 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; for medium-sized&amp;nbsp;collections&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;NAS&lt;/span&gt;:&lt;/strong&gt; Synology or TrueNAS systems for backing up the upload&amp;nbsp;volume&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;what-is&lt;/code&gt; → &lt;code&gt;/nextcloud-immich-comparison&lt;/code&gt; for readers choosing a photo&amp;nbsp;platform&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mobile&lt;/code&gt; → &lt;code&gt;/tailscale-homelab-guide&lt;/code&gt; for secure remote access without port&amp;nbsp;forwarding&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;/homelab-backup-strategy&lt;/code&gt; for protecting your photo&amp;nbsp;archive&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How many photos are you backing up with Immich?&lt;/strong&gt; Share your library size and server specs in the&amp;nbsp;comments!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Subscribe to the WordForge newsletter&lt;/strong&gt; for weekly self-hosting and privacy-focused&amp;nbsp;guides.&lt;/p&gt;
&lt;/blockquote&gt;</content><category term="Tutorials"/><category term="immich"/><category term="docker"/><category term="docker compose"/><category term="self-hosted"/><category term="photo backup"/><category term="google photos alternative"/><category term="homelab"/></entry><entry><title>Migrate from ESXi to Proxmox: A Complete Homelab Migration Guide 2026</title><link href="https://steadypub.com/2026/06/migrate-from-esxi-to-proxmox/" rel="alternate"/><published>2026-06-05T00:33:00+07:00</published><updated>2026-06-05T00:33:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/migrate-from-esxi-to-proxmox/</id><summary type="html">&lt;p&gt;Step-by-step guide to migrate VMs from VMware ESXi to Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; without reinstalling. Covers &lt;span class="caps"&gt;OVA&lt;/span&gt; export, qm import, live migration tools, and post-migration&amp;nbsp;cleanup.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~20 minutes&lt;br&gt;
&lt;strong&gt;Audience:&lt;/strong&gt; VMware ESXi homelab users affected by Broadcom licensing changes&lt;br&gt;
&lt;strong&gt;Prerequisites:&lt;/strong&gt; Running ESXi 6.7+ or 7.0/8.0, and a fresh Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; 8.2&amp;nbsp;node&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why Migrate from ESXi to&amp;nbsp;Proxmox?&lt;/h2&gt;
&lt;h3&gt;The Broadcom&amp;nbsp;Situation&lt;/h3&gt;
&lt;p&gt;In late 2023, Broadcom acquired VMware and discontinued the free ESXi hypervisor (vSphere Hypervisor). As of 2024–2026, new ESXi downloads require a paid VMware Cloud Foundation (&lt;span class="caps"&gt;VCF&lt;/span&gt;) subscription, with per-core pricing that makes homelab use economically unreasonable. Existing free ESXi installations lost update access and are increasingly&amp;nbsp;insecure.&lt;/p&gt;
&lt;h3&gt;Why Proxmox Is the Natural&amp;nbsp;Replacement&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Factor&lt;/th&gt;
&lt;th&gt;ESXi (Pre-2024)&lt;/th&gt;
&lt;th&gt;Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; 8.2&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;License cost&lt;/td&gt;
&lt;td&gt;Free (discontinued)&lt;/td&gt;
&lt;td&gt;Free, fully functional&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Feature limits&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt; capped at 8 vCPUs&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;APIs&lt;/td&gt;
&lt;td&gt;Locked vSphere APIs&lt;/td&gt;
&lt;td&gt;Full &lt;span class="caps"&gt;REST&lt;/span&gt; &lt;span class="caps"&gt;API&lt;/span&gt; + &lt;span class="caps"&gt;CLI&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backup&lt;/td&gt;
&lt;td&gt;Requires Veeam or paid &lt;span class="caps"&gt;VDP&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Built-in vzdump&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;VMFS&lt;/span&gt; only&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;ZFS&lt;/span&gt;, &lt;span class="caps"&gt;LVM&lt;/span&gt;, Ceph, &lt;span class="caps"&gt;NFS&lt;/span&gt;, iSCSI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Community&lt;/td&gt;
&lt;td&gt;Shrinking due to licensing&lt;/td&gt;
&lt;td&gt;Growing rapidly&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;h3&gt;Hardware&amp;nbsp;Requirements&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Resource&lt;/th&gt;
&lt;th&gt;Minimum&lt;/th&gt;
&lt;th&gt;Recommended&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Proxmox host &lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;64-bit with &lt;span class="caps"&gt;VT&lt;/span&gt;-x&lt;/td&gt;
&lt;td&gt;Same or better than ESXi host&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Proxmox host &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;4 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Match ESXi host &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;128 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Equal or greater than total &lt;span class="caps"&gt;VM&lt;/span&gt; disk usage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network&lt;/td&gt;
&lt;td&gt;1 GbE&lt;/td&gt;
&lt;td&gt;1 GbE shared subnet for migration&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Software&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Access to ESXi Host Client (web &lt;span class="caps"&gt;UI&lt;/span&gt;) or&amp;nbsp;vCenter&lt;/li&gt;
&lt;li&gt;A fresh Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; 8.2 installation with available&amp;nbsp;storage&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;SSH&lt;/span&gt;/&lt;span class="caps"&gt;SCP&lt;/span&gt; access between ESXi and Proxmox (or a shared &lt;span class="caps"&gt;NFS&lt;/span&gt;&amp;nbsp;datastore)&lt;/li&gt;
&lt;li&gt;Adequate free space on Proxmox for imported disks (thin-provisioned VMDKs expand to full size during&amp;nbsp;import)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Export VMs from ESXi as &lt;span class="caps"&gt;OVA&lt;/span&gt;/&lt;span class="caps"&gt;OVF&lt;/span&gt;&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Create portable &lt;span class="caps"&gt;VM&lt;/span&gt; packages from ESXi that Proxmox can&amp;nbsp;import.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Log in to the &lt;strong&gt;ESXi Host Client&lt;/strong&gt;&amp;nbsp;(&lt;code&gt;https://esxi-ip&lt;/code&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Shut down the &lt;span class="caps"&gt;VM&lt;/span&gt; you want to migrate&amp;nbsp;cleanly.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Right-click the &lt;span class="caps"&gt;VM&lt;/span&gt; → &lt;strong&gt;Export&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ESXi will generate two&amp;nbsp;files:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.ovf&lt;/code&gt; — &lt;span class="caps"&gt;VM&lt;/span&gt; configuration (&lt;span class="caps"&gt;CPU&lt;/span&gt;, &lt;span class="caps"&gt;RAM&lt;/span&gt;, network, disk&amp;nbsp;mappings)&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;.vmdk&lt;/code&gt; — Virtual disk&amp;nbsp;image&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Download both files to your local computer or an intermediate storage&amp;nbsp;server.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; If the export is grayed out, power off the &lt;span class="caps"&gt;VM&lt;/span&gt; completely (not just a guest shutdown). Some ESXi versions require the &lt;span class="caps"&gt;VM&lt;/span&gt; to be fully stopped before&amp;nbsp;export.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Alternative: &lt;span class="caps"&gt;SCP&lt;/span&gt; from ESXi datastore&amp;nbsp;directly&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If the web export fails or the &lt;span class="caps"&gt;VM&lt;/span&gt; is too large for browser&amp;nbsp;download:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# From your Proxmox node (or any Linux machine)&lt;/span&gt;
scp&lt;span class="w"&gt; &lt;/span&gt;root@esxi-ip:/vmfs/volumes/datastore1/vm-name/vm-name.vmdk&lt;span class="w"&gt; &lt;/span&gt;/tmp/
scp&lt;span class="w"&gt; &lt;/span&gt;root@esxi-ip:/vmfs/volumes/datastore1/vm-name/vm-name.ovf&lt;span class="w"&gt; &lt;/span&gt;/tmp/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;ESXi root password is&amp;nbsp;required.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 2: Transfer Files to&amp;nbsp;Proxmox&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Move the exported &lt;span class="caps"&gt;VM&lt;/span&gt; files to the Proxmox&amp;nbsp;node.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Option A: Direct &lt;span class="caps"&gt;SCP&lt;/span&gt; to&amp;nbsp;Proxmox&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;scp&lt;span class="w"&gt; &lt;/span&gt;/local/path/*.vmdk&lt;span class="w"&gt; &lt;/span&gt;root@proxmox-ip:/var/lib/vz/dump/
scp&lt;span class="w"&gt; &lt;/span&gt;/local/path/*.ovf&lt;span class="w"&gt; &lt;/span&gt;root@proxmox-ip:/var/lib/vz/dump/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Option B: Shared &lt;span class="caps"&gt;NFS&lt;/span&gt;/&lt;span class="caps"&gt;SMB&lt;/span&gt;&amp;nbsp;datastore&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Mount a temporary &lt;span class="caps"&gt;NFS&lt;/span&gt; share on both ESXi and&amp;nbsp;Proxmox:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# On Proxmox&lt;/span&gt;
mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;/mnt/migration
mount&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;nfs&lt;span class="w"&gt; &lt;/span&gt;nas-ip:/export/migration&lt;span class="w"&gt; &lt;/span&gt;/mnt/migration
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Option C: &lt;span class="caps"&gt;USB&lt;/span&gt; external&amp;nbsp;drive&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For air-gapped networks, copy VMDKs to an external &lt;span class="caps"&gt;USB&lt;/span&gt; drive, attach it to the Proxmox host, and mount&amp;nbsp;it.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 3: Import the &lt;span class="caps"&gt;VM&lt;/span&gt; into&amp;nbsp;Proxmox&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Convert the ESXi virtual disk and register it as a Proxmox &lt;span class="caps"&gt;VM&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;span class="caps"&gt;SSH&lt;/span&gt; into your Proxmox node&amp;nbsp;as &lt;code&gt;root&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a target &lt;span class="caps"&gt;VM&lt;/span&gt; shell without disks (we will attach the imported &lt;span class="caps"&gt;VMDK&lt;/span&gt;):&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;qm&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;migrated-vm&lt;span class="w"&gt; &lt;/span&gt;--memory&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4096&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--cores&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--net0&lt;span class="w"&gt; &lt;/span&gt;virtio,bridge&lt;span class="o"&gt;=&lt;/span&gt;vmbr0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Replace &lt;code&gt;9000&lt;/code&gt; with an unused &lt;span class="caps"&gt;VM&lt;/span&gt; &lt;span class="caps"&gt;ID&lt;/span&gt;, and adjust &lt;span class="caps"&gt;RAM&lt;/span&gt;/cores to match the original &lt;span class="caps"&gt;VM&lt;/span&gt;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Import the &lt;span class="caps"&gt;VMDK&lt;/span&gt; into Proxmox&amp;nbsp;storage:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;qm&lt;span class="w"&gt; &lt;/span&gt;importdisk&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/var/lib/vz/dump/vm-name.vmdk&lt;span class="w"&gt; &lt;/span&gt;local-lvm&lt;span class="w"&gt; &lt;/span&gt;--format&lt;span class="w"&gt; &lt;/span&gt;qcow2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you are using &lt;span class="caps"&gt;ZFS&lt;/span&gt; or another&amp;nbsp;storage:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;qm&lt;span class="w"&gt; &lt;/span&gt;importdisk&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/var/lib/vz/dump/vm-name.vmdk&lt;span class="w"&gt; &lt;/span&gt;zfs-tank&lt;span class="w"&gt; &lt;/span&gt;--format&lt;span class="w"&gt; &lt;/span&gt;raw
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Attach the imported disk to the &lt;span class="caps"&gt;VM&lt;/span&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;qm&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--scsi0&lt;span class="w"&gt; &lt;/span&gt;local-lvm:vm-9000-disk-1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Add a &lt;span class="caps"&gt;CD&lt;/span&gt;-&lt;span class="caps"&gt;ROM&lt;/span&gt; drive (optional, for driver&amp;nbsp;installation):&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;qm&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--ide2&lt;span class="w"&gt; &lt;/span&gt;local:iso/virtio-win.iso,media&lt;span class="o"&gt;=&lt;/span&gt;cdrom
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Set the boot&amp;nbsp;disk:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;qm&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--boot&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;order&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;scsi0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;In the Proxmox web &lt;span class="caps"&gt;UI&lt;/span&gt;, inspect the &lt;span class="caps"&gt;VM&lt;/span&gt; under &lt;strong&gt;Hardware&lt;/strong&gt;:&lt;/li&gt;
&lt;li&gt;Ensure the disk shows&amp;nbsp;as &lt;code&gt;scsi0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Verify network adapter&amp;nbsp;is &lt;code&gt;virtio&lt;/code&gt; on &lt;code&gt;vmbr0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Remove any &lt;span class="caps"&gt;IDE&lt;/span&gt; disk references if they were&amp;nbsp;auto-created&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Step 4: Post-Migration&amp;nbsp;Configuration&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Fix network drivers, install &lt;span class="caps"&gt;QEMU&lt;/span&gt; guest agent, and optimize for &lt;span class="caps"&gt;KVM&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;For Windows&amp;nbsp;VMs:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Start the &lt;span class="caps"&gt;VM&lt;/span&gt; and open the&amp;nbsp;console.&lt;/li&gt;
&lt;li&gt;Windows will likely detect new hardware (the virtual &lt;span class="caps"&gt;NIC&lt;/span&gt; changed from Intel E1000e to&amp;nbsp;VirtIO).&lt;/li&gt;
&lt;li&gt;Mount the &lt;strong&gt;VirtIO driver &lt;span class="caps"&gt;ISO&lt;/span&gt;&lt;/strong&gt;:&lt;/li&gt;
&lt;li&gt;In Proxmox &lt;span class="caps"&gt;UI&lt;/span&gt;: &lt;strong&gt;Hardware → &lt;span class="caps"&gt;CD&lt;/span&gt;/&lt;span class="caps"&gt;DVD&lt;/span&gt; Drive → Choose&amp;nbsp;virtio-win.iso&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Inside Windows, open Device Manager and update the &lt;strong&gt;Ethernet Controller&lt;/strong&gt; driver by pointing it to the mounted &lt;span class="caps"&gt;ISO&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;Install the &lt;span class="caps"&gt;QEMU&lt;/span&gt; guest agent for clean shutdowns and &lt;span class="caps"&gt;IP&lt;/span&gt;&amp;nbsp;reporting:&lt;/li&gt;
&lt;li&gt;Mount &lt;code&gt;virtio-win.iso&lt;/code&gt;, navigate&amp;nbsp;to &lt;code&gt;guest-agent/&lt;/code&gt;,&amp;nbsp;run &lt;code&gt;qemu-ga-x64.msi&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;For Linux&amp;nbsp;VMs:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Start the &lt;span class="caps"&gt;VM&lt;/span&gt; and open the&amp;nbsp;console.&lt;/li&gt;
&lt;li&gt;Linux usually detects VirtIO NICs&amp;nbsp;automatically.&lt;/li&gt;
&lt;li&gt;Install the &lt;span class="caps"&gt;QEMU&lt;/span&gt; guest&amp;nbsp;agent:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;qemu-guest-agent&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;# Debian/Ubuntu&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;yum&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;qemu-guest-agent&lt;span class="w"&gt;                       &lt;/span&gt;&lt;span class="c1"&gt;# RHEL/CentOS&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--now&lt;span class="w"&gt; &lt;/span&gt;qemu-guest-agent
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Update initramfs if you switched disk controller&amp;nbsp;types:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;update-initramfs&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;# Debian/Ubuntu&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;dracut&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="c1"&gt;# RHEL/Fedora&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;For all&amp;nbsp;VMs:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Remove the &lt;span class="caps"&gt;CD&lt;/span&gt;-&lt;span class="caps"&gt;ROM&lt;/span&gt; after driver&amp;nbsp;installation:
  &lt;code&gt;bash
  qm set 9000 --delete ide2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Adjust memory ballooning if&amp;nbsp;desired:
  &lt;code&gt;bash
  qm set 9000 --balloon 2048&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Enable Discard (&lt;span class="caps"&gt;TRIM&lt;/span&gt;) if the underlying storage is &lt;span class="caps"&gt;SSD&lt;/span&gt;:
  In the &lt;span class="caps"&gt;UI&lt;/span&gt;, go to &lt;strong&gt;Hardware → Hard Disk → Edit → Check &amp;#8220;Discard&amp;#8221;&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Step 5: Bulk Migration&amp;nbsp;with &lt;code&gt;qm import&lt;/code&gt; Scripting&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Automate migration when you have many&amp;nbsp;VMs.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;p&gt;For 5+ VMs, manual clicking becomes tedious. Use a shell&amp;nbsp;loop:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c1"&gt;# migrate.sh — run on Proxmox as root&lt;/span&gt;

&lt;span class="nv"&gt;VM_LIST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;vm1 vm2 vm3 vm4 vm5&amp;quot;&lt;/span&gt;
&lt;span class="nv"&gt;DATASTORE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;local-lvm&amp;quot;&lt;/span&gt;
&lt;span class="nv"&gt;IMPORT_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/var/lib/vz/dump&amp;quot;&lt;/span&gt;
&lt;span class="nv"&gt;START_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;9000&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;VM_NAME&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$VM_LIST&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;VMID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;&lt;span class="nv"&gt;START_ID&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Importing &lt;/span&gt;&lt;span class="nv"&gt;$VM_NAME&lt;/span&gt;&lt;span class="s2"&gt; as VMID &lt;/span&gt;&lt;span class="nv"&gt;$VMID&lt;/span&gt;&lt;span class="s2"&gt;...&amp;quot;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;qm&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$VMID&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$VM_NAME&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--memory&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4096&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--cores&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--net0&lt;span class="w"&gt; &lt;/span&gt;virtio,bridge&lt;span class="o"&gt;=&lt;/span&gt;vmbr0
&lt;span class="w"&gt;  &lt;/span&gt;qm&lt;span class="w"&gt; &lt;/span&gt;importdisk&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$VMID&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$IMPORT_DIR&lt;/span&gt;/&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;VM_NAME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;.vmdk&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$DATASTORE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--format&lt;span class="w"&gt; &lt;/span&gt;qcow2
&lt;span class="w"&gt;  &lt;/span&gt;qm&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$VMID&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--scsi0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DATASTORE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;:vm-&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;VMID&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;-disk-1&lt;span class="w"&gt; &lt;/span&gt;--boot&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;order&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;scsi0
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Done: &lt;/span&gt;&lt;span class="nv"&gt;$VM_NAME&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Make executable and&amp;nbsp;run:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;chmod&lt;span class="w"&gt; &lt;/span&gt;+x&lt;span class="w"&gt; &lt;/span&gt;migrate.sh
./migrate.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Convert Thick to Thin During&amp;nbsp;Import&lt;/h3&gt;
&lt;p&gt;ESXi often uses thick-provisioned VMDKs.&amp;nbsp;Proxmox&amp;#8217;s &lt;code&gt;qcow2&lt;/code&gt; format is thin-provisioned by default, saving significant space. Always&amp;nbsp;specify &lt;code&gt;--format qcow2&lt;/code&gt; unless you need raw&amp;nbsp;performance.&lt;/p&gt;
&lt;h3&gt;Tip 2: Snapshot Before&amp;nbsp;Migration&lt;/h3&gt;
&lt;p&gt;On ESXi, take a snapshot before powering off. If the migration fails, you can revert and retry without losing the running&amp;nbsp;state.&lt;/p&gt;
&lt;h3&gt;Tip 3: Network &lt;span class="caps"&gt;MAC&lt;/span&gt; Address&amp;nbsp;Preservation&lt;/h3&gt;
&lt;p&gt;If your &lt;span class="caps"&gt;VM&lt;/span&gt; has &lt;span class="caps"&gt;DHCP&lt;/span&gt; reservations or firewall rules tied to its &lt;span class="caps"&gt;MAC&lt;/span&gt; address, preserve it during&amp;nbsp;migration:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;qm&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--net0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;virtio&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;AA:BB:CC:DD:EE:FF,bridge&lt;span class="o"&gt;=&lt;/span&gt;vmbr0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 4: Test One &lt;span class="caps"&gt;VM&lt;/span&gt; Before Bulk&amp;nbsp;Operations&lt;/h3&gt;
&lt;p&gt;Migrate your least critical &lt;span class="caps"&gt;VM&lt;/span&gt; first. Verify it boots, network works, and applications function before committing time to the&amp;nbsp;rest.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Troubleshooting Common&amp;nbsp;Issues&lt;/h2&gt;
&lt;h3&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;No bootable device&amp;#8221; After&amp;nbsp;Import&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Ensure the boot order&amp;nbsp;includes &lt;code&gt;scsi0&lt;/code&gt; or &lt;code&gt;virtio0&lt;/code&gt;:
  &lt;code&gt;bash
  qm set 9000 --boot order=scsi0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Check that the imported disk is attached and not showing as &amp;#8220;Unused&amp;#8221; in the Hardware&amp;nbsp;tab.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Blue Screen (INACCESSIBLE_BOOT_DEVICE) on&amp;nbsp;Windows&lt;/h3&gt;
&lt;p&gt;The disk controller changed from VMware &lt;span class="caps"&gt;LSI&lt;/span&gt; Logic to VirtIO/&lt;span class="caps"&gt;SCSI&lt;/span&gt;. Before exporting from ESXi, install the VirtIO drivers inside Windows, or change the Proxmox disk controller&amp;nbsp;to &lt;code&gt;IDE&lt;/code&gt; temporarily, boot Windows, install drivers, then switch&amp;nbsp;to &lt;code&gt;SCSI&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Slow Import&amp;nbsp;Speed&lt;/h3&gt;
&lt;p&gt;&lt;span class="caps"&gt;VMDK&lt;/span&gt; to &lt;span class="caps"&gt;QCOW2&lt;/span&gt; conversion is &lt;span class="caps"&gt;CPU&lt;/span&gt;-intensive. On low-power hosts (N100), large disks can take hours. Consider:
-&amp;nbsp;Using &lt;code&gt;screen&lt;/code&gt; or &lt;code&gt;tmux&lt;/code&gt; so &lt;span class="caps"&gt;SSH&lt;/span&gt; disconnects do not abort the import
- Scheduling bulk imports&amp;nbsp;overnight&lt;/p&gt;
&lt;h3&gt;Network Not&amp;nbsp;Connecting&lt;/h3&gt;
&lt;p&gt;Linux VMs may have network interface names changed&amp;nbsp;(&lt;code&gt;ens160&lt;/code&gt; → &lt;code&gt;ens18&lt;/code&gt;).&amp;nbsp;Update &lt;code&gt;/etc/netplan/&lt;/code&gt; or &lt;code&gt;/etc/network/interfaces&lt;/code&gt; accordingly.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;You have exported VMs from ESXi, transferred them to Proxmox, converted VMDKs to &lt;span class="caps"&gt;QCOW2&lt;/span&gt;, attached them to new &lt;span class="caps"&gt;VM&lt;/span&gt; configurations, and fixed network drivers. The migration path is proven and does not require reinstalling operating systems or&amp;nbsp;applications.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/proxmox-vs-esxi-for-homelab"&gt;Compare Proxmox vs ESXi in&amp;nbsp;depth&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/proxmox-backup-server-guide"&gt;Set up Proxmox Backup Server for automated &lt;span class="caps"&gt;VM&lt;/span&gt;&amp;nbsp;snapshots&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/proxmox-cluster-setup"&gt;Learn Proxmox high availability&amp;nbsp;clustering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/docker-compose-for-beginners"&gt;Deploy your first Docker stack on the migrated &lt;span class="caps"&gt;VM&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mini PCs for Proxmox:&lt;/strong&gt; Beelink, Minisforum, or used Dell OptiPlex&amp;nbsp;units&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Storage upgrades:&lt;/strong&gt; Samsung 990 &lt;span class="caps"&gt;PRO&lt;/span&gt;, Crucial T500 for fast &lt;span class="caps"&gt;VM&lt;/span&gt;&amp;nbsp;storage&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;10 GbE networking:&lt;/strong&gt; MikroTik &lt;span class="caps"&gt;CRS305&lt;/span&gt; or &lt;span class="caps"&gt;TP&lt;/span&gt;-Link &lt;span class="caps"&gt;TL&lt;/span&gt;-&lt;span class="caps"&gt;SX3008F&lt;/span&gt; for fast &lt;span class="caps"&gt;VM&lt;/span&gt;&amp;nbsp;migrations&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;why-migrate&lt;/code&gt; → &lt;code&gt;/proxmox-vs-esxi-for-homelab&lt;/code&gt; for readers weighing&amp;nbsp;options&lt;/li&gt;
&lt;li&gt;&lt;code&gt;import&lt;/code&gt; → &lt;code&gt;/proxmox-beginner-guide&lt;/code&gt; for storage and networking&amp;nbsp;basics&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;/docker-compose-for-beginners&lt;/code&gt; for app deployment on the migrated&amp;nbsp;VMs&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How many VMs did you migrate?&lt;/strong&gt; Share your ESXi-to-Proxmox story in the&amp;nbsp;comments!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Subscribe to the WordForge newsletter&lt;/strong&gt; for more migration guides, self-hosting tips, and homelab hardware&amp;nbsp;reviews.&lt;/p&gt;
&lt;/blockquote&gt;</content><category term="Tutorials"/><category term="proxmox"/><category term="esxi"/><category term="vmware"/><category term="migration"/><category term="homelab"/><category term="self-hosted"/><category term="broadcom"/></entry><entry><title>Nextcloud Docker Compose Setup 2026: Self-Hosted Cloud Storage Guide</title><link href="https://steadypub.com/2026/06/nextcloud-docker-compose/" rel="alternate"/><published>2026-06-05T00:33:00+07:00</published><updated>2026-06-05T00:33:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/nextcloud-docker-compose/</id><summary type="html">&lt;p&gt;Deploy Nextcloud with MariaDB, Redis, and &lt;span class="caps"&gt;NGINX&lt;/span&gt; Proxy Manager using Docker Compose. A complete production-ready configuration with persistent volumes and security&amp;nbsp;hardening.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~16 minutes&lt;br&gt;
&lt;strong&gt;Audience:&lt;/strong&gt; Docker users ready to replace Google Drive / Dropbox / iCloud&lt;br&gt;
&lt;strong&gt;Last tested:&lt;/strong&gt; Nextcloud 30.0, MariaDB 11.4, Redis 7.4, June&amp;nbsp;2026&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is&amp;nbsp;Nextcloud?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Nextcloud is a self-hosted cloud storage and collaboration platform. It provides file sync, document editing (via Collabora or OnlyOffice), calendar/contacts sync (CalDAV/CardDAV), and a growing app ecosystem — all under your control, on your server, with no vendor lock-in or data&amp;nbsp;mining.&lt;/p&gt;
&lt;p&gt;For homelab users, Nextcloud is often the first &amp;#8220;serious&amp;#8221; self-hosted application. It replaces multiple SaaS subscriptions and gives you terabytes of storage without monthly&amp;nbsp;fees.&lt;/p&gt;
&lt;h3&gt;Key&amp;nbsp;Benefits&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Nextcloud Self-Hosted&lt;/th&gt;
&lt;th&gt;Google Drive / Dropbox&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Storage cost&lt;/td&gt;
&lt;td&gt;One-time hardware&lt;/td&gt;
&lt;td&gt;$10–30/month for 2 &lt;span class="caps"&gt;TB&lt;/span&gt;+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data privacy&lt;/td&gt;
&lt;td&gt;You own the encryption keys&lt;/td&gt;
&lt;td&gt;Provider can scan files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom domain&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Business plans only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Apps / integrations&lt;/td&gt;
&lt;td&gt;200+ community apps&lt;/td&gt;
&lt;td&gt;Limited to vendor choices&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Max file size&lt;/td&gt;
&lt;td&gt;Limited only by disk/&lt;span class="caps"&gt;ZFS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;750 &lt;span class="caps"&gt;GB&lt;/span&gt; upload limit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Offline sync&lt;/td&gt;
&lt;td&gt;Desktop, Android, iOS&lt;/td&gt;
&lt;td&gt;Desktop, Android, iOS&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;h3&gt;Hardware&amp;nbsp;Requirements&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Users&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Storage&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1–2 personal&lt;/td&gt;
&lt;td&gt;2 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;2 cores&lt;/td&gt;
&lt;td&gt;100 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Raspberry Pi 5 or N100 viable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3–5 family&lt;/td&gt;
&lt;td&gt;4 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;4 cores&lt;/td&gt;
&lt;td&gt;500 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt; + &lt;span class="caps"&gt;HDD&lt;/span&gt; backup&lt;/td&gt;
&lt;td&gt;Recommended for most homelabs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10+ small team&lt;/td&gt;
&lt;td&gt;8 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;4 cores&lt;/td&gt;
&lt;td&gt;1 &lt;span class="caps"&gt;TB&lt;/span&gt; NVMe + backup&lt;/td&gt;
&lt;td&gt;Redis and database on same host&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Software&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Docker Engine 24.0+ and Docker Compose&amp;nbsp;plugin&lt;/li&gt;
&lt;li&gt;A Linux host with a static &lt;span class="caps"&gt;IP&lt;/span&gt; or local &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;name&lt;/li&gt;
&lt;li&gt;(Optional) A reverse proxy for &lt;span class="caps"&gt;HTTPS&lt;/span&gt; (&lt;span class="caps"&gt;NGINX&lt;/span&gt; Proxy Manager, Traefik, or&amp;nbsp;Caddy)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Create the Docker Compose&amp;nbsp;Stack&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Write a&amp;nbsp;production-grade &lt;code&gt;docker-compose.yml&lt;/code&gt; with MariaDB, Redis, and&amp;nbsp;Nextcloud.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Create a project&amp;nbsp;directory:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;~/nextcloud&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/nextcloud
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Create &lt;code&gt;.env&lt;/code&gt; for&amp;nbsp;secrets:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;cat&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;.env&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&amp;lt; &amp;#39;EOF&amp;#39;&lt;/span&gt;
&lt;span class="s"&gt;MYSQL_ROOT_PASSWORD=change-this-root-password-now&lt;/span&gt;
&lt;span class="s"&gt;MYSQL_PASSWORD=change-this-db-password-now&lt;/span&gt;
&lt;span class="s"&gt;NEXTCLOUD_ADMIN_USER=admin&lt;/span&gt;
&lt;span class="s"&gt;NEXTCLOUD_ADMIN_PASSWORD=change-this-admin-password-now&lt;/span&gt;
&lt;span class="s"&gt;NEXTCLOUD_TRUSTED_DOMAINS=nextcloud.yourdomain.com&lt;/span&gt;
&lt;span class="s"&gt;EOF&lt;/span&gt;
chmod&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;600&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;.env
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Create &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;mariadb:11.4&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud-db&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;--transaction-isolation=READ-COMMITTED --log-bin=binlog --binlog-format=ROW&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;db-data:/var/lib/mysql&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_PASSWORD=${MYSQL_PASSWORD}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_DATABASE=nextcloud&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_USER=nextcloud&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;healthcheck&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;CMD&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;mariadb-admin&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ping&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-u&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;root&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-p${MYSQL_ROOT_PASSWORD}&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;10s&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;5s&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;retries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;5&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis:7.4-alpine&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud-redis&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis-data:/data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud:30-apache&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud-app&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8080:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;links&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;db&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud-data:/var/www/html&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_PASSWORD=${MYSQL_PASSWORD}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_DATABASE=nextcloud&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_USER=nextcloud&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_HOST=db&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;REDIS_HOST=redis&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;NEXTCLOUD_ADMIN_USER=${NEXTCLOUD_ADMIN_USER}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;NEXTCLOUD_ADMIN_PASSWORD=${NEXTCLOUD_ADMIN_PASSWORD}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;NEXTCLOUD_TRUSTED_DOMAINS=${NEXTCLOUD_TRUSTED_DOMAINS}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;OVERWRITEPROTOCOL=https&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;service_healthy&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;service_started&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;healthcheck&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;CMD&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;curl&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-f&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://localhost:80/status.php&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;30s&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;10s&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;retries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;3&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;cron&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud:30-apache&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud-cron&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud-data:/var/www/html:ro&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;entrypoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/cron.sh&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;db&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;db-data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;redis-data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;nextcloud-data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Architecture Note:&lt;/strong&gt; We use MariaDB instead of PostgreSQL because it is more forgiving for beginners and widely tested with Nextcloud. Redis acts as a file locking cache, dramatically improving performance for concurrent&amp;nbsp;users.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;Step 2: Deploy and Complete Web&amp;nbsp;Setup&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Start the stack and finish installation through the web &lt;span class="caps"&gt;UI&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Start the&amp;nbsp;stack:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Watch logs to ensure the database&amp;nbsp;initializes:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;logs&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;db
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Wait for the &amp;#8220;mariadbd: ready for connections&amp;#8221; line, then press&amp;nbsp;Ctrl+C.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open your&amp;nbsp;browser:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;http://your-server-ip:8080
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;You should see the Nextcloud setup screen. Because we passed admin credentials via environment variables, it may auto-create the admin account and skip the wizard. If&amp;nbsp;not:&lt;/li&gt;
&lt;li&gt;Create an admin&amp;nbsp;account&lt;/li&gt;
&lt;li&gt;Database: &lt;strong&gt;MySQL/MariaDB&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Database&amp;nbsp;user: &lt;code&gt;nextcloud&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Database password:&amp;nbsp;(from &lt;code&gt;.env&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Database&amp;nbsp;name: &lt;code&gt;nextcloud&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Database&amp;nbsp;host: &lt;code&gt;db&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click &lt;strong&gt;Install&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;After installation, log in and go to &lt;strong&gt;Administration settings → Overview&lt;/strong&gt;. Address any warnings (&lt;span class="caps"&gt;HTTPS&lt;/span&gt;, memory cache,&amp;nbsp;etc.).&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Step 3: Configure Redis and&amp;nbsp;Performance&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Enable Redis for file locking and adjust &lt;span class="caps"&gt;PHP&lt;/span&gt; memory&amp;nbsp;limits.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Enter the Nextcloud app&amp;nbsp;container:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="w"&gt; &lt;/span&gt;www-data&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;nextcloud-app&lt;span class="w"&gt; &lt;/span&gt;bash
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Configure Redis in&amp;nbsp;Nextcloud:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;php&lt;span class="w"&gt; &lt;/span&gt;occ&lt;span class="w"&gt; &lt;/span&gt;config:system:set&lt;span class="w"&gt; &lt;/span&gt;redis&lt;span class="w"&gt; &lt;/span&gt;host&lt;span class="w"&gt; &lt;/span&gt;--value&lt;span class="o"&gt;=&lt;/span&gt;redis
php&lt;span class="w"&gt; &lt;/span&gt;occ&lt;span class="w"&gt; &lt;/span&gt;config:system:set&lt;span class="w"&gt; &lt;/span&gt;redis&lt;span class="w"&gt; &lt;/span&gt;port&lt;span class="w"&gt; &lt;/span&gt;--value&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;6379&lt;/span&gt;
php&lt;span class="w"&gt; &lt;/span&gt;occ&lt;span class="w"&gt; &lt;/span&gt;config:system:set&lt;span class="w"&gt; &lt;/span&gt;memcache.locking&lt;span class="w"&gt; &lt;/span&gt;--value&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;OC&lt;span class="se"&gt;\\&lt;/span&gt;Memcache&lt;span class="se"&gt;\\&lt;/span&gt;Redis
php&lt;span class="w"&gt; &lt;/span&gt;occ&lt;span class="w"&gt; &lt;/span&gt;config:system:set&lt;span class="w"&gt; &lt;/span&gt;memcache.local&lt;span class="w"&gt; &lt;/span&gt;--value&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;OC&lt;span class="se"&gt;\\&lt;/span&gt;Memcache&lt;span class="se"&gt;\\&lt;/span&gt;APCu
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Increase &lt;span class="caps"&gt;PHP&lt;/span&gt; memory&amp;nbsp;limit:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;php&lt;span class="w"&gt; &lt;/span&gt;occ&lt;span class="w"&gt; &lt;/span&gt;config:system:set&lt;span class="w"&gt; &lt;/span&gt;memory_limit&lt;span class="w"&gt; &lt;/span&gt;--value&lt;span class="o"&gt;=&lt;/span&gt;1024M
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Set background jobs to use cron (already running in&amp;nbsp;our &lt;code&gt;cron&lt;/code&gt; service):&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;php&lt;span class="w"&gt; &lt;/span&gt;occ&lt;span class="w"&gt; &lt;/span&gt;background:cron
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Exit the&amp;nbsp;container:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Restart the app container to&amp;nbsp;apply:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;restart&lt;span class="w"&gt; &lt;/span&gt;app
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 4: Reverse Proxy and &lt;span class="caps"&gt;HTTPS&lt;/span&gt;&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Secure Nextcloud with &lt;span class="caps"&gt;HTTPS&lt;/span&gt; via &lt;span class="caps"&gt;NGINX&lt;/span&gt; Proxy&amp;nbsp;Manager.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;p&gt;If you already have &lt;span class="caps"&gt;NGINX&lt;/span&gt; Proxy Manager running, add a Proxy&amp;nbsp;Host:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Domain Names&lt;/td&gt;
&lt;td&gt;&lt;code&gt;nextcloud.yourdomain.com&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scheme&lt;/td&gt;
&lt;td&gt;&lt;code&gt;http&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Forward Hostname / &lt;span class="caps"&gt;IP&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;nextcloud-app&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Forward Port&lt;/td&gt;
&lt;td&gt;&lt;code&gt;80&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Block Common Exploits&lt;/td&gt;
&lt;td&gt;✅ Enabled&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Websockets Support&lt;/td&gt;
&lt;td&gt;✅ Enabled&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Important Nextcloud config for reverse&amp;nbsp;proxy:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Enter the app container and&amp;nbsp;run:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;php&lt;span class="w"&gt; &lt;/span&gt;occ&lt;span class="w"&gt; &lt;/span&gt;config:system:set&lt;span class="w"&gt; &lt;/span&gt;trusted_proxies&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--value&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;172&lt;/span&gt;.18.0.0/16
php&lt;span class="w"&gt; &lt;/span&gt;occ&lt;span class="w"&gt; &lt;/span&gt;config:system:set&lt;span class="w"&gt; &lt;/span&gt;overwritehost&lt;span class="w"&gt; &lt;/span&gt;--value&lt;span class="o"&gt;=&lt;/span&gt;nextcloud.yourdomain.com
php&lt;span class="w"&gt; &lt;/span&gt;occ&lt;span class="w"&gt; &lt;/span&gt;config:system:set&lt;span class="w"&gt; &lt;/span&gt;overwriteprotocol&lt;span class="w"&gt; &lt;/span&gt;--value&lt;span class="o"&gt;=&lt;/span&gt;https
php&lt;span class="w"&gt; &lt;/span&gt;occ&lt;span class="w"&gt; &lt;/span&gt;config:system:set&lt;span class="w"&gt; &lt;/span&gt;overwrite.cli.url&lt;span class="w"&gt; &lt;/span&gt;--value&lt;span class="o"&gt;=&lt;/span&gt;https://nextcloud.yourdomain.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Security Note:&lt;/strong&gt; Do not expose port 8080 directly to the internet. Always use a reverse proxy with valid &lt;span class="caps"&gt;SSL&lt;/span&gt;&amp;nbsp;certificates.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;Step 5: Desktop and Mobile Sync&amp;nbsp;Setup&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Connect client apps to your self-hosted&amp;nbsp;instance.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Desktop (Windows/macOS/Linux):&lt;/strong&gt;
1. Download Nextcloud Desktop from &lt;a href="https://nextcloud.com/install/"&gt;nextcloud.com/install&lt;/a&gt;
2. Enter your server &lt;span class="caps"&gt;URL&lt;/span&gt;: &lt;code&gt;https://nextcloud.yourdomain.com&lt;/code&gt;
3. Log in and choose folders to&amp;nbsp;sync&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Android / iOS:&lt;/strong&gt;
1. Install Nextcloud from the Play Store / App Store
2. Enter server &lt;span class="caps"&gt;URL&lt;/span&gt; and credentials
3. Enable auto-upload for camera photos (a popular Immich alternative for simple&amp;nbsp;sync)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CalDAV/CardDAV (Thunderbird, Apple Calendar, DAVx⁵):&lt;/strong&gt;
- &lt;span class="caps"&gt;URL&lt;/span&gt;: &lt;code&gt;https://nextcloud.yourdomain.com/remote.php/dav&lt;/code&gt;
- Use your Nextcloud username and app password (create one in &lt;strong&gt;Security → Devices &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; sessions&lt;/strong&gt;)&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Enable Server-Side&amp;nbsp;Encryption&lt;/h3&gt;
&lt;p&gt;If your data disk is not encrypted at rest, enable Nextcloud&amp;#8217;s server-side&amp;nbsp;encryption:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;php&lt;span class="w"&gt; &lt;/span&gt;occ&lt;span class="w"&gt; &lt;/span&gt;encryption:enable
php&lt;span class="w"&gt; &lt;/span&gt;occ&lt;span class="w"&gt; &lt;/span&gt;encryption:encrypt-all
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: This protects data at rest but adds &lt;span class="caps"&gt;CPU&lt;/span&gt; overhead. &lt;span class="caps"&gt;ZFS&lt;/span&gt; native encryption&amp;nbsp;(&lt;code&gt;zfs create -o encryption=on&lt;/code&gt;) is often a better&amp;nbsp;alternative.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Tip 2: Offsite Backup with&amp;nbsp;Restic&lt;/h3&gt;
&lt;p&gt;Back up&amp;nbsp;your &lt;code&gt;nextcloud-data&lt;/code&gt; and &lt;code&gt;db-data&lt;/code&gt; volumes&amp;nbsp;nightly:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;nextcloud-db&lt;span class="w"&gt; &lt;/span&gt;mariadb-dump&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;nextcloud&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;nextcloud-sqlbkp_&lt;span class="k"&gt;$(&lt;/span&gt;date&lt;span class="w"&gt; &lt;/span&gt;+%Y%m%d&lt;span class="k"&gt;)&lt;/span&gt;.sql
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Store the &lt;span class="caps"&gt;SQL&lt;/span&gt; dump and volume backup on a &lt;a href="/best-europe-vps-homelab"&gt;Hetzner Storage Box&lt;/a&gt; or local &lt;span class="caps"&gt;NAS&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;Tip 3: Use Preview&amp;nbsp;Generator&lt;/h3&gt;
&lt;p&gt;Generate thumbnails ahead of time to avoid &lt;span class="caps"&gt;CPU&lt;/span&gt; spikes when browsing&amp;nbsp;photos:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;php&lt;span class="w"&gt; &lt;/span&gt;occ&lt;span class="w"&gt; &lt;/span&gt;app:install&lt;span class="w"&gt; &lt;/span&gt;previewgenerator
php&lt;span class="w"&gt; &lt;/span&gt;occ&lt;span class="w"&gt; &lt;/span&gt;preview:generate-all
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Add to cron for periodic&amp;nbsp;generation.&lt;/p&gt;
&lt;h3&gt;Tip 4: Limit Upload&amp;nbsp;Size&lt;/h3&gt;
&lt;p&gt;The default upload limit is 2 &lt;span class="caps"&gt;GB&lt;/span&gt;. To raise&amp;nbsp;it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;php&lt;span class="w"&gt; &lt;/span&gt;occ&lt;span class="w"&gt; &lt;/span&gt;config:system:set&lt;span class="w"&gt; &lt;/span&gt;max_chunk_size&lt;span class="w"&gt; &lt;/span&gt;--value&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;104857600&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Also adjust the reverse proxy&amp;nbsp;(&lt;code&gt;client_max_body_size 10G;&lt;/code&gt; in &lt;span class="caps"&gt;NGINX&lt;/span&gt;).&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Troubleshooting Common&amp;nbsp;Issues&lt;/h2&gt;
&lt;h3&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;Internal Server Error&amp;#8221; on First&amp;nbsp;Login&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Check database&amp;nbsp;connectivity: &lt;code&gt;docker compose logs db&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Ensure MariaDB finished initializing before Nextcloud started&amp;nbsp;(our &lt;code&gt;depends_on&lt;/code&gt; with &lt;code&gt;condition: service_healthy&lt;/code&gt; handles&amp;nbsp;this)&lt;/li&gt;
&lt;li&gt;Verify &lt;code&gt;.env&lt;/code&gt; passwords do not contain special characters that break &lt;span class="caps"&gt;YAML&lt;/span&gt; parsing (wrap in quotes if&amp;nbsp;needed)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Slow File&amp;nbsp;Listing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Ensure Redis is configured for file locking (see Step&amp;nbsp;3)&lt;/li&gt;
&lt;li&gt;Enable &lt;span class="caps"&gt;PHP&lt;/span&gt; OPcache in the container (it is enabled by default in the official&amp;nbsp;image)&lt;/li&gt;
&lt;li&gt;Check&amp;nbsp;that &lt;code&gt;cron&lt;/code&gt; container is&amp;nbsp;running: &lt;code&gt;docker compose ps cron&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;Trusted Domain&amp;#8221;&amp;nbsp;Error&lt;/h3&gt;
&lt;p&gt;Add your domain&amp;nbsp;to &lt;code&gt;NEXTCLOUD_TRUSTED_DOMAINS&lt;/code&gt; in &lt;code&gt;.env&lt;/code&gt;,&amp;nbsp;then:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;down
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;You now have a production-grade Nextcloud deployment with MariaDB, Redis, cron jobs, and reverse proxy compatibility. It can serve a family or small team with file sync, calendars, contacts, and optional document&amp;nbsp;editing.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/nextcloud-immich-comparison"&gt;Compare Nextcloud vs Immich for photo&amp;nbsp;backup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/nextcloud-office-integration"&gt;Add OnlyOffice or Collabora for document&amp;nbsp;editing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/homelab-backup-strategy"&gt;Back up your volumes with Restic or&amp;nbsp;BorgBackup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/nextcloud-end-to-end-encryption"&gt;Set up client-side encryption with Nextcloud &lt;span class="caps"&gt;E2EE&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Storage:&lt;/strong&gt; Samsung 870 &lt;span class="caps"&gt;EVO&lt;/span&gt; / 990 &lt;span class="caps"&gt;PRO&lt;/span&gt; SSDs for Nextcloud data&amp;nbsp;volumes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mini PCs:&lt;/strong&gt; Intel N305 systems for running Nextcloud 24/7 at low&amp;nbsp;power&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;UPS&lt;/span&gt;:&lt;/strong&gt; &lt;span class="caps"&gt;APC&lt;/span&gt; Back-&lt;span class="caps"&gt;UPS&lt;/span&gt; to prevent database corruption during power&amp;nbsp;loss&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;what-is&lt;/code&gt; → &lt;code&gt;/nextcloud-vs-owncloud&lt;/code&gt; for readers comparing cloud&amp;nbsp;platforms&lt;/li&gt;
&lt;li&gt;&lt;code&gt;performance&lt;/code&gt; → &lt;code&gt;/docker-monitoring-grafana-prometheus&lt;/code&gt; to monitor Nextcloud resource&amp;nbsp;usage&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;/nextcloud-immich-comparison&lt;/code&gt; for photo backup&amp;nbsp;specialization&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What did you replace with Nextcloud?&lt;/strong&gt; Share your self-hosting wins in the&amp;nbsp;comments!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Subscribe to the WordForge newsletter&lt;/strong&gt; for weekly Docker and self-hosted app&amp;nbsp;guides.&lt;/p&gt;
&lt;/blockquote&gt;</content><category term="Tutorials"/><category term="nextcloud"/><category term="docker"/><category term="docker compose"/><category term="self-hosted"/><category term="cloud storage"/><category term="homelab"/></entry><entry><title>Pi-hole + Unbound Docker Setup 2026: Recursive DNS for Privacy</title><link href="https://steadypub.com/2026/06/pihole-unbound-dns/" rel="alternate"/><published>2026-06-05T00:33:00+07:00</published><updated>2026-06-05T00:33:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/pihole-unbound-dns/</id><summary type="html">&lt;p&gt;Replace upstream &lt;span class="caps"&gt;DNS&lt;/span&gt; resolvers with Unbound for true recursive &lt;span class="caps"&gt;DNS&lt;/span&gt;. Complete Docker Compose setup with Pi-hole as the filter and Unbound as the root-resolving&amp;nbsp;engine.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~13 minutes&lt;br&gt;
&lt;strong&gt;Audience:&lt;/strong&gt; Privacy-focused homelab users who want to stop leaking &lt;span class="caps"&gt;DNS&lt;/span&gt; queries to Cloudflare or Google&lt;br&gt;
&lt;strong&gt;Last tested:&lt;/strong&gt; Pi-hole &lt;span class="caps"&gt;FTL&lt;/span&gt; v6.0, Unbound 1.22, June&amp;nbsp;2026&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why Add Unbound to&amp;nbsp;Pi-hole?&lt;/h2&gt;
&lt;h3&gt;The Privacy Gap in Standard&amp;nbsp;Pi-hole&lt;/h3&gt;
&lt;p&gt;By default, Pi-hole forwards filtered queries to upstream resolvers like Cloudflare&amp;nbsp;(&lt;code&gt;1.1.1.1&lt;/code&gt;), Quad9&amp;nbsp;(&lt;code&gt;9.9.9.9&lt;/code&gt;), or Google&amp;nbsp;(&lt;code&gt;8.8.8.8&lt;/code&gt;). While these are fast and reliable, they see every domain you visit. Even with &lt;span class="caps"&gt;DNS&lt;/span&gt;-over-&lt;span class="caps"&gt;HTTPS&lt;/span&gt; (DoH), you are trusting a third party with your browsing&amp;nbsp;metadata.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Unbound&lt;/strong&gt; is a validating, recursive, caching &lt;span class="caps"&gt;DNS&lt;/span&gt; resolver. Instead of asking Google &amp;#8220;what is example.com?&amp;#8221;, Unbound asks the root &lt;span class="caps"&gt;DNS&lt;/span&gt; servers, then&amp;nbsp;the &lt;code&gt;.com&lt;/code&gt; &lt;span class="caps"&gt;TLD&lt;/span&gt; servers, then the authoritative nameservers&amp;nbsp;for &lt;code&gt;example.com&lt;/code&gt;. No third party ever sees your full query&amp;nbsp;log.&lt;/p&gt;
&lt;h3&gt;Key&amp;nbsp;Benefits&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Pi-hole Only&lt;/th&gt;
&lt;th&gt;Pi-hole + Unbound&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ad blocking&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tracker blocking&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Recursive resolution&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Third-party &lt;span class="caps"&gt;DNS&lt;/span&gt; logs&lt;/td&gt;
&lt;td&gt;Yes (Cloudflare, etc.)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;DNSSEC&lt;/span&gt; validation&lt;/td&gt;
&lt;td&gt;Partial&lt;/td&gt;
&lt;td&gt;Full end-to-end&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Local caching&lt;/td&gt;
&lt;td&gt;Minimal&lt;/td&gt;
&lt;td&gt;Aggressive&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;h3&gt;Hardware&amp;nbsp;Requirements&lt;/h3&gt;
&lt;p&gt;Unbound requires slightly more &lt;span class="caps"&gt;RAM&lt;/span&gt; than forwarding to Cloudflare because it maintains a cache of &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;records:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Minimum&lt;/th&gt;
&lt;th&gt;Recommended&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;512 &lt;span class="caps"&gt;MB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1 core&lt;/td&gt;
&lt;td&gt;2 cores (for initial root server queries)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;8 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;16 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt; (for Unbound cache and logs)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Software&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Existing Pi-hole Docker deployment or willingness to deploy both&amp;nbsp;together&lt;/li&gt;
&lt;li&gt;Docker Engine and Docker Compose&amp;nbsp;plugin&lt;/li&gt;
&lt;li&gt;A static local &lt;span class="caps"&gt;IP&lt;/span&gt; for the &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;stack&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Deploy Unbound as a Separate&amp;nbsp;Container&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Create an Unbound container that Pi-hole will use as its sole upstream&amp;nbsp;resolver.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;If you already have Pi-hole running, create a new directory for&amp;nbsp;Unbound:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;~/unbound&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/unbound
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you are starting fresh, create a combined&amp;nbsp;stack:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;~/pihole-unbound&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/pihole-unbound
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Create &lt;code&gt;unbound.conf&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;cat&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;unbound.conf&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&amp;lt; &amp;#39;EOF&amp;#39;&lt;/span&gt;
&lt;span class="s"&gt;server:&lt;/span&gt;
&lt;span class="s"&gt;    verbosity: 0&lt;/span&gt;
&lt;span class="s"&gt;    num-threads: 2&lt;/span&gt;
&lt;span class="s"&gt;    interface: 0.0.0.0&lt;/span&gt;
&lt;span class="s"&gt;    port: 5335&lt;/span&gt;
&lt;span class="s"&gt;    do-ip4: yes&lt;/span&gt;
&lt;span class="s"&gt;    do-ip6: yes&lt;/span&gt;
&lt;span class="s"&gt;    do-udp: yes&lt;/span&gt;
&lt;span class="s"&gt;    do-tcp: yes&lt;/span&gt;
&lt;span class="s"&gt;    so-rcvbuf: 1m&lt;/span&gt;
&lt;span class="s"&gt;    so-sndbuf: 1m&lt;/span&gt;

&lt;span class="s"&gt;    harden-glue: yes&lt;/span&gt;
&lt;span class="s"&gt;    harden-dnssec-stripped: yes&lt;/span&gt;
&lt;span class="s"&gt;    harden-referral-path: yes&lt;/span&gt;
&lt;span class="s"&gt;    unwanted-reply-threshold: 10000&lt;/span&gt;
&lt;span class="s"&gt;    val-clean-additional: yes&lt;/span&gt;
&lt;span class="s"&gt;    edns-buffer-size: 1232&lt;/span&gt;
&lt;span class="s"&gt;    prefetch: yes&lt;/span&gt;
&lt;span class="s"&gt;    prefetch-key: yes&lt;/span&gt;
&lt;span class="s"&gt;    cache-min-ttl: 300&lt;/span&gt;
&lt;span class="s"&gt;    cache-max-ttl: 86400&lt;/span&gt;
&lt;span class="s"&gt;    msg-cache-slabs: 2&lt;/span&gt;
&lt;span class="s"&gt;    rrset-cache-slabs: 2&lt;/span&gt;
&lt;span class="s"&gt;    infra-cache-slabs: 2&lt;/span&gt;
&lt;span class="s"&gt;    key-cache-slabs: 2&lt;/span&gt;
&lt;span class="s"&gt;    rrset-cache-size: 64m&lt;/span&gt;
&lt;span class="s"&gt;    msg-cache-size: 32m&lt;/span&gt;
&lt;span class="s"&gt;    soa-cache-size: 128k&lt;/span&gt;
&lt;span class="s"&gt;    neg-cache-size: 128k&lt;/span&gt;

&lt;span class="s"&gt;    # Performance tuning&lt;/span&gt;
&lt;span class="s"&gt;    qname-minimisation: yes&lt;/span&gt;
&lt;span class="s"&gt;    qname-minimisation-strict: no&lt;/span&gt;
&lt;span class="s"&gt;    aggressive-nsec: yes&lt;/span&gt;
&lt;span class="s"&gt;    delay-close: 10000&lt;/span&gt;

&lt;span class="s"&gt;    # Private ranges (do not forward these)&lt;/span&gt;
&lt;span class="s"&gt;    private-address: 192.168.0.0/16&lt;/span&gt;
&lt;span class="s"&gt;    private-address: 169.254.0.0/16&lt;/span&gt;
&lt;span class="s"&gt;    private-address: 172.16.0.0/12&lt;/span&gt;
&lt;span class="s"&gt;    private-address: 10.0.0.0/8&lt;/span&gt;
&lt;span class="s"&gt;    private-address: fd00::/8&lt;/span&gt;
&lt;span class="s"&gt;    private-address: fe80::/10&lt;/span&gt;

&lt;span class="s"&gt;    # Root hints are built into the image; no extra config needed&lt;/span&gt;
&lt;span class="s"&gt;    auto-trust-anchor-file: &amp;quot;/var/lib/unbound/root.key&amp;quot;&lt;/span&gt;
&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Create &lt;code&gt;docker-compose.yml&lt;/code&gt; for the combined&amp;nbsp;stack:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;unbound&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unbound&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;mvance/unbound-rpi:latest&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Use mvance/unbound:latest for x86_64&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./unbound.conf:/etc/unbound/unbound.conf.d/custom.conf:ro&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;5335:5335/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;5335:5335/udp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;healthcheck&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;CMD&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;dig&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;@127.0.0.1&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-p&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;5335&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;dnssec-failed.org&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;30s&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;10s&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;retries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;3&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;pihole&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pihole&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pihole/pihole:2025.07.0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;53:53/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;53:53/udp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8080:80/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TZ=Europe/Berlin&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;WEBPASSWORD=changeme&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;FTLCONF_LOCAL_IPV4=192.168.1.10&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;PIHOLE_DNS_=unbound#5335&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Point to Unbound container&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./etc-pihole:/etc/pihole&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./etc-dnsmasq.d:/etc/dnsmasq.d&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;unbound&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;service_healthy&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;cap_add&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;NET_ADMIN&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;dns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;127.0.0.1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Image selection:&lt;/strong&gt;&amp;nbsp;Use &lt;code&gt;mvance/unbound:latest&lt;/code&gt; on Intel/&lt;span class="caps"&gt;AMD&lt;/span&gt;.&amp;nbsp;Use &lt;code&gt;mvance/unbound-rpi:latest&lt;/code&gt; on Raspberry Pi (&lt;span class="caps"&gt;ARM64&lt;/span&gt;). If those tags are&amp;nbsp;unavailable, &lt;code&gt;alpinelabs/unbound&lt;/code&gt; is a solid&amp;nbsp;alternative.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Create directories and&amp;nbsp;start:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;etc-pihole&lt;span class="w"&gt; &lt;/span&gt;etc-dnsmasq.d
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 2: Verify Recursive&amp;nbsp;Resolution&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Confirm that Unbound is resolving and Pi-hole is using&amp;nbsp;it.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Test Unbound&amp;nbsp;directly:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;dig&lt;span class="w"&gt; &lt;/span&gt;@127.0.0.1&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5335&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;wordforge.example.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You should&amp;nbsp;see &lt;code&gt;NOERROR&lt;/code&gt; and an &lt;span class="caps"&gt;IP&lt;/span&gt; address in&amp;nbsp;the &lt;code&gt;ANSWER SECTION&lt;/code&gt;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Test &lt;span class="caps"&gt;DNSSEC&lt;/span&gt; validation (Unbound should&amp;nbsp;return &lt;code&gt;SERVFAIL&lt;/code&gt; for broken&amp;nbsp;domains):&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;dig&lt;span class="w"&gt; &lt;/span&gt;@127.0.0.1&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5335&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;dnssec-failed.org
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Expected: &lt;code&gt;status: SERVFAIL&lt;/code&gt; — this confirms &lt;span class="caps"&gt;DNSSEC&lt;/span&gt; validation is&amp;nbsp;working.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Test through&amp;nbsp;Pi-hole:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;dig&lt;span class="w"&gt; &lt;/span&gt;@127.0.0.1&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;53&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;wordforge.example.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Check Pi-hole dashboard → &lt;strong&gt;Settings → &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Custom upstream should&amp;nbsp;show &lt;code&gt;unbound#5335&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;No other upstreams should be&amp;nbsp;listed&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Confirm no external resolvers are&amp;nbsp;used:&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;logs&lt;span class="w"&gt; &lt;/span&gt;pihole&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;forwarded&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You should&amp;nbsp;see &lt;code&gt;to unbound#5335&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 3: Tune Unbound&amp;nbsp;Performance&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Optimize cache sizes and thread counts for your&amp;nbsp;hardware.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;For low-power hosts (Raspberry Pi,&amp;nbsp;N100):&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Keep the default config above. It is already tuned for modest&amp;nbsp;hardware.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For dedicated servers with 4+ cores and 4+ &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Increase cache sizes&amp;nbsp;in &lt;code&gt;unbound.conf&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;num-threads: 4
rrset-cache-size: 256m
msg-cache-size: 128m
so-rcvbuf: 4m
so-sndbuf: 4m
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Restart&amp;nbsp;Unbound:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;restart&lt;span class="w"&gt; &lt;/span&gt;unbound
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Monitor cache hit&amp;nbsp;rate:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;unbound&lt;span class="w"&gt; &lt;/span&gt;unbound-control&lt;span class="w"&gt; &lt;/span&gt;stats_noreset&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;cache
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A hit rate above 70% is excellent for a home&amp;nbsp;network.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 4: Maintain and&amp;nbsp;Update&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Keep both services updated without losing&amp;nbsp;configuration.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Update both&amp;nbsp;containers:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/pihole-unbound
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;pull
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Clear Unbound cache if&amp;nbsp;needed:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;unbound&lt;span class="w"&gt; &lt;/span&gt;unbound-control&lt;span class="w"&gt; &lt;/span&gt;flush
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Backup your&amp;nbsp;configuration:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;tar&lt;span class="w"&gt; &lt;/span&gt;czf&lt;span class="w"&gt; &lt;/span&gt;pihole-unbound-backup-&lt;span class="k"&gt;$(&lt;/span&gt;date&lt;span class="w"&gt; &lt;/span&gt;+%Y%m%d&lt;span class="k"&gt;)&lt;/span&gt;.tar.gz&lt;span class="w"&gt; &lt;/span&gt;etc-pihole&lt;span class="w"&gt; &lt;/span&gt;etc-dnsmasq.d&lt;span class="w"&gt; &lt;/span&gt;unbound.conf&lt;span class="w"&gt; &lt;/span&gt;docker-compose.yml&lt;span class="w"&gt; &lt;/span&gt;.env
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Add &lt;span class="caps"&gt;DNS&lt;/span&gt;-over-&lt;span class="caps"&gt;TLS&lt;/span&gt; for External&amp;nbsp;Queries&lt;/h3&gt;
&lt;p&gt;If you occasionally need to query an external resolver (e.g., for GeoCDN accuracy), configure Unbound to forward specific zones over &lt;span class="caps"&gt;TLS&lt;/span&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;forward&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;zone&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;.&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;forward&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.1.1.1&lt;/span&gt;&lt;span class="mi"&gt;@853&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;cloudflare&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;forward&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ssl&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;upstream&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This hybrid mode uses Unbound for recursion but encrypts the final&amp;nbsp;hop.&lt;/p&gt;
&lt;h3&gt;Tip 2: Split-Horizon &lt;span class="caps"&gt;DNS&lt;/span&gt; for&amp;nbsp;Homelab&lt;/h3&gt;
&lt;p&gt;Unbound can serve local records without Pi-hole&amp;#8217;s&amp;nbsp;involvement:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;local-zone: &amp;quot;lan.&amp;quot; static
local-data: &amp;quot;proxmox.lan. IN A 192.168.1.5&amp;quot;
local-data: &amp;quot;nas.lan. IN A 192.168.1.20&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Restart Unbound and&amp;nbsp;query: &lt;code&gt;dig @192.168.1.10 -p 5335 proxmox.lan&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;Tip 3: Reduce &lt;span class="caps"&gt;TTL&lt;/span&gt; for Faster Blocklist&amp;nbsp;Updates&lt;/h3&gt;
&lt;p&gt;When you add a new blocklist to Pi-hole, old cached records may persist. Lower&amp;nbsp;Unbound&amp;#8217;s &lt;code&gt;cache-min-ttl&lt;/code&gt; to &lt;code&gt;60&lt;/code&gt; seconds temporarily, then raise it back&amp;nbsp;to &lt;code&gt;300&lt;/code&gt; after Gravity&amp;nbsp;updates.&lt;/p&gt;
&lt;h3&gt;Tip 4: Run on a Separate &lt;span class="caps"&gt;VLAN&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;For network segmentation, place Pi-hole + Unbound on a dedicated management &lt;span class="caps"&gt;VLAN&lt;/span&gt; (e.g., &lt;span class="caps"&gt;VLAN&lt;/span&gt; 10). Ensure your router allows &lt;span class="caps"&gt;UDP&lt;/span&gt;/&lt;span class="caps"&gt;TCP&lt;/span&gt; 53 from all client VLANs to the &lt;span class="caps"&gt;DNS&lt;/span&gt; &lt;span class="caps"&gt;VLAN&lt;/span&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Troubleshooting Common&amp;nbsp;Issues&lt;/h2&gt;
&lt;h3&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;connection refused&amp;#8221; on Port&amp;nbsp;5335&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Unbound container may not be fully started. Check&amp;nbsp;logs:
  &lt;code&gt;bash
  docker compose logs unbound&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Ensure no other service is using port 5335 on the&amp;nbsp;host.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Slow Initial&amp;nbsp;Resolution&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Unbound must populate its cache from root servers. The first query to any domain is slower (~200–500 ms) than Cloudflare (~20 ms). Subsequent queries are cached and typically faster than external&amp;nbsp;resolvers.&lt;/li&gt;
&lt;li&gt;This is normal and improves dramatically after 24 hours of&amp;nbsp;use.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;Server Failed&amp;#8221; for All&amp;nbsp;Queries&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Check&amp;nbsp;that &lt;code&gt;auto-trust-anchor-file&lt;/code&gt; is generating&amp;nbsp;correctly:
  &lt;code&gt;bash
  docker exec unbound ls -la /var/lib/unbound/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;If &lt;code&gt;root.key&lt;/code&gt; is missing, generate it&amp;nbsp;manually:
  &lt;code&gt;bash
  docker exec unbound unbound-anchor -a /var/lib/unbound/root.key
  docker compose restart unbound&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;You now have a privacy-first &lt;span class="caps"&gt;DNS&lt;/span&gt; stack: Pi-hole filters ads and trackers, while Unbound performs recursive resolution without leaking your browsing history to upstream providers. Your network enjoys faster cached &lt;span class="caps"&gt;DNS&lt;/span&gt;, end-to-end &lt;span class="caps"&gt;DNSSEC&lt;/span&gt; validation, and complete query&amp;nbsp;autonomy.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/adguard-home-vs-pihole-unbound"&gt;Compare Pi-hole + Unbound vs AdGuard&amp;nbsp;Home&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/dns-over-https-homelab"&gt;Add &lt;span class="caps"&gt;DNS&lt;/span&gt;-over-&lt;span class="caps"&gt;HTTPS&lt;/span&gt; for encrypted client&amp;nbsp;queries&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/pihole-ha-redundancy"&gt;Set up a secondary Pi-hole for&amp;nbsp;redundancy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/grafana-loki-logs"&gt;Monitor &lt;span class="caps"&gt;DNS&lt;/span&gt; query patterns with&amp;nbsp;Grafana&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Raspberry Pi:&lt;/strong&gt; Pi 4/5 with PoE &lt;span class="caps"&gt;HAT&lt;/span&gt; for always-on &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;SSD&lt;/span&gt;:&lt;/strong&gt; Small 32 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt; for Pi-hole + Unbound persistent&amp;nbsp;storage&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;UPS&lt;/span&gt;:&lt;/strong&gt; &lt;span class="caps"&gt;APC&lt;/span&gt; unit to maintain &lt;span class="caps"&gt;DNS&lt;/span&gt; during&amp;nbsp;outages&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;what-is&lt;/code&gt; → &lt;code&gt;/homelab-ad-blocking-pihole&lt;/code&gt; for readers starting from&amp;nbsp;scratch&lt;/li&gt;
&lt;li&gt;&lt;code&gt;router&lt;/code&gt; → &lt;code&gt;/homelab-networking-basics&lt;/code&gt; for &lt;span class="caps"&gt;VLAN&lt;/span&gt; and subnet&amp;nbsp;guidance&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;/adguard-home-docker&lt;/code&gt; for readers comparing &lt;span class="caps"&gt;DNS&lt;/span&gt; filter&amp;nbsp;options&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Are you running recursive &lt;span class="caps"&gt;DNS&lt;/span&gt; at home?&lt;/strong&gt; Share your block rate and cache hit percentage in the&amp;nbsp;comments!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Subscribe to the WordForge newsletter&lt;/strong&gt; for weekly homelab privacy and networking deep&amp;nbsp;dives.&lt;/p&gt;
&lt;/blockquote&gt;</content><category term="Tutorials"/><category term="pihole"/><category term="unbound"/><category term="dns"/><category term="privacy"/><category term="docker"/><category term="recursive dns"/><category term="homelab"/></entry><entry><title>Portainer Setup Guide 2026: Visual Docker Management for Homelabs</title><link href="https://steadypub.com/2026/06/portainer-setup-guide/" rel="alternate"/><published>2026-06-05T00:33:00+07:00</published><updated>2026-06-05T00:33:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/portainer-setup-guide/</id><summary type="html">&lt;p&gt;Install Portainer &lt;span class="caps"&gt;CE&lt;/span&gt; on Docker Compose in under 10 minutes. Manage containers, stacks, volumes, and networks through a clean web &lt;span class="caps"&gt;UI&lt;/span&gt; instead of memorizing &lt;span class="caps"&gt;CLI&lt;/span&gt;&amp;nbsp;commands.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~10 minutes&lt;br&gt;
&lt;strong&gt;Audience:&lt;/strong&gt; Docker users who prefer GUIs over terminal commands&lt;br&gt;
&lt;strong&gt;Last tested:&lt;/strong&gt; Portainer &lt;span class="caps"&gt;CE&lt;/span&gt; 2.25, June&amp;nbsp;2026&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is&amp;nbsp;Portainer?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Portainer Community Edition (&lt;span class="caps"&gt;CE&lt;/span&gt;) is a lightweight web-based management interface for Docker, Docker Swarm, and Kubernetes. It translates every Docker operation — starting containers, inspecting logs, managing volumes, editing Compose files — into clickable buttons and&amp;nbsp;forms.&lt;/p&gt;
&lt;p&gt;For homelab users, Portainer eliminates the need to &lt;span class="caps"&gt;SSH&lt;/span&gt; into your server every time you want to check a container log or update an image. It also provides a built-in stack editor with Git integration, making it ideal for managing 10–50 self-hosted&amp;nbsp;applications.&lt;/p&gt;
&lt;h3&gt;Key&amp;nbsp;Benefits&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Portainer&lt;/th&gt;
&lt;th&gt;Docker &lt;span class="caps"&gt;CLI&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Start/stop containers&lt;/td&gt;
&lt;td&gt;One click&lt;/td&gt;
&lt;td&gt;&lt;code&gt;docker start/stop&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;View logs&lt;/td&gt;
&lt;td&gt;Real-time web stream&lt;/td&gt;
&lt;td&gt;&lt;code&gt;docker logs -f&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Edit Compose stacks&lt;/td&gt;
&lt;td&gt;In-browser &lt;span class="caps"&gt;YAML&lt;/span&gt; editor + redeploy&lt;/td&gt;
&lt;td&gt;Edit file + &lt;span class="caps"&gt;CLI&lt;/span&gt; commands&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Browse container files&lt;/td&gt;
&lt;td&gt;Web file manager&lt;/td&gt;
&lt;td&gt;&lt;code&gt;docker exec -it ... bash&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-host management&lt;/td&gt;
&lt;td&gt;Single &lt;span class="caps"&gt;UI&lt;/span&gt; for multiple nodes&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;SSH&lt;/span&gt; to each host&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;App templates&lt;/td&gt;
&lt;td&gt;50+ one-click app templates&lt;/td&gt;
&lt;td&gt;Manual &lt;code&gt;docker compose up&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Portainer &lt;span class="caps"&gt;CE&lt;/span&gt; vs Portainer Business (&lt;span class="caps"&gt;BE&lt;/span&gt;)&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Capability&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;CE&lt;/span&gt; (Free)&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;BE&lt;/span&gt; (Paid)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Container management&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stack editing&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-environment&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Unlimited&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RBAC&lt;/span&gt; / Teams&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Registry management&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For single-user homelabs, &lt;span class="caps"&gt;CE&lt;/span&gt; provides everything you&amp;nbsp;need.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;h3&gt;Hardware&amp;nbsp;Requirements&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Minimum&lt;/th&gt;
&lt;th&gt;Recommended&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Any x86_64 or &lt;span class="caps"&gt;ARM64&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;2 cores&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;512 &lt;span class="caps"&gt;MB&lt;/span&gt; for Portainer itself&lt;/td&gt;
&lt;td&gt;2 &lt;span class="caps"&gt;GB&lt;/span&gt; total for host&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;10 &lt;span class="caps"&gt;MB&lt;/span&gt; for Portainer image&lt;/td&gt;
&lt;td&gt;20 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt; for host&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network&lt;/td&gt;
&lt;td&gt;Same subnet as your client&lt;/td&gt;
&lt;td&gt;Static &lt;span class="caps"&gt;IP&lt;/span&gt; preferred&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Software&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Docker Engine 24.0+ with Docker Compose&amp;nbsp;plugin&lt;/li&gt;
&lt;li&gt;A Linux host (Ubuntu, Debian, Proxmox &lt;span class="caps"&gt;LXC&lt;/span&gt;, Raspberry Pi &lt;span class="caps"&gt;OS&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;The host must have internet access to pull&amp;nbsp;images&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Create the Portainer Data&amp;nbsp;Volume&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Prepare persistent storage so Portainer settings survive&amp;nbsp;updates.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;span class="caps"&gt;SSH&lt;/span&gt; into your Docker&amp;nbsp;host.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a dedicated Docker&amp;nbsp;volume:&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;volume&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;portainer_data
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Verify it&amp;nbsp;exists:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;volume&lt;span class="w"&gt; &lt;/span&gt;ls
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Why a named volume?&lt;/strong&gt; Portainer stores user accounts, endpoint configurations, and stack definitions&amp;nbsp;in &lt;code&gt;/data&lt;/code&gt;. A named volume persists this across image updates. Bind mounts work too, but named volumes are cleaner for single-file&amp;nbsp;databases.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;Step 2: Deploy Portainer via Docker&amp;nbsp;Compose&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Launch Portainer &lt;span class="caps"&gt;CE&lt;/span&gt; with a simple, maintainable Compose&amp;nbsp;file.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Create a directory for&amp;nbsp;Portainer:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;~/portainer&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/portainer
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Create &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;portainer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;portainer/portainer-ce:2.25-alpine&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;portainer&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;security_opt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;no-new-privileges:true&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/etc/localtime:/etc/localtime:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/var/run/docker.sock:/var/run/docker.sock:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;portainer_data:/data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;9000:9000&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8000:8000&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Only needed for Edge Agent setups&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;portainer_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Start the&amp;nbsp;container:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Check that it is&amp;nbsp;running:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;ps
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;logs&lt;span class="w"&gt; &lt;/span&gt;-f
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You should&amp;nbsp;see &lt;code&gt;portainer&lt;/code&gt; in&amp;nbsp;an &lt;code&gt;Up&lt;/code&gt; state.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Security Note:&lt;/strong&gt;&amp;nbsp;Mounting &lt;code&gt;/var/run/docker.sock&lt;/code&gt; gives Portainer full control over Docker on the host. This is necessary for its functionality but means you should &lt;strong&gt;not&lt;/strong&gt; expose Portainer to the public internet without &lt;span class="caps"&gt;HTTPS&lt;/span&gt; + strong&amp;nbsp;authentication.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;Step 3: Initial Configuration and Connecting the&amp;nbsp;Environment&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Complete the first-run wizard and connect Portainer to your local Docker&amp;nbsp;socket.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Open your browser and navigate&amp;nbsp;to:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;http://your-server-ip:9000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;You will see the &lt;strong&gt;&amp;#8220;Create the first administrator user&amp;#8221;&lt;/strong&gt;&amp;nbsp;screen.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Username:&lt;/strong&gt; Choose something memorable&amp;nbsp;(e.g., &lt;code&gt;admin&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Password:&lt;/strong&gt; Use a strong, unique password (16+&amp;nbsp;characters)&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Confirm password:&lt;/strong&gt; Re-enter&amp;nbsp;it&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click &lt;strong&gt;&amp;#8220;Create user&amp;#8221;&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;On the &lt;strong&gt;&amp;#8220;Environment Wizard&amp;#8221;&lt;/strong&gt; screen, select &lt;strong&gt;&amp;#8220;Get Started&amp;#8221;&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Choose &lt;strong&gt;&amp;#8220;Docker&amp;#8221;&lt;/strong&gt; as the environment type, then &lt;strong&gt;&amp;#8220;Start Wizard&amp;#8221;&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Select &lt;strong&gt;&amp;#8220;Docker environment&amp;#8221;&lt;/strong&gt; and click &lt;strong&gt;&amp;#8220;Connect&amp;#8221;&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Portainer will detect the local Docker socket and import all existing containers, volumes, networks, and&amp;nbsp;images.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 4: Exploring the Portainer&amp;nbsp;Interface&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Learn the main sections and where to find critical&amp;nbsp;functions.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Left sidebar&amp;nbsp;navigation:&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Menu Item&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dashboard&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Overview of running/stopped containers, &lt;span class="caps"&gt;CPU&lt;/span&gt;, &lt;span class="caps"&gt;RAM&lt;/span&gt;, and network usage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;App Templates&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;One-click installers for common apps (&lt;span class="caps"&gt;NGINX&lt;/span&gt;, MySQL, WordPress, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Stacks&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;View and edit Docker Compose stacks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Containers&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Start, stop, kill, pause, resume, inspect, view logs, access console&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Images&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Pull, build, remove, and inspect Docker images&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Networks&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manage bridge, overlay, and custom networks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Volumes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Create, inspect, and delete named volumes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Events&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Real-time Docker daemon event stream&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Host&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;View disk usage, running processes, and system info&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Key actions to&amp;nbsp;try:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;View logs:&lt;/strong&gt; Click any container → &lt;strong&gt;Logs&lt;/strong&gt; tab. Use the search box to&amp;nbsp;filter.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Access console:&lt;/strong&gt; Click any container → &lt;strong&gt;Console&lt;/strong&gt; tab →&amp;nbsp;Choose &lt;code&gt;/bin/bash&lt;/code&gt; or &lt;code&gt;/bin/sh&lt;/code&gt; → &lt;strong&gt;Connect&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Inspect a container:&lt;/strong&gt; Click any container → &lt;strong&gt;Inspect&lt;/strong&gt; tab to see the raw &lt;span class="caps"&gt;JSON&lt;/span&gt; Docker&amp;nbsp;config.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Edit a running container:&lt;/strong&gt; You cannot directly edit a running container&amp;#8217;s config, but you can &lt;strong&gt;Duplicate/Edit&lt;/strong&gt; to clone it with&amp;nbsp;changes.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Step 5: Deploying a Stack from the Web&amp;nbsp;Editor&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Use Portainer&amp;#8217;s built-in editor to deploy a multi-container application without touching the&amp;nbsp;terminal.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;In Portainer, click &lt;strong&gt;Stacks → Add stack&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Name the&amp;nbsp;stack: &lt;code&gt;whoami-demo&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;In the &lt;strong&gt;Web editor&lt;/strong&gt;,&amp;nbsp;paste:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;whoami&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;traefik/whoami&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;whoami-web&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8080:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Click &lt;strong&gt;Deploy the stack&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Navigate to &lt;strong&gt;Containers&lt;/strong&gt;. You will&amp;nbsp;see &lt;code&gt;whoami-web&lt;/code&gt; running.&lt;/li&gt;
&lt;li&gt;Visit &lt;code&gt;http://your-server-ip:8080&lt;/code&gt; to confirm it&amp;nbsp;responds.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;To update a stack:&lt;/strong&gt;
1. Go to &lt;strong&gt;Stacks → whoami-demo → Editor&lt;/strong&gt;.
2. Make changes (e.g., change the image tag).
3. Click &lt;strong&gt;Update the stack → Pull latest images&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Use Portainer with a Reverse&amp;nbsp;Proxy&lt;/h3&gt;
&lt;p&gt;Do not expose Portainer on port 9000 directly to the internet. Put it behind &lt;span class="caps"&gt;NGINX&lt;/span&gt; Proxy Manager or&amp;nbsp;Traefik:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# In your reverse proxy stack&lt;/span&gt;
&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;nginx-proxy-manager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;jc21/nginx-proxy-manager:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;80:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;443:443&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;81:81&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Add a Proxy Host in the NPM UI:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Domain: portainer.yourdomain.com&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Forward Host: portainer&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Forward Port: 9000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 2: Back Up Portainer&amp;nbsp;Data&lt;/h3&gt;
&lt;p&gt;The entire Portainer state lives in&amp;nbsp;the &lt;code&gt;portainer_data&lt;/code&gt; volume. Back it up&amp;nbsp;with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;--rm&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;portainer_data:/data&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;:/backup&lt;span class="w"&gt; &lt;/span&gt;alpine&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;tar&lt;span class="w"&gt; &lt;/span&gt;czf&lt;span class="w"&gt; &lt;/span&gt;/backup/portainer-backup.tar.gz&lt;span class="w"&gt; &lt;/span&gt;-C&lt;span class="w"&gt; &lt;/span&gt;/data&lt;span class="w"&gt; &lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 3: Enable Dark&amp;nbsp;Mode&lt;/h3&gt;
&lt;p&gt;Go to &lt;strong&gt;My account → Theme → Dark&lt;/strong&gt;. Portainer&amp;#8217;s light theme is blinding at 2 &lt;span class="caps"&gt;AM&lt;/span&gt; during a homelab debug&amp;nbsp;session.&lt;/p&gt;
&lt;h3&gt;Tip 4: Use Git Repositories for&amp;nbsp;Stacks&lt;/h3&gt;
&lt;p&gt;Instead of editing in the browser, connect Portainer to a Git repo:
1. &lt;strong&gt;Stacks → Add stack → Repository&lt;/strong&gt;
2. Enter your Git &lt;span class="caps"&gt;URL&lt;/span&gt;, branch, and Compose file path
3. Enable &lt;strong&gt;Authentication&lt;/strong&gt; if the repo is private
4. Enable &lt;strong&gt;Automatic updates&lt;/strong&gt; to poll for changes every X&amp;nbsp;minutes&lt;/p&gt;
&lt;p&gt;This turns Portainer into a lightweight GitOps controller for your&amp;nbsp;homelab.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Troubleshooting Common&amp;nbsp;Issues&lt;/h2&gt;
&lt;h3&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;Cannot connect to the Docker&amp;nbsp;daemon&amp;#8221;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Verify the Docker service is&amp;nbsp;running: &lt;code&gt;sudo systemctl status docker&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Ensure &lt;code&gt;/var/run/docker.sock&lt;/code&gt; exists on the&amp;nbsp;host&lt;/li&gt;
&lt;li&gt;If running in &lt;span class="caps"&gt;LXC&lt;/span&gt;, ensure the container is &lt;strong&gt;privileged&lt;/strong&gt; or&amp;nbsp;has &lt;code&gt;nesting=1&lt;/code&gt; and &lt;code&gt;keyctl=1&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Forgotten Admin&amp;nbsp;Password&lt;/h3&gt;
&lt;p&gt;If you locked yourself out, reset via &lt;span class="caps"&gt;CLI&lt;/span&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;stop&lt;span class="w"&gt; &lt;/span&gt;portainer
docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;--rm&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;portainer_data:/data&lt;span class="w"&gt; &lt;/span&gt;portainer/portainer-ce:2.25-alpine&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--admin-reset-password
&lt;span class="c1"&gt;# Follow prompts, then restart Portainer&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;portainer
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;High Memory&amp;nbsp;Usage&lt;/h3&gt;
&lt;p&gt;Portainer itself uses ~50–100 &lt;span class="caps"&gt;MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;. If memory spikes, it is likely due to a large number of images or containers. Prune unused images in &lt;strong&gt;Images → Prune&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;You now have Portainer &lt;span class="caps"&gt;CE&lt;/span&gt; running as a web &lt;span class="caps"&gt;UI&lt;/span&gt; for your Docker host. You can inspect logs, manage containers, deploy stacks from a browser, and even connect Git repositories for automatic&amp;nbsp;deployments.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/nextcloud-docker-compose"&gt;Deploy Nextcloud via Portainer Stack&amp;nbsp;Editor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/portainer-vs-cockpit"&gt;Compare Portainer vs Cockpit&lt;/a&gt; for full-system&amp;nbsp;management&lt;/li&gt;
&lt;li&gt;&lt;a href="/nginx-proxy-manager-docker"&gt;Set up &lt;span class="caps"&gt;NGINX&lt;/span&gt; Proxy Manager&lt;/a&gt; for clean local&amp;nbsp;domains&lt;/li&gt;
&lt;li&gt;&lt;a href="/docker-monitoring-grafana-prometheus"&gt;Monitor your containers with Grafana and&amp;nbsp;Prometheus&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mini PCs:&lt;/strong&gt; Compact Docker hosts (Intel N100, Beelink &lt;span class="caps"&gt;SER5&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Monitors:&lt;/strong&gt; A small touchscreen display mounted near your server rack for quick Portainer&amp;nbsp;checks&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;UPS&lt;/span&gt;:&lt;/strong&gt; Keep Portainer accessible during power&amp;nbsp;flickers&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;what-is&lt;/code&gt; → &lt;code&gt;/docker-compose-for-beginners&lt;/code&gt; for readers new to&amp;nbsp;Docker&lt;/li&gt;
&lt;li&gt;&lt;code&gt;stack-editor&lt;/code&gt; → &lt;code&gt;/nextcloud-docker-compose&lt;/code&gt; for a real-world Compose&amp;nbsp;example&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;/portainer-vs-cockpit&lt;/code&gt; to compare container vs system management&amp;nbsp;tools&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What apps are you managing with Portainer?&lt;/strong&gt; Share your stack in the&amp;nbsp;comments!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Subscribe to the WordForge newsletter&lt;/strong&gt; for weekly self-hosting guides and Docker&amp;nbsp;tips.&lt;/p&gt;
&lt;/blockquote&gt;</content><category term="Tutorials"/><category term="portainer"/><category term="docker"/><category term="homelab"/><category term="self-hosted"/><category term="container management"/></entry><entry><title>Proxmox Beginner Guide 2026: From Zero to Your First VM</title><link href="https://steadypub.com/2026/06/proxmox-beginner-guide/" rel="alternate"/><published>2026-06-05T00:33:00+07:00</published><updated>2026-06-05T00:33:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/proxmox-beginner-guide/</id><summary type="html">&lt;p&gt;A complete beginner&amp;#8217;s guide to Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; 8.2. Learn installation, web &lt;span class="caps"&gt;UI&lt;/span&gt; navigation, storage setup, and how to create your first virtual machine in under 45&amp;nbsp;minutes.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~18 minutes&lt;br&gt;
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab beginners migrating from bare-metal or cloud VMs&lt;br&gt;
&lt;strong&gt;Last tested:&lt;/strong&gt; Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; 8.2, June&amp;nbsp;2026&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;If you are new to homelab and want to run multiple operating systems on one machine, Proxmox Virtual Environment (&lt;span class="caps"&gt;VE&lt;/span&gt;) is the best place to start in 2026. It is free, open-source, and built on Debian Linux. Unlike VMware ESXi — which killed its free tier after the Broadcom acquisition — Proxmox gives you full features without a license&amp;nbsp;key.&lt;/p&gt;
&lt;p&gt;Proxmox Virtual Environment (&lt;span class="caps"&gt;VE&lt;/span&gt;) is an open-source Type-1 hypervisor based on Debian Linux. It combines two virtualization technologies in a single web interface: &lt;strong&gt;&lt;span class="caps"&gt;KVM&lt;/span&gt;&lt;/strong&gt; for full virtual machines (VMs) and &lt;strong&gt;&lt;span class="caps"&gt;LXC&lt;/span&gt;&lt;/strong&gt; for lightweight Linux containers. Unlike VMware ESXi or Microsoft Hyper-V, Proxmox is completely free for homelab use without artificial feature limits, and it includes enterprise-grade features like software-defined storage (Ceph, &lt;span class="caps"&gt;ZFS&lt;/span&gt;), live migration, and backup scheduling out of the&amp;nbsp;box.&lt;/p&gt;
&lt;h3&gt;Key Benefits for Homelab&amp;nbsp;Users&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Typical Consumer &lt;span class="caps"&gt;NAS&lt;/span&gt; / Cloud&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cost&lt;/td&gt;
&lt;td&gt;Free (subscription optional)&lt;/td&gt;
&lt;td&gt;$100–500/year or hardware lock-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Virtualization&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;KVM&lt;/span&gt; + &lt;span class="caps"&gt;LXC&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Often none or Docker-only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;ZFS&lt;/span&gt;, Ceph, &lt;span class="caps"&gt;LVM&lt;/span&gt;, &lt;span class="caps"&gt;NFS&lt;/span&gt;, iSCSI&lt;/td&gt;
&lt;td&gt;Proprietary &lt;span class="caps"&gt;RAID&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backup&lt;/td&gt;
&lt;td&gt;Built-in vzdump + scheduler&lt;/td&gt;
&lt;td&gt;Manual or paid add-on&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hardware choice&lt;/td&gt;
&lt;td&gt;Any x86_64 server/&lt;span class="caps"&gt;PC&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Vendor-locked&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Learning curve&lt;/td&gt;
&lt;td&gt;Moderate&lt;/td&gt;
&lt;td&gt;Low, but less capable&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;h3&gt;Minimum Hardware&amp;nbsp;Requirements&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Minimum&lt;/th&gt;
&lt;th&gt;Recommended for 3+ VMs&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;64-bit dual-core&lt;/td&gt;
&lt;td&gt;4c/8t Intel or &lt;span class="caps"&gt;AMD&lt;/span&gt;, &lt;span class="caps"&gt;ECC&lt;/span&gt; optional&lt;/td&gt;
&lt;td&gt;More cores = more concurrent VMs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;4 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;16–32 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;DDR4&lt;/span&gt;/&lt;span class="caps"&gt;DDR5&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Plan 2–4 &lt;span class="caps"&gt;GB&lt;/span&gt; per &lt;span class="caps"&gt;VM&lt;/span&gt; + 2 &lt;span class="caps"&gt;GB&lt;/span&gt; for host&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;32 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;256 &lt;span class="caps"&gt;GB&lt;/span&gt; NVMe + &lt;span class="caps"&gt;HDD&lt;/span&gt; for backups&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;ZFS&lt;/span&gt; loves fast drives; avoid &lt;span class="caps"&gt;SMR&lt;/span&gt; HDDs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network&lt;/td&gt;
&lt;td&gt;1 GbE&lt;/td&gt;
&lt;td&gt;2× 1 GbE or 10 GbE&lt;/td&gt;
&lt;td&gt;Wi-Fi is unsupported for the host&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;USB&lt;/span&gt; port&lt;/td&gt;
&lt;td&gt;1 (for installer)&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Real-world beginner builds in&amp;nbsp;2026:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Budget:&lt;/strong&gt; Old Dell OptiPlex or &lt;span class="caps"&gt;HP&lt;/span&gt; EliteDesk (6th–8th gen Intel), 16 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, 256 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;SATA&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sweet spot:&lt;/strong&gt; Intel N100 or N305 mini &lt;span class="caps"&gt;PC&lt;/span&gt;, 32 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;DDR5&lt;/span&gt;, 512 &lt;span class="caps"&gt;GB&lt;/span&gt;&amp;nbsp;NVMe&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enthusiast:&lt;/strong&gt; Used Dell PowerEdge R620/R720 or &lt;span class="caps"&gt;HP&lt;/span&gt; ProLiant DL380p, dual Xeon, 64–128 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;ECC&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The Intel N100 has become the most popular entry point in 2026. It draws under 15W at idle, costs around $150–$200 for a barebones unit, and handles 3–4 lightweight VMs without issue. Models from Beelink, GMKtec, and Minisforum are well-tested in the&amp;nbsp;community.&lt;/p&gt;
&lt;h3&gt;&lt;span class="caps"&gt;BIOS&lt;/span&gt;/&lt;span class="caps"&gt;UEFI&lt;/span&gt; Settings to Check Before&amp;nbsp;Installing&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Enable Intel &lt;span class="caps"&gt;VT&lt;/span&gt;-x / &lt;span class="caps"&gt;AMD&lt;/span&gt;-V&lt;/strong&gt; (virtualization&amp;nbsp;extensions)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enable Intel &lt;span class="caps"&gt;VT&lt;/span&gt;-d / &lt;span class="caps"&gt;AMD&lt;/span&gt;-Vi&lt;/strong&gt; (&lt;span class="caps"&gt;IOMMU&lt;/span&gt;) if you plan &lt;span class="caps"&gt;GPU&lt;/span&gt; passthrough&amp;nbsp;later&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Disable Secure Boot&lt;/strong&gt; — Proxmox does not ship with a signed&amp;nbsp;bootloader&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Set boot order&lt;/strong&gt; to &lt;span class="caps"&gt;USB&lt;/span&gt;&amp;nbsp;first&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Software&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; 8.2 &lt;span class="caps"&gt;ISO&lt;/span&gt; (&lt;a href="https://www.proxmox.com/en/downloads/proxmox-virtual-environment/iso"&gt;download&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;BalenaEtcher, Rufus,&amp;nbsp;or &lt;code&gt;dd&lt;/code&gt; to write the &lt;span class="caps"&gt;ISO&lt;/span&gt; to a &lt;span class="caps"&gt;USB&lt;/span&gt; drive (8 &lt;span class="caps"&gt;GB&lt;/span&gt;+)&lt;/li&gt;
&lt;li&gt;A second computer or smartphone to access the web &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Download and Create Bootable&amp;nbsp;Media&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Prepare a bootable &lt;span class="caps"&gt;USB&lt;/span&gt; drive with the Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;&amp;nbsp;installer.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Download the latest Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; 8.2 &lt;span class="caps"&gt;ISO&lt;/span&gt; from the official website. Verify the &lt;span class="caps"&gt;SHA256&lt;/span&gt; checksum if you are&amp;nbsp;security-conscious.&lt;/li&gt;
&lt;li&gt;Insert your &lt;span class="caps"&gt;USB&lt;/span&gt; drive. &lt;strong&gt;All data on it will be&amp;nbsp;erased.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Flash the &lt;span class="caps"&gt;ISO&lt;/span&gt; using your preferred&amp;nbsp;tool:&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Linux/macOS:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;dd&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;proxmox-ve_8.2-1.iso&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/sdX&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4M&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;progress&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;conv&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;fsync
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Replace &lt;code&gt;/dev/sdX&lt;/code&gt; with your actual &lt;span class="caps"&gt;USB&lt;/span&gt; device (check&amp;nbsp;with &lt;code&gt;lsblk&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Windows:&lt;/strong&gt;
Use Rufus in &amp;#8220;&lt;span class="caps"&gt;DD&lt;/span&gt; mode&amp;#8221; or&amp;nbsp;BalenaEtcher.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Safely eject the &lt;span class="caps"&gt;USB&lt;/span&gt; and insert it into your target&amp;nbsp;server.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Step 2: Install Proxmox on Your&amp;nbsp;Hardware&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Run the graphical installer and configure&amp;nbsp;networking.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Power on the server and boot from the &lt;span class="caps"&gt;USB&lt;/span&gt;&amp;nbsp;drive.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;&amp;#8220;Install Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; (Graphical)&amp;#8221;&lt;/strong&gt; from the &lt;span class="caps"&gt;GRUB&lt;/span&gt;&amp;nbsp;menu.&lt;/li&gt;
&lt;li&gt;Accept the &lt;span class="caps"&gt;EULA&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;Choose your target disk. If you have multiple&amp;nbsp;disks:&lt;/li&gt;
&lt;li&gt;Install Proxmox on your smallest/fastest &lt;span class="caps"&gt;SSD&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;Leave larger HDDs untouched for now; we will add them as storage&amp;nbsp;later.&lt;/li&gt;
&lt;li&gt;Select your &lt;strong&gt;country, timezone, and keyboard layout&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Set a strong &lt;strong&gt;root password&lt;/strong&gt; and enter an email address for system&amp;nbsp;notifications.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Network configuration&lt;/strong&gt; — this is&amp;nbsp;critical:&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Management interface:&lt;/strong&gt; Select your primary &lt;span class="caps"&gt;NIC&lt;/span&gt;&amp;nbsp;(e.g., &lt;code&gt;enp3s0&lt;/code&gt; or &lt;code&gt;eth0&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hostname:&lt;/strong&gt; Use a fully qualified domain name (&lt;span class="caps"&gt;FQDN&lt;/span&gt;)&amp;nbsp;like &lt;code&gt;pve.lan&lt;/code&gt; or &lt;code&gt;pve.home.arpa&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;IP&lt;/span&gt; address:&lt;/strong&gt; Assign a static &lt;span class="caps"&gt;IP&lt;/span&gt; outside your router&amp;#8217;s &lt;span class="caps"&gt;DHCP&lt;/span&gt; pool,&amp;nbsp;e.g., &lt;code&gt;192.168.1.10/24&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Gateway:&lt;/strong&gt; Your router&amp;#8217;s &lt;span class="caps"&gt;IP&lt;/span&gt;&amp;nbsp;(e.g., &lt;code&gt;192.168.1.1&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt;:&lt;/strong&gt; &lt;code&gt;1.1.1.1&lt;/code&gt; or your router&amp;#8217;s &lt;span class="caps"&gt;IP&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;Review the summary and click &lt;strong&gt;Install&lt;/strong&gt;. The system will reboot&amp;nbsp;automatically.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pro Tip:&lt;/strong&gt; Write down the &lt;span class="caps"&gt;IP&lt;/span&gt; address you assigned. The web &lt;span class="caps"&gt;UI&lt;/span&gt; will be accessible&amp;nbsp;at &lt;code&gt;https://192.168.1.10:8006&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;Step 3: First Login and Web &lt;span class="caps"&gt;UI&lt;/span&gt;&amp;nbsp;Overview&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Access the web interface and understand the main&amp;nbsp;sections.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;On another computer, open a browser and navigate&amp;nbsp;to:
   &lt;code&gt;https://&amp;lt;your-proxmox-ip&amp;gt;:8006&lt;/code&gt;
   You will see a self-signed certificate warning. Click &lt;strong&gt;Advanced → Proceed&lt;/strong&gt; (or add an&amp;nbsp;exception).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Log in with &lt;strong&gt;Username:&lt;/strong&gt; &lt;code&gt;root&lt;/code&gt; and the password you set during&amp;nbsp;installation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dismiss the subscription nag&lt;/strong&gt; (bottom-right &amp;#8220;X&amp;#8221;). Proxmox works fully without a paid subscription; the nag is&amp;nbsp;cosmetic.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Web &lt;span class="caps"&gt;UI&lt;/span&gt;&amp;nbsp;Layout&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Panel&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Left sidebar&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Resource tree: Datacenter → Node → VMs/Containers/Storage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Center pane&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Details, graphs, and configuration for the selected item&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Top buttons&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Create &lt;span class="caps"&gt;VM&lt;/span&gt;, Create &lt;span class="caps"&gt;CT&lt;/span&gt;, Start/Stop/Console actions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Right sidebar&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Contextual options (Hardware, Options, Backup, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Step 4: Configure&amp;nbsp;Storage&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Add your data disks to Proxmox so VMs can use&amp;nbsp;them.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;In the left sidebar, click &lt;strong&gt;Datacenter → Storage&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Add → Directory&lt;/strong&gt; to add a simple mount point, or &lt;strong&gt;Add → &lt;span class="caps"&gt;ZFS&lt;/span&gt;&lt;/strong&gt; if you want&amp;nbsp;redundancy.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;For a single data disk&amp;nbsp;(simplest):&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# SSH into Proxmox as root&lt;/span&gt;
lsblk&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Identify your data disk (e.g., /dev/sdb)&lt;/span&gt;
fdisk&lt;span class="w"&gt; &lt;/span&gt;/dev/sdb&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Create a single Linux partition (type 83)&lt;/span&gt;
mkfs.ext4&lt;span class="w"&gt; &lt;/span&gt;/dev/sdb1
mkdir&lt;span class="w"&gt; &lt;/span&gt;/mnt/data
mount&lt;span class="w"&gt; &lt;/span&gt;/dev/sdb1&lt;span class="w"&gt; &lt;/span&gt;/mnt/data
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/dev/sdb1 /mnt/data ext4 defaults 0 2&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/fstab
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;In the web &lt;span class="caps"&gt;UI&lt;/span&gt;, click &lt;strong&gt;Datacenter → Storage → Add → Directory&lt;/strong&gt;:&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;ID&lt;/span&gt;: &lt;code&gt;data-disk&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Directory: &lt;code&gt;/mnt/data&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Content: &lt;code&gt;Disk image, Container&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Add&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;For &lt;span class="caps"&gt;ZFS&lt;/span&gt; (recommended if you have 2+ identical&amp;nbsp;disks):&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;zpool&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;tank&lt;span class="w"&gt; &lt;/span&gt;mirror&lt;span class="w"&gt; &lt;/span&gt;/dev/sdb&lt;span class="w"&gt; &lt;/span&gt;/dev/sdc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then&amp;nbsp;add &lt;code&gt;tank&lt;/code&gt; as a &lt;span class="caps"&gt;ZFS&lt;/span&gt; storage in the &lt;span class="caps"&gt;UI&lt;/span&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 5: Create Your First Virtual&amp;nbsp;Machine&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Deploy an Ubuntu Server &lt;span class="caps"&gt;VM&lt;/span&gt; with best-practice&amp;nbsp;settings.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Download the Ubuntu Server 24.04 &lt;span class="caps"&gt;LTS&lt;/span&gt; &lt;span class="caps"&gt;ISO&lt;/span&gt; to your local&amp;nbsp;computer.&lt;/li&gt;
&lt;li&gt;In Proxmox, click &lt;strong&gt;local (pve) → &lt;span class="caps"&gt;ISO&lt;/span&gt; Images → Upload&lt;/strong&gt; and select the &lt;span class="caps"&gt;ISO&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;Click the &lt;strong&gt;Create &lt;span class="caps"&gt;VM&lt;/span&gt;&lt;/strong&gt; button (top&amp;nbsp;right).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;General:&lt;/strong&gt; Give it a name&amp;nbsp;like &lt;code&gt;ubuntu-test&lt;/code&gt;. Leave &lt;span class="caps"&gt;VM&lt;/span&gt; &lt;span class="caps"&gt;ID&lt;/span&gt; as&amp;nbsp;auto-assigned.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;OS&lt;/span&gt;:&lt;/strong&gt; Select &lt;strong&gt;Use &lt;span class="caps"&gt;CD&lt;/span&gt;/&lt;span class="caps"&gt;DVD&lt;/span&gt; disc image file (iso)&lt;/strong&gt; and pick your uploaded &lt;span class="caps"&gt;ISO&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;System:&lt;/strong&gt; Leave defaults. If installing Windows, check &lt;strong&gt;Add &lt;span class="caps"&gt;TPM&lt;/span&gt;&lt;/strong&gt; and set version to 2.0, and enable Secure&amp;nbsp;Boot.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Disks:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Bus/Device: &lt;code&gt;SCSI&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Storage: &lt;code&gt;data-disk&lt;/code&gt; (or &lt;code&gt;local-lvm&lt;/code&gt; if you only have one&amp;nbsp;disk)&lt;/li&gt;
&lt;li&gt;Disk&amp;nbsp;size: &lt;code&gt;20 GB&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Check &lt;strong&gt;Discard&lt;/strong&gt; (enables &lt;span class="caps"&gt;TRIM&lt;/span&gt; for&amp;nbsp;SSDs)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Sockets: &lt;code&gt;1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Cores: &lt;code&gt;2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Type: &lt;code&gt;host&lt;/code&gt; (for best performance on single-node&amp;nbsp;setups)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Memory:&lt;/strong&gt; &lt;code&gt;2048 MiB&lt;/code&gt; (2 &lt;span class="caps"&gt;GB&lt;/span&gt;). Leave &lt;strong&gt;Ballooning&lt;/strong&gt; unchecked for&amp;nbsp;now.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Network:&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;Bridge: &lt;code&gt;vmbr0&lt;/code&gt; (default)&lt;/li&gt;
&lt;li&gt;Model: &lt;code&gt;VirtIO&lt;/code&gt; (best&amp;nbsp;performance)&lt;/li&gt;
&lt;li&gt;Leave &lt;span class="caps"&gt;VLAN&lt;/span&gt; blank unless you have configured&amp;nbsp;VLANs&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Confirm&lt;/strong&gt; and&amp;nbsp;finish.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Start the &lt;span class="caps"&gt;VM&lt;/span&gt;, open the &lt;strong&gt;Console&lt;/strong&gt;, and install Ubuntu as you would on physical&amp;nbsp;hardware.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pro Tip:&lt;/strong&gt; After installing the &lt;span class="caps"&gt;OS&lt;/span&gt;, go to &lt;strong&gt;Hardware → &lt;span class="caps"&gt;CD&lt;/span&gt;/&lt;span class="caps"&gt;DVD&lt;/span&gt; Drive → Remove&lt;/strong&gt; so the &lt;span class="caps"&gt;VM&lt;/span&gt; boots from disk, not &lt;span class="caps"&gt;ISO&lt;/span&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Install &lt;span class="caps"&gt;QEMU&lt;/span&gt; Guest&amp;nbsp;Agent&lt;/h3&gt;
&lt;p&gt;The &lt;span class="caps"&gt;QEMU&lt;/span&gt; guest agent improves shutdown behavior and enables &lt;span class="caps"&gt;IP&lt;/span&gt; reporting in the Proxmox &lt;span class="caps"&gt;UI&lt;/span&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;qemu-guest-agent
sudo&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--now&lt;span class="w"&gt; &lt;/span&gt;qemu-guest-agent
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 2: Use Templates, Not Clones from&amp;nbsp;ISOs&lt;/h3&gt;
&lt;p&gt;After setting up a clean &lt;span class="caps"&gt;VM&lt;/span&gt;, right-click it and select &lt;strong&gt;Convert to Template&lt;/strong&gt;. Future VMs can be cloned from this template in seconds instead of reinstalling from &lt;span class="caps"&gt;ISO&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;Tip 3: Back Up Before Major&amp;nbsp;Changes&lt;/h3&gt;
&lt;p&gt;Click a &lt;span class="caps"&gt;VM&lt;/span&gt; → &lt;strong&gt;Backup → Backup Now&lt;/strong&gt;. The&amp;nbsp;default &lt;code&gt;vzdump&lt;/code&gt; format compresses well and can be restored to any Proxmox&amp;nbsp;node.&lt;/p&gt;
&lt;h3&gt;Tip 4: Enable Dark&amp;nbsp;Mode&lt;/h3&gt;
&lt;p&gt;Go to &lt;strong&gt;User → My Settings → &lt;span class="caps"&gt;UI&lt;/span&gt; Language&lt;/strong&gt; and switch to the dark theme. Your eyes will thank&amp;nbsp;you.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Troubleshooting Common&amp;nbsp;Issues&lt;/h2&gt;
&lt;h3&gt;Cannot Access Web &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Verify the &lt;span class="caps"&gt;IP&lt;/span&gt; address&amp;nbsp;with &lt;code&gt;ip a&lt;/code&gt; from the Proxmox terminal (Alt+F2 or &lt;span class="caps"&gt;SSH&lt;/span&gt;).&lt;/li&gt;
&lt;li&gt;Ensure your client &lt;span class="caps"&gt;PC&lt;/span&gt; is on the same&amp;nbsp;subnet.&lt;/li&gt;
&lt;li&gt;Try &lt;code&gt;https://&amp;lt;ip&amp;gt;:8006&lt;/code&gt; with both &lt;span class="caps"&gt;HTTP&lt;/span&gt; and &lt;span class="caps"&gt;HTTPS&lt;/span&gt;&amp;nbsp;explicitly.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;span class="caps"&gt;VM&lt;/span&gt; Boots to Black&amp;nbsp;Screen&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Change the display&amp;nbsp;from &lt;code&gt;Default&lt;/code&gt; to &lt;code&gt;VirtIO-GPU&lt;/code&gt; or &lt;code&gt;VNC&lt;/code&gt; in Hardware&amp;nbsp;settings.&lt;/li&gt;
&lt;li&gt;Ensure the &lt;span class="caps"&gt;ISO&lt;/span&gt; is mounted and boot order has &lt;span class="caps"&gt;CD&lt;/span&gt;-&lt;span class="caps"&gt;ROM&lt;/span&gt; first for initial&amp;nbsp;install.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Slow Disk&amp;nbsp;Performance&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Ensure you&amp;nbsp;selected &lt;code&gt;VirtIO SCSI&lt;/code&gt; or &lt;code&gt;SCSI&lt;/code&gt; with &lt;code&gt;Discard&lt;/code&gt; enabled.&lt;/li&gt;
&lt;li&gt;Avoid &lt;code&gt;IDE&lt;/code&gt; emulation — it is emulated in software and significantly&amp;nbsp;slower.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;You now have a working Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; 8.2 node with configured storage and a running Ubuntu &lt;span class="caps"&gt;VM&lt;/span&gt;. Proxmox scales from a single Intel N100 mini-&lt;span class="caps"&gt;PC&lt;/span&gt; to a multi-node Ceph cluster. The same interface you used today will manage 50 VMs or 50 nodes&amp;nbsp;tomorrow.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/docker-compose-for-beginners"&gt;Learn Docker Compose on Proxmox&lt;/a&gt; to run modern self-hosted&amp;nbsp;apps&lt;/li&gt;
&lt;li&gt;&lt;a href="/portainer-setup-guide"&gt;Set up Portainer&lt;/a&gt; for a visual Docker management&amp;nbsp;layer&lt;/li&gt;
&lt;li&gt;&lt;a href="/proxmox-vs-esxi-for-homelab"&gt;Compare Proxmox vs ESXi&lt;/a&gt; if you are migrating from&amp;nbsp;VMware&lt;/li&gt;
&lt;li&gt;&lt;a href="/proxmox-lxc-guide"&gt;Explore &lt;span class="caps"&gt;LXC&lt;/span&gt; containers&lt;/a&gt; — lighter than VMs for Linux-only&amp;nbsp;workloads&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Hardware:&lt;/strong&gt; Mini PCs like Beelink &lt;span class="caps"&gt;SER5&lt;/span&gt; or Minisforum &lt;span class="caps"&gt;MS&lt;/span&gt;-01 for compact Proxmox&amp;nbsp;nodes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Storage:&lt;/strong&gt; Samsung 990 &lt;span class="caps"&gt;PRO&lt;/span&gt; NVMe or Crucial &lt;span class="caps"&gt;MX500&lt;/span&gt; SSDs for reliable &lt;span class="caps"&gt;VM&lt;/span&gt;&amp;nbsp;storage&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Networking:&lt;/strong&gt; UniFi Dream Router or &lt;span class="caps"&gt;TP&lt;/span&gt;-Link Omada for &lt;span class="caps"&gt;VLAN&lt;/span&gt;-aware homelab&amp;nbsp;networks&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;what-is&lt;/code&gt; → &lt;code&gt;/proxmox-vs-esxi-for-homelab&lt;/code&gt; for readers evaluating&amp;nbsp;hypervisors&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt; → &lt;code&gt;/proxmox-zfs-setup-guide&lt;/code&gt; for advanced &lt;span class="caps"&gt;ZFS&lt;/span&gt;&amp;nbsp;configuration&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;/docker-compose-for-beginners&lt;/code&gt; as the natural next skill to&amp;nbsp;learn&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What&amp;#8217;s your Proxmox setup?&lt;/strong&gt; Share your hardware specs and favorite VMs in the comments&amp;nbsp;below!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Subscribe to the WordForge newsletter&lt;/strong&gt; for weekly homelab tutorials, self-hosting tips, and exclusive gear&amp;nbsp;guides.&lt;/p&gt;
&lt;/blockquote&gt;</content><category term="Tutorials"/><category term="homelab"/><category term="proxmox"/><category term="proxmox beginner guide"/><category term="self-hosted"/><category term="virtualization"/></entry><entry><title>Self-Hosted Media Server Setup 2026: Jellyfin Docker Compose Guide</title><link href="https://steadypub.com/2026/06/self-hosted-media-server-setup/" rel="alternate"/><published>2026-06-05T00:33:00+07:00</published><updated>2026-06-05T00:33:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/self-hosted-media-server-setup/</id><summary type="html">&lt;p&gt;Deploy Jellyfin as a free Plex alternative using Docker Compose. Includes hardware transcoding setup for Intel Quick Sync and &lt;span class="caps"&gt;NVIDIA&lt;/span&gt;, library organization, and remote streaming&amp;nbsp;configuration.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~14 minutes&lt;br&gt;
&lt;strong&gt;Audience:&lt;/strong&gt; Media enthusiasts leaving Plex or Emby due to policy changes or subscription fatigue&lt;br&gt;
&lt;strong&gt;Last tested:&lt;/strong&gt; Jellyfin 10.10, June&amp;nbsp;2026&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is&amp;nbsp;Jellyfin?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Jellyfin is a free, open-source media server forked from Emby before it went closed-source. It organizes your movies, &lt;span class="caps"&gt;TV&lt;/span&gt; shows, music, and photos into a Netflix-like interface, then streams them to browsers, mobile apps, smart TVs, and &lt;span class="caps"&gt;DLNA&lt;/span&gt; devices — all without calling home, collecting telemetry, or charging subscription&amp;nbsp;fees.&lt;/p&gt;
&lt;p&gt;Unlike Plex, Jellyfin does not require account creation, and your viewing habits are never sent to a third-party analytics&amp;nbsp;platform.&lt;/p&gt;
&lt;h3&gt;Key&amp;nbsp;Benefits&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Jellyfin&lt;/th&gt;
&lt;th&gt;Plex&lt;/th&gt;
&lt;th&gt;Emby&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cost&lt;/td&gt;
&lt;td&gt;100% free&lt;/td&gt;
&lt;td&gt;Freemium (paid features)&lt;/td&gt;
&lt;td&gt;Freemium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Open source&lt;/td&gt;
&lt;td&gt;✅ (GPLv2)&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Partial&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phone home / telemetry&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hardware transcoding&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Paid (Plex Pass)&lt;/td&gt;
&lt;td&gt;Paid (Premiere)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Live &lt;span class="caps"&gt;TV&lt;/span&gt; / &lt;span class="caps"&gt;DVR&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Paid&lt;/td&gt;
&lt;td&gt;Paid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Plugins&lt;/td&gt;
&lt;td&gt;30+ community&lt;/td&gt;
&lt;td&gt;Curated store&lt;/td&gt;
&lt;td&gt;Curated store&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;h3&gt;Hardware&amp;nbsp;Requirements&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Storage&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;GPU&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Direct play only (no transcode)&lt;/td&gt;
&lt;td&gt;Any 2-core&lt;/td&gt;
&lt;td&gt;2 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1 &lt;span class="caps"&gt;TB&lt;/span&gt;+ &lt;span class="caps"&gt;HDD&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2–3 concurrent 1080p transcodes&lt;/td&gt;
&lt;td&gt;4-core modern&lt;/td&gt;
&lt;td&gt;4 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1 &lt;span class="caps"&gt;TB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt; for metadata&lt;/td&gt;
&lt;td&gt;Intel &lt;span class="caps"&gt;UHD&lt;/span&gt; / Iris Xe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4+ concurrent 4K &lt;span class="caps"&gt;HDR&lt;/span&gt; → 1080p&lt;/td&gt;
&lt;td&gt;6-core&lt;/td&gt;
&lt;td&gt;8 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;256 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt; cache + &lt;span class="caps"&gt;NAS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Intel Arc, &lt;span class="caps"&gt;NVIDIA&lt;/span&gt; &lt;span class="caps"&gt;GTX&lt;/span&gt; 1650+&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Transcoding Quick&amp;nbsp;Reference&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Direct Play:&lt;/strong&gt; The client plays the file as-is. Zero &lt;span class="caps"&gt;CPU&lt;/span&gt;/&lt;span class="caps"&gt;GPU&lt;/span&gt; usage. Best&amp;nbsp;quality.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Transcoding:&lt;/strong&gt; The server re-encodes the video in real time for incompatible clients (old phones, bandwidth-limited remotes). This is where hardware acceleration&amp;nbsp;matters.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Codec&lt;/th&gt;
&lt;th&gt;Direct Play Support&lt;/th&gt;
&lt;th&gt;Often Needs Transcode&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;H.264 (&lt;span class="caps"&gt;AVC&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;Universal&lt;/td&gt;
&lt;td&gt;Rare&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;H.265 (&lt;span class="caps"&gt;HEVC&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;Modern devices&lt;/td&gt;
&lt;td&gt;Older Roku, web browsers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;AV1&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;2022+ devices&lt;/td&gt;
&lt;td&gt;Almost everything else&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4K &lt;span class="caps"&gt;HDR&lt;/span&gt; → 1080p &lt;span class="caps"&gt;SDR&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Never direct&lt;/td&gt;
&lt;td&gt;Always (tone mapping)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Deploy Jellyfin with Docker&amp;nbsp;Compose&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Create a Compose file with proper volume mappings for media, config, and hardware device&amp;nbsp;access.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Create a project&amp;nbsp;directory:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;~/jellyfin/&lt;span class="o"&gt;{&lt;/span&gt;config,cache,media&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/jellyfin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Set correct permissions (Jellyfin runs as &lt;span class="caps"&gt;UID&lt;/span&gt;/&lt;span class="caps"&gt;GID&lt;/span&gt; 1000:1000 by&amp;nbsp;default):&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;chown&lt;span class="w"&gt; &lt;/span&gt;-R&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;:1000&lt;span class="w"&gt; &lt;/span&gt;config&lt;span class="w"&gt; &lt;/span&gt;cache
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Create &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;jellyfin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;jellyfin/jellyfin:10.10&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;jellyfin&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1000:1000&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;group_add&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;105&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Change to your host&amp;#39;s render group ID for GPU access&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;network_mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;host&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Simplifies DLNA and client discovery&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./config:/config&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./cache:/cache&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/mnt/media:/media:ro&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Read-only access to your media library&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;JELLYFIN_PublishedServerUrl=http://jellyfin.lan&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Uncomment the appropriate device block for GPU transcoding:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Intel Quick Sync:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# devices:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#   - /dev/dri:/dev/dri&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# NVIDIA:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# deploy:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#   resources:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#     reservations:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#       devices:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#         - driver: nvidia&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#           count: 1&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;#           capabilities: [gpu]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Find your render group &lt;span class="caps"&gt;ID&lt;/span&gt; (for Intel/&lt;span class="caps"&gt;AMD&lt;/span&gt; &lt;span class="caps"&gt;GPU&lt;/span&gt;&amp;nbsp;passthrough):&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;getent&lt;span class="w"&gt; &lt;/span&gt;group&lt;span class="w"&gt; &lt;/span&gt;render&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cut&lt;span class="w"&gt; &lt;/span&gt;-d:&lt;span class="w"&gt; &lt;/span&gt;-f3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Replace &lt;code&gt;105&lt;/code&gt; in &lt;code&gt;group_add&lt;/code&gt; with your actual&amp;nbsp;value.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Start&amp;nbsp;Jellyfin:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Access the web &lt;span class="caps"&gt;UI&lt;/span&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;http://your-server-ip:8096
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 2: Initial Library&amp;nbsp;Setup&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Add media folders and let Jellyfin scan your&amp;nbsp;collection.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;On first launch, Jellyfin walks you through&amp;nbsp;setup:&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Preferred display language:&lt;/strong&gt; Choose your&amp;nbsp;language&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Username / Password:&lt;/strong&gt; Create the admin&amp;nbsp;account&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Add Media&amp;nbsp;Library:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Content type:&lt;/strong&gt; Movies, &lt;span class="caps"&gt;TV&lt;/span&gt; Shows, Music,&amp;nbsp;etc.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Display name:&lt;/strong&gt; e.g., &amp;#8220;Movies&amp;#8221;, &amp;#8220;&lt;span class="caps"&gt;TV&lt;/span&gt;&amp;nbsp;Shows&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Folders:&lt;/strong&gt; &lt;code&gt;/media/movies&lt;/code&gt;, &lt;code&gt;/media/tv&lt;/code&gt;,&amp;nbsp;etc.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Preferred language:&lt;/strong&gt; English (or your&amp;nbsp;language)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Metadata downloaders:&lt;/strong&gt; Enable TheMovieDB, TheTVDB, &lt;span class="caps"&gt;OMDB&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Image fetchers:&lt;/strong&gt; Enable TheMovieDB, Screen&amp;nbsp;Grabber&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click &lt;strong&gt;Next → Next → Finish&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Jellyfin will begin scanning. For 1,000 movies, this takes 15–30 minutes depending on internet speed and &lt;span class="caps"&gt;CPU&lt;/span&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Recommended folder&amp;nbsp;structure:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;/mnt/media/
├── movies/
│   ├── The Matrix (1999)/
│   │   └── The Matrix (1999) [1080p].mkv
│   └── Inception (2010)/
│       └── Inception (2010) [2160p].mkv
├── tv/
│   ├── Breaking Bad/
│   │   ├── Season 01/
│   │   │   ├── Breaking Bad - S01E01.mkv
│   │   │   └── Breaking Bad - S01E02.mkv
└── music/
    ├── Artist Name/
    │   ├── Album Name/
    │   │   └── 01 - Track Name.flac
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pro Tip:&lt;/strong&gt; Name files accurately. Jellyfin matches&amp;nbsp;using &lt;code&gt;Movie Name (Year)&lt;/code&gt; and &lt;code&gt;Series Name - SXXEYY&lt;/code&gt; patterns. Tools like &lt;a href="https://sonarr.tv/"&gt;Sonarr&lt;/a&gt; and &lt;a href="https://radarr.video/"&gt;Radarr&lt;/a&gt; automate&amp;nbsp;naming.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;Step 3: Enable Hardware&amp;nbsp;Transcoding&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Offload video transcoding from &lt;span class="caps"&gt;CPU&lt;/span&gt; to &lt;span class="caps"&gt;GPU&lt;/span&gt; for smooth 4K→1080p&amp;nbsp;conversions.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;For Intel Quick Sync (12th–14th Gen,&amp;nbsp;N100–N305):&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Ensure &lt;code&gt;/dev/dri&lt;/code&gt; is passed through&amp;nbsp;in &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;devices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/dev/dri:/dev/dri&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;In Jellyfin web &lt;span class="caps"&gt;UI&lt;/span&gt;: &lt;strong&gt;Administration → Playback →&amp;nbsp;Transcoding&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enable hardware decoding:&lt;/strong&gt;&amp;nbsp;✅&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hardware&amp;nbsp;acceleration:&lt;/strong&gt; &lt;code&gt;Intel QuickSync (QSV)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enable hardware encoding:&lt;/strong&gt;&amp;nbsp;✅&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Allow decoding:&lt;/strong&gt; Check all formats (H264, &lt;span class="caps"&gt;HEVC&lt;/span&gt;, &lt;span class="caps"&gt;VP9&lt;/span&gt;, &lt;span class="caps"&gt;AV1&lt;/span&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click &lt;strong&gt;Save&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Test by playing a 4K file on a remote device and checking the dashboard for the orange ✅ &amp;#8220;Transcoding&amp;#8221; indicator. &lt;span class="caps"&gt;CPU&lt;/span&gt; usage should drop to&amp;nbsp;&amp;lt;10%.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;For &lt;span class="caps"&gt;NVIDIA&lt;/span&gt;&amp;nbsp;GPUs:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Install the &lt;span class="caps"&gt;NVIDIA&lt;/span&gt; Container Toolkit on the&amp;nbsp;host:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;distribution&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;/etc/os-release&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$ID$VERSION_ID&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
curl&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;-L&lt;span class="w"&gt; &lt;/span&gt;https://nvidia.github.io/nvidia-docker/gpgkey&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;apt-key&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt; &lt;/span&gt;-
curl&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;-L&lt;span class="w"&gt; &lt;/span&gt;https://nvidia.github.io/nvidia-docker/&lt;span class="nv"&gt;$distribution&lt;/span&gt;/nvidia-docker.list&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;tee&lt;span class="w"&gt; &lt;/span&gt;/etc/apt/sources.list.d/nvidia-docker.list
sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;nvidia-docker2
sudo&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;restart&lt;span class="w"&gt; &lt;/span&gt;docker
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Use&amp;nbsp;the &lt;code&gt;deploy&lt;/code&gt; block in Compose (shown in Step&amp;nbsp;1).&lt;/li&gt;
&lt;li&gt;In Jellyfin,&amp;nbsp;select &lt;code&gt;NVIDIA NVENC&lt;/code&gt; as the acceleration&amp;nbsp;method.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Step 4: Remote Access and &lt;span class="caps"&gt;HTTPS&lt;/span&gt;&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Stream securely from outside your home&amp;nbsp;network.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Option A: Reverse Proxy&amp;nbsp;(Recommended)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Add a Proxy Host in &lt;span class="caps"&gt;NGINX&lt;/span&gt; Proxy Manager:
| Field | Value |
|&amp;#8212;&amp;#8212;&amp;#8212;-|&amp;#8212;&amp;#8212;&amp;#8212;-|
| Domain&amp;nbsp;| &lt;code&gt;jellyfin.yourdomain.com&lt;/code&gt; |
| Forward Host&amp;nbsp;| &lt;code&gt;your-server-ip&lt;/code&gt; |
| Forward Port&amp;nbsp;| &lt;code&gt;8096&lt;/code&gt; |
| Block Exploits | ✅ |
| Websockets | ✅&amp;nbsp;|&lt;/p&gt;
&lt;p&gt;In Jellyfin: &lt;strong&gt;Administration → Networking&lt;/strong&gt;:
- &lt;strong&gt;Base &lt;span class="caps"&gt;URL&lt;/span&gt;:&lt;/strong&gt; leave blank
- &lt;strong&gt;Public &lt;span class="caps"&gt;HTTPS&lt;/span&gt;&amp;nbsp;port:&lt;/strong&gt; &lt;code&gt;443&lt;/code&gt;
- &lt;strong&gt;Known proxies:&lt;/strong&gt; Add your reverse proxy &lt;span class="caps"&gt;IP&lt;/span&gt; or&amp;nbsp;subnet&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Option B: Tailscale / Zero&amp;nbsp;Trust&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Install Tailscale on your Jellyfin host and client devices. Access Jellyfin&amp;nbsp;at &lt;code&gt;http://jellyfin-host:8096&lt;/code&gt; over the encrypted mesh network without opening firewall&amp;nbsp;ports.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Option C: Direct Port Forward (Not&amp;nbsp;Recommended)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Forward router&amp;nbsp;port &lt;code&gt;8096&lt;/code&gt; to your Jellyfin host. Only use this with Jellyfin&amp;#8217;s built-in &lt;span class="caps"&gt;HTTPS&lt;/span&gt; and strong&amp;nbsp;passwords.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Use Sonarr + Radarr + Bazarr for&amp;nbsp;Automation&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Sonarr:&lt;/strong&gt; &lt;span class="caps"&gt;TV&lt;/span&gt; show downloading and&amp;nbsp;renaming&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Radarr:&lt;/strong&gt; Movie downloading and&amp;nbsp;renaming&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bazarr:&lt;/strong&gt; Subtitle&amp;nbsp;downloading&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Prowlarr:&lt;/strong&gt; Indexer&amp;nbsp;management&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Run them all in a separate Docker Compose stack and point their root folders&amp;nbsp;to &lt;code&gt;/mnt/media&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Tip 2: Enable Tone Mapping for &lt;span class="caps"&gt;HDR&lt;/span&gt;&amp;nbsp;Content&lt;/h3&gt;
&lt;p&gt;Without tone mapping, &lt;span class="caps"&gt;HDR&lt;/span&gt; movies look washed out on &lt;span class="caps"&gt;SDR&lt;/span&gt; screens:
- &lt;strong&gt;Administration → Playback → Tone&amp;nbsp;mapping:&lt;/strong&gt; &lt;code&gt;Enable&lt;/code&gt;
- &lt;strong&gt;Tone mapping&amp;nbsp;algorithm:&lt;/strong&gt; &lt;code&gt;BT.2390&lt;/code&gt; (best quality)&amp;nbsp;or &lt;code&gt;Reinhard&lt;/code&gt; (lower &lt;span class="caps"&gt;GPU&lt;/span&gt; load)
- &lt;strong&gt;Tone mapping&amp;nbsp;mode:&lt;/strong&gt; &lt;code&gt;GPU&lt;/code&gt; if you have hardware&amp;nbsp;acceleration&lt;/p&gt;
&lt;h3&gt;Tip 3: Cache Metadata on &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;If your media lives on a slow &lt;span class="caps"&gt;NAS&lt;/span&gt; or &lt;span class="caps"&gt;HDD&lt;/span&gt;, keep Jellyfin&amp;#8217;s config and cache on an &lt;span class="caps"&gt;SSD&lt;/span&gt;. Our Compose file already does this&amp;nbsp;via &lt;code&gt;./config&lt;/code&gt; and &lt;code&gt;./cache&lt;/code&gt; bind&amp;nbsp;mounts.&lt;/p&gt;
&lt;h3&gt;Tip 4: Limit Transcode&amp;nbsp;Sessions&lt;/h3&gt;
&lt;p&gt;Prevent a single remote user from monopolizing your &lt;span class="caps"&gt;GPU&lt;/span&gt;:
- &lt;strong&gt;Administration → Playback → Transcoding → Max transcode&amp;nbsp;sessions:&lt;/strong&gt; &lt;code&gt;2&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Troubleshooting Common&amp;nbsp;Issues&lt;/h2&gt;
&lt;h3&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;No compatible streams&amp;#8221;&amp;nbsp;Error&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;The client cannot direct play the file and transcoding is&amp;nbsp;failing.&lt;/li&gt;
&lt;li&gt;Check that hardware acceleration is enabled&amp;nbsp;and &lt;code&gt;/dev/dri&lt;/code&gt; is visible inside the&amp;nbsp;container:
  &lt;code&gt;bash
  docker exec -it jellyfin ls -la /dev/dri&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;If empty,&amp;nbsp;your &lt;code&gt;group_add&lt;/code&gt; or &lt;code&gt;devices&lt;/code&gt; block is&amp;nbsp;incorrect.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Slow Library&amp;nbsp;Scanning&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Disable real-time monitoring if using network storage (&lt;span class="caps"&gt;NFS&lt;/span&gt;/&lt;span class="caps"&gt;SMB&lt;/span&gt;):
  &lt;strong&gt;Administration → Libraries → [Library] → Advanced → Enable real time monitoring:&lt;/strong&gt;&amp;nbsp;❌&lt;/li&gt;
&lt;li&gt;Schedule a nightly scan instead:
  &lt;strong&gt;Administration → Scheduled Tasks → Scan Media&amp;nbsp;Library&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Subtitles Not&amp;nbsp;Showing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Ensure the subtitle file has the same base name as the&amp;nbsp;video:
  &lt;code&gt;Movie (2024).mkv&lt;/code&gt; → &lt;code&gt;Movie (2024).en.srt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Or use Bazarr to fetch subtitles&amp;nbsp;automatically.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;You now have Jellyfin running in Docker with hardware transcoding, a properly organized media library, and secure remote access. It replaces Plex or Emby without subscription fees or&amp;nbsp;telemetry.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="/jellyfin-vs-plex-vs-emby"&gt;Compare Jellyfin vs Plex vs Emby in&amp;nbsp;depth&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/sonarr-radarr-docker-compose"&gt;Set up Sonarr and Radarr for automated media&amp;nbsp;management&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/jellyfin-hdr-tone-mapping"&gt;Add hardware tone mapping for &lt;span class="caps"&gt;HDR&lt;/span&gt;&amp;nbsp;content&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/docker-monitoring-grafana-prometheus"&gt;Monitor your media server with&amp;nbsp;Grafana&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Storage:&lt;/strong&gt; &lt;span class="caps"&gt;WD&lt;/span&gt; Red Plus or Seagate IronWolf &lt;span class="caps"&gt;NAS&lt;/span&gt; drives for media&amp;nbsp;libraries&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mini PCs:&lt;/strong&gt; Beelink &lt;span class="caps"&gt;SER6&lt;/span&gt; (&lt;span class="caps"&gt;AMD&lt;/span&gt; Radeon 680M) for excellent &lt;span class="caps"&gt;GPU&lt;/span&gt;&amp;nbsp;transcoding&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Networking:&lt;/strong&gt; 2.5 GbE switches for local 4K direct play without&amp;nbsp;buffering&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;what-is&lt;/code&gt; → &lt;code&gt;/jellyfin-vs-plex-vs-emby&lt;/code&gt; for readers weighing&amp;nbsp;options&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hardware&lt;/code&gt; → &lt;code&gt;/low-power-homelab-server-build&lt;/code&gt; for hardware&amp;nbsp;recommendations&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;/sonarr-radarr-docker-compose&lt;/code&gt; for media&amp;nbsp;automation&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What are you streaming on Jellyfin?&lt;/strong&gt; Share your library size and favorite client in the&amp;nbsp;comments!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Subscribe to the WordForge newsletter&lt;/strong&gt; for weekly self-hosted media and homelab&amp;nbsp;guides.&lt;/p&gt;
&lt;/blockquote&gt;</content><category term="Tutorials"/><category term="jellyfin"/><category term="media server"/><category term="docker"/><category term="docker compose"/><category term="self-hosted"/><category term="plex alternative"/><category term="homelab"/></entry><entry><title>AdGuard Home Setup Guide: Network-Wide Ad Blocking in 2026</title><link href="https://steadypub.com/2026/06/adguard-home-setup/" rel="alternate"/><published>2026-06-05T00:00:00+07:00</published><updated>2026-06-05T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/adguard-home-setup/</id><summary type="html">&lt;p&gt;Complete AdGuard Home setup guide for Docker, Debian, and Proxmox &lt;span class="caps"&gt;LXC&lt;/span&gt;. Covers installation, &lt;span class="caps"&gt;DNS&lt;/span&gt; configuration, filtering, parental controls, and router&amp;nbsp;integration.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~12 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelabbers wanting a modern, user-friendly &lt;span class="caps"&gt;DNS&lt;/span&gt; ad&amp;nbsp;blocker&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is AdGuard&amp;nbsp;Home?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;AdGuard Home is a network-wide &lt;span class="caps"&gt;DNS&lt;/span&gt; ad blocker that blocks ads, trackers, and adult content at the &lt;span class="caps"&gt;DNS&lt;/span&gt; level. It is similar to Pi-hole but offers a more modern web &lt;span class="caps"&gt;UI&lt;/span&gt;, better parental controls, native &lt;span class="caps"&gt;DNS&lt;/span&gt;-over-&lt;span class="caps"&gt;HTTPS&lt;/span&gt; (DoH) and &lt;span class="caps"&gt;DNS&lt;/span&gt;-over-&lt;span class="caps"&gt;TLS&lt;/span&gt; (DoT) support, and built-in &lt;span class="caps"&gt;DHCP&lt;/span&gt; server&amp;nbsp;functionality.&lt;/p&gt;
&lt;h3&gt;Key&amp;nbsp;Benefits&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Benefit&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Modern &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Clean, responsive web interface with dark mode&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Encrypted &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Native DoH and DoT support without extra containers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Parental controls&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Block adult sites, enforce safe search, schedule internet access&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Query log&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fast, filterable log with client identification&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Statistics&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Per-client stats, top queried domains, top blocked domains&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Blocking modes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Default hosts, &lt;span class="caps"&gt;NXDOMAIN&lt;/span&gt;, Null &lt;span class="caps"&gt;IP&lt;/span&gt;, or custom &lt;span class="caps"&gt;IP&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt; rewrites&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Local &lt;span class="caps"&gt;DNS&lt;/span&gt; records (split-horizon &lt;span class="caps"&gt;DNS&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Upstreams&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Easy load balancing and fallback &lt;span class="caps"&gt;DNS&lt;/span&gt; resolvers&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;h3&gt;Hardware&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Any device running Docker or Linux (mini &lt;span class="caps"&gt;PC&lt;/span&gt;, Raspberry Pi, &lt;span class="caps"&gt;NAS&lt;/span&gt;, &lt;span class="caps"&gt;VM&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;256MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; minimum (&lt;span class="caps"&gt;512MB&lt;/span&gt;&amp;nbsp;recommended)&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;100MB&lt;/span&gt; storage for the binary + log&amp;nbsp;space&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Software&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Docker Engine 24.x+ or a Debian 12/Ubuntu 24.04&amp;nbsp;host&lt;/li&gt;
&lt;li&gt;Router access to change &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;settings&lt;/li&gt;
&lt;li&gt;Port 3000 free (for initial setup) and port 53 (for &lt;span class="caps"&gt;DNS&lt;/span&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Knowledge&amp;nbsp;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Basic Docker or Linux&amp;nbsp;commands&lt;/li&gt;
&lt;li&gt;Router admin panel&amp;nbsp;access&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;concepts&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Install AdGuard Home with Docker&amp;nbsp;Compose&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Deploy AdGuard Home as a persistent container with proper volumes and network&amp;nbsp;settings.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Create the project&amp;nbsp;directory:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;~/docker/adguardhome&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/docker/adguardhome
mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;workdir&lt;span class="w"&gt; &lt;/span&gt;confdir
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Create &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;adguardhome&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;adguardhome&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;adguard/adguardhome:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;53:53/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;53:53/udp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8080:80/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8443:443/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3000:3000/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./workdir:/opt/adguardhome/work&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./confdir:/opt/adguardhome/conf&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;adguard-net&lt;/span&gt;

&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;adguard-net&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;bridge&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Deploy:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Complete the initial setup&amp;nbsp;wizard:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Open &lt;code&gt;http://your-server-ip:3000&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Set admin username and a strong&amp;nbsp;password&lt;/li&gt;
&lt;li&gt;Choose interface and port&amp;nbsp;(keep &lt;code&gt;0.0.0.0:53&lt;/code&gt; for &lt;span class="caps"&gt;DNS&lt;/span&gt;, &lt;code&gt;80&lt;/code&gt; for web &lt;span class="caps"&gt;UI&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;Set upstream &lt;span class="caps"&gt;DNS&lt;/span&gt; resolvers (Cloudflare, Quad9, or&amp;nbsp;custom)&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create filters and click &amp;#8220;Open&amp;nbsp;Dashboard&amp;#8221;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;After setup, the web &lt;span class="caps"&gt;UI&lt;/span&gt; moves to port&amp;nbsp;80:&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Access&amp;nbsp;at &lt;code&gt;http://your-server-ip:8080&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Step 2: Configure &lt;span class="caps"&gt;DNS&lt;/span&gt; and Upstream&amp;nbsp;Resolvers&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Set up reliable upstream &lt;span class="caps"&gt;DNS&lt;/span&gt; with encryption and fallback&amp;nbsp;options.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Go to Settings → &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;settings&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Upstream &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;servers:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;# DNS-over-HTTPS (DoH)
https://dns.cloudflare.com/dns-query
https://dns.quad9.net/dns-query

# DNS-over-TLS (DoT)
tls://dns.google

# Plain DNS (fallback)
1.1.1.1
1.0.0.1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Bootstrap &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;servers:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="mf"&gt;1.1.1.1&lt;/span&gt;
&lt;span class="mf"&gt;1.0.0.1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Rate limiting:&lt;/strong&gt; 20 requests per second per&amp;nbsp;client&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enable &lt;span class="caps"&gt;DNSSEC&lt;/span&gt;&amp;nbsp;validation&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Save and&amp;nbsp;apply&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Step 3: Configure &lt;span class="caps"&gt;DNS&lt;/span&gt; Rewrites (Local &lt;span class="caps"&gt;DNS&lt;/span&gt;)&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Point local hostnames to internal IPs so you can access services by name&amp;nbsp;(e.g., &lt;code&gt;http://proxmox.local&lt;/code&gt;).&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Go to Filters → &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;rewrites&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Add&amp;nbsp;entries:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Domain&lt;/th&gt;
&lt;th&gt;Answer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;proxmox.local&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;192.168.1.10&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nas.local&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;192.168.1.20&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pihole.local&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;192.168.1.30&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;jellyfin.local&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;192.168.1.40&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Test:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;nslookup&lt;span class="w"&gt; &lt;/span&gt;proxmox.local&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.1.10
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 4: Router&amp;nbsp;Configuration&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Point your entire network to AdGuard Home for &lt;span class="caps"&gt;DNS&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Option A: Router &lt;span class="caps"&gt;DHCP&lt;/span&gt; (Recommended)&lt;/strong&gt;
1. Log into your router&amp;nbsp;(&lt;code&gt;192.168.1.1&lt;/code&gt; or &lt;code&gt;192.168.0.1&lt;/code&gt;)
2. Find &lt;strong&gt;&lt;span class="caps"&gt;DHCP&lt;/span&gt; Server&lt;/strong&gt; or &lt;strong&gt;&lt;span class="caps"&gt;LAN&lt;/span&gt; Settings&lt;/strong&gt;
3. Set &lt;strong&gt;Primary &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/strong&gt; to AdGuard Home &lt;span class="caps"&gt;IP&lt;/span&gt;&amp;nbsp;(e.g., &lt;code&gt;192.168.1.10&lt;/code&gt;)
4. &lt;strong&gt;Secondary &lt;span class="caps"&gt;DNS&lt;/span&gt;:&lt;/strong&gt; leave blank or use a backup AdGuard instance
5. Save and reboot the&amp;nbsp;router&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Option B: AdGuard Home &lt;span class="caps"&gt;DHCP&lt;/span&gt; Server&lt;/strong&gt;
If your router is locked (&lt;span class="caps"&gt;ISP&lt;/span&gt;-provided), let AdGuard Home handle &lt;span class="caps"&gt;DHCP&lt;/span&gt;:
1. Go to &lt;strong&gt;Settings → &lt;span class="caps"&gt;DHCP&lt;/span&gt; settings&lt;/strong&gt;
2. Enable &lt;span class="caps"&gt;DHCP&lt;/span&gt; server
3. Set&amp;nbsp;range: &lt;code&gt;192.168.1.100&lt;/code&gt; to &lt;code&gt;192.168.1.200&lt;/code&gt;
4. Set&amp;nbsp;gateway: &lt;code&gt;192.168.1.1&lt;/code&gt;
5. Set subnet&amp;nbsp;mask: &lt;code&gt;255.255.255.0&lt;/code&gt;
6. Disable &lt;span class="caps"&gt;DHCP&lt;/span&gt; on your router
7. Renew all client&amp;nbsp;leases&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Enable &lt;span class="caps"&gt;DNSSEC&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;In Settings → &lt;span class="caps"&gt;DNS&lt;/span&gt; settings, enable &amp;#8220;&lt;span class="caps"&gt;DNSSEC&lt;/span&gt; validation.&amp;#8221; This prevents &lt;span class="caps"&gt;DNS&lt;/span&gt; spoofing and ensures domain&amp;nbsp;authenticity.&lt;/p&gt;
&lt;h3&gt;Tip 2: Use Per-Client&amp;nbsp;Filtering&lt;/h3&gt;
&lt;p&gt;Go to &lt;strong&gt;Settings → Client settings&lt;/strong&gt; and add clients by &lt;span class="caps"&gt;IP&lt;/span&gt; or &lt;span class="caps"&gt;MAC&lt;/span&gt;. You can assign different filtering rules to kids&amp;#8217; devices vs. adult&amp;nbsp;devices.&lt;/p&gt;
&lt;h3&gt;Tip 3: Enable Safe&amp;nbsp;Search&lt;/h3&gt;
&lt;p&gt;In &lt;strong&gt;Filters → &lt;span class="caps"&gt;DNS&lt;/span&gt; blocklists&lt;/strong&gt;, enable the safe search option. This forces Google, Bing, YouTube, and DuckDuckGo to use safe search&amp;nbsp;modes.&lt;/p&gt;
&lt;h3&gt;Tip 4: Add Custom Filtering&amp;nbsp;Rules&lt;/h3&gt;
&lt;p&gt;AdGuard Home supports custom rules in AdGuard&amp;nbsp;syntax:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;# Block a specific domain
||example.com^

# Block a subdomain
||ads.example.com^

# Allow an exception
@@||safe.example.com^

# Redirect a domain
192.168.1.10 proxmox.local
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 5: Backup Your&amp;nbsp;Configuration&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Backup the config directory&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/docker/adguardhome
tar&lt;span class="w"&gt; &lt;/span&gt;czvf&lt;span class="w"&gt; &lt;/span&gt;adguard-backup-&lt;span class="k"&gt;$(&lt;/span&gt;date&lt;span class="w"&gt; &lt;/span&gt;+%F&lt;span class="k"&gt;)&lt;/span&gt;.tar.gz&lt;span class="w"&gt; &lt;/span&gt;confdir&lt;span class="w"&gt; &lt;/span&gt;workdir

&lt;span class="c1"&gt;# Restore: extract and restart container&lt;/span&gt;
tar&lt;span class="w"&gt; &lt;/span&gt;xzvf&lt;span class="w"&gt; &lt;/span&gt;adguard-backup-2026-06-05.tar.gz
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;restart
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Troubleshooting Common&amp;nbsp;Issues&lt;/h2&gt;
&lt;h3&gt;Problem 1: &amp;#8220;Dashboard Not Accessible After&amp;nbsp;Setup&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Cause:&lt;/strong&gt; Port 3000 is only for the initial setup wizard. After configuration, the &lt;span class="caps"&gt;UI&lt;/span&gt; runs on port 80 inside the container (mapped to 8080 on&amp;nbsp;host).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&amp;nbsp;Access &lt;code&gt;http://your-server-ip:8080&lt;/code&gt; after&amp;nbsp;setup.&lt;/p&gt;
&lt;h3&gt;Problem 2: &amp;#8220;&lt;span class="caps"&gt;DNS&lt;/span&gt; Queries Not Being&amp;nbsp;Blocked&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Cause:&lt;/strong&gt; Router not using AdGuard Home as &lt;span class="caps"&gt;DNS&lt;/span&gt;, or devices using hardcoded &lt;span class="caps"&gt;DNS&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;
- Check router &lt;span class="caps"&gt;DNS&lt;/span&gt; settings
- For devices with hardcoded &lt;span class="caps"&gt;DNS&lt;/span&gt; (some Android TVs, Chromecast), use AdGuard Home&amp;#8217;s &amp;#8220;force safe search&amp;#8221; or block port 53 outbound on your&amp;nbsp;firewall&lt;/p&gt;
&lt;h3&gt;Problem 3: &amp;#8220;Port 53 Already in&amp;nbsp;Use&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Cause:&lt;/strong&gt; systemd-resolved or another &lt;span class="caps"&gt;DNS&lt;/span&gt; service is bound to port&amp;nbsp;53.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;stop&lt;span class="w"&gt; &lt;/span&gt;systemd-resolved
systemctl&lt;span class="w"&gt; &lt;/span&gt;disable&lt;span class="w"&gt; &lt;/span&gt;systemd-resolved
rm&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;/etc/resolv.conf
ln&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;/run/systemd/resolve/resolv.conf&lt;span class="w"&gt; &lt;/span&gt;/etc/resolv.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;AdGuard Home is a modern, powerful &lt;span class="caps"&gt;DNS&lt;/span&gt; ad blocker with built-in encrypted &lt;span class="caps"&gt;DNS&lt;/span&gt;, parental controls, and local &lt;span class="caps"&gt;DNS&lt;/span&gt; rewriting. The Docker Compose setup takes under 10 minutes and immediately improves privacy and ad blocking across your entire&amp;nbsp;network.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Compare with &lt;a href="pihole-vs-adguard-home"&gt;Pi-hole&lt;/a&gt; to see which fits your&amp;nbsp;style&lt;/li&gt;
&lt;li&gt;Set up &lt;a href="pihole-unbound-dns"&gt;Unbound&lt;/a&gt; as a recursive resolver for complete &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;independence&lt;/li&gt;
&lt;li&gt;Monitor your network with &lt;a href="grafana-prometheus-setup"&gt;Prometheus and&amp;nbsp;Grafana&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Beelink Mini S12 Pro&lt;/strong&gt;: Mini &lt;span class="caps"&gt;PC&lt;/span&gt; for running AdGuard Home + other&amp;nbsp;services&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;TP&lt;/span&gt;-Link Omada router&lt;/strong&gt;: Router with flexible &lt;span class="caps"&gt;DNS&lt;/span&gt;/&lt;span class="caps"&gt;DHCP&lt;/span&gt;&amp;nbsp;settings&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;intro&lt;/code&gt; → &lt;code&gt;pihole-vs-adguard-home&lt;/code&gt; for blocker&amp;nbsp;comparison&lt;/li&gt;
&lt;li&gt;&lt;code&gt;step-2&lt;/code&gt; → &lt;code&gt;pihole-unbound-dns&lt;/code&gt; for recursive &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;setup&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;docker-compose-for-beginners&lt;/code&gt; for Docker&amp;nbsp;basics&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] Are you using AdGuard Home or Pi-hole? Share your filtering stats and favorite&amp;nbsp;blocklists!&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for weekly privacy and &lt;span class="caps"&gt;DNS&lt;/span&gt; setup&amp;nbsp;guides.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Tutorials"/><category term="adguard home"/><category term="dns ad blocker"/><category term="setup guide"/><category term="homelab"/><category term="docker"/><category term="network-wide"/></entry><entry><title>APC UPS for Homelab: A Complete Guide to Power Protection</title><link href="https://steadypub.com/2026/06/apc-ups-homelab/" rel="alternate"/><published>2026-06-05T00:00:00+07:00</published><updated>2026-06-05T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/apc-ups-homelab/</id><summary type="html">&lt;p&gt;How to choose and configure an &lt;span class="caps"&gt;APC&lt;/span&gt; &lt;span class="caps"&gt;UPS&lt;/span&gt; for your homelab. Covers sizing, runtime calculation, &lt;span class="caps"&gt;NUT&lt;/span&gt; integration, and model recommendations for mini PCs and rack&amp;nbsp;servers.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~12 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab builders who want clean power and graceful&amp;nbsp;shutdowns&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why an &lt;span class="caps"&gt;APC&lt;/span&gt; &lt;span class="caps"&gt;UPS&lt;/span&gt; for Your&amp;nbsp;Homelab?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;An &lt;span class="caps"&gt;APC&lt;/span&gt; &lt;span class="caps"&gt;UPS&lt;/span&gt; (Uninterruptible Power Supply) protects your homelab from power outages, surges, and brownouts. It provides battery backup to keep your servers running long enough to shut down gracefully, preventing data corruption, &lt;span class="caps"&gt;ZFS&lt;/span&gt; pool degradation, and database damage. &lt;span class="caps"&gt;APC&lt;/span&gt; is the most trusted &lt;span class="caps"&gt;UPS&lt;/span&gt; brand for homelab and small business&amp;nbsp;use.&lt;/p&gt;
&lt;h3&gt;Key&amp;nbsp;Benefits&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Graceful shutdowns:&lt;/strong&gt; When power fails, the &lt;span class="caps"&gt;UPS&lt;/span&gt; signals your server to shut down before the battery&amp;nbsp;depletes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Surge protection:&lt;/strong&gt; Absorbs voltage spikes from lightning or grid&amp;nbsp;instability.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Voltage regulation:&lt;/strong&gt; Automatic Voltage Regulation (&lt;span class="caps"&gt;AVR&lt;/span&gt;) corrects brownouts without switching to&amp;nbsp;battery.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Power monitoring:&lt;/strong&gt; &lt;span class="caps"&gt;LCD&lt;/span&gt; displays show load percentage, runtime, and battery&amp;nbsp;health.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;NUT&lt;/span&gt; compatibility:&lt;/strong&gt; &lt;span class="caps"&gt;APC&lt;/span&gt; &lt;span class="caps"&gt;UPS&lt;/span&gt; units work seamlessly with Network &lt;span class="caps"&gt;UPS&lt;/span&gt; Tools (&lt;span class="caps"&gt;NUT&lt;/span&gt;) on Linux and&amp;nbsp;Proxmox.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Evaluation&amp;nbsp;Criteria&lt;/h2&gt;
&lt;h3&gt;Price-to-Performance&lt;/h3&gt;
&lt;p&gt;&lt;span class="caps"&gt;APC&lt;/span&gt; offers a wide range of &lt;span class="caps"&gt;UPS&lt;/span&gt; units. For homelab use, the sweet spot is the &lt;strong&gt;Back-&lt;span class="caps"&gt;UPS&lt;/span&gt; Pro&lt;/strong&gt; line (&lt;span class="caps"&gt;BR1500G&lt;/span&gt;, &lt;span class="caps"&gt;BR1500MS&lt;/span&gt;) for tower setups and the &lt;strong&gt;Smart-&lt;span class="caps"&gt;UPS&lt;/span&gt;&lt;/strong&gt; line (&lt;span class="caps"&gt;SMT1500RM2U&lt;/span&gt;) for rackmount&amp;nbsp;setups.&lt;/p&gt;
&lt;h3&gt;Feature&amp;nbsp;Set&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Back-&lt;span class="caps"&gt;UPS&lt;/span&gt; Pro&lt;/th&gt;
&lt;th&gt;Smart-&lt;span class="caps"&gt;UPS&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;VA&lt;/span&gt; / Watt&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1500 &lt;span class="caps"&gt;VA&lt;/span&gt; / 865 W&lt;/td&gt;
&lt;td&gt;1500 &lt;span class="caps"&gt;VA&lt;/span&gt; / 1000 W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Topology&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Line-interactive&lt;/td&gt;
&lt;td&gt;Line-interactive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;AVR&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;LCD&lt;/span&gt; display&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;USB&lt;/span&gt; management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Network card (&lt;span class="caps"&gt;SNMP&lt;/span&gt;)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Optional&lt;/td&gt;
&lt;td&gt;Optional&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rackmount form&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅ (2U)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Pure sine wave&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅ (&lt;span class="caps"&gt;SMT&lt;/span&gt;/&lt;span class="caps"&gt;SMX&lt;/span&gt; lines)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;External battery&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅ (&lt;span class="caps"&gt;EBM&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Community &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;Support&lt;/h3&gt;
&lt;p&gt;&lt;span class="caps"&gt;APC&lt;/span&gt; has the largest &lt;span class="caps"&gt;UPS&lt;/span&gt; community. &lt;span class="caps"&gt;NUT&lt;/span&gt; drivers support nearly every &lt;span class="caps"&gt;APC&lt;/span&gt; model. Replacement batteries (&lt;span class="caps"&gt;RBC123&lt;/span&gt;, &lt;span class="caps"&gt;RBC7&lt;/span&gt;, &lt;span class="caps"&gt;RBC55&lt;/span&gt;) are widely available and easy to&amp;nbsp;install.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;#1: &lt;span class="caps"&gt;APC&lt;/span&gt; Back-&lt;span class="caps"&gt;UPS&lt;/span&gt; Pro &lt;span class="caps"&gt;BR1500G&lt;/span&gt;&lt;/h2&gt;
&lt;h3&gt;Why It Tops Our&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;The &lt;span class="caps"&gt;BR1500G&lt;/span&gt; is the most popular homelab &lt;span class="caps"&gt;UPS&lt;/span&gt;. It provides 1500 &lt;span class="caps"&gt;VA&lt;/span&gt; / 865 W, 10 outlets (5 battery + 5 surge), and a &lt;span class="caps"&gt;USB&lt;/span&gt; port for &lt;span class="caps"&gt;NUT&lt;/span&gt; integration. The &lt;span class="caps"&gt;LCD&lt;/span&gt; display shows real-time load, runtime estimate, and battery&amp;nbsp;health.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;VA&lt;/span&gt; / Watt&lt;/td&gt;
&lt;td&gt;1500 &lt;span class="caps"&gt;VA&lt;/span&gt; / 865 W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Outlets&lt;/td&gt;
&lt;td&gt;10 (5 battery + 5 surge)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runtime @ 50% load&lt;/td&gt;
&lt;td&gt;~12 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;USB&lt;/span&gt; port&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;USB&lt;/span&gt;-B (for &lt;span class="caps"&gt;NUT&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network card&lt;/td&gt;
&lt;td&gt;Optional (&lt;span class="caps"&gt;AP9640&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Display&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;LCD&lt;/span&gt; with load/runtime&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Form factor&lt;/td&gt;
&lt;td&gt;Tower&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Warranty&lt;/td&gt;
&lt;td&gt;3 years&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Affordable&amp;nbsp;(~$180–220).&lt;/li&gt;
&lt;li&gt;Hot-swappable battery (&lt;span class="caps"&gt;RBC123&lt;/span&gt;).&lt;/li&gt;
&lt;li&gt;PowerChute software for Windows; &lt;span class="caps"&gt;NUT&lt;/span&gt; for&amp;nbsp;Linux/Proxmox.&lt;/li&gt;
&lt;li&gt;Enough outlets for a mini &lt;span class="caps"&gt;PC&lt;/span&gt;, switch, router, and&amp;nbsp;modem.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;865 W is not enough for dual-socket servers or high-wattage&amp;nbsp;GPUs.&lt;/li&gt;
&lt;li&gt;No pure sine wave (stepped approximation). Most Active &lt;span class="caps"&gt;PFC&lt;/span&gt; PSUs work fine, but some high-end units may&amp;nbsp;complain.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Small-to-medium homelabs with a total load under 500&amp;nbsp;W.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;New:&lt;/strong&gt; $180–220 &lt;span class="caps"&gt;USD&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Replacement battery (&lt;span class="caps"&gt;RBC123&lt;/span&gt;):&lt;/strong&gt;&amp;nbsp;$40–60&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;#2: &lt;span class="caps"&gt;APC&lt;/span&gt; Back-&lt;span class="caps"&gt;UPS&lt;/span&gt; Pro &lt;span class="caps"&gt;BR1500MS&lt;/span&gt;&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;The &lt;span class="caps"&gt;BR1500MS&lt;/span&gt; is the newer version of the &lt;span class="caps"&gt;BR1500G&lt;/span&gt; with a &lt;strong&gt;sinewave inverter&lt;/strong&gt;, &lt;span class="caps"&gt;USB&lt;/span&gt;-C charging port, and &lt;span class="caps"&gt;AVR&lt;/span&gt;. It is the best &lt;span class="caps"&gt;APC&lt;/span&gt; &lt;span class="caps"&gt;UPS&lt;/span&gt; for modern Active &lt;span class="caps"&gt;PFC&lt;/span&gt; power&amp;nbsp;supplies.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;VA&lt;/span&gt; / Watt&lt;/td&gt;
&lt;td&gt;1500 &lt;span class="caps"&gt;VA&lt;/span&gt; / 900 W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Outlets&lt;/td&gt;
&lt;td&gt;10 (5 battery + 5 surge)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runtime @ 50% load&lt;/td&gt;
&lt;td&gt;~11 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;USB&lt;/span&gt; port&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;USB&lt;/span&gt;-B + &lt;span class="caps"&gt;USB&lt;/span&gt;-C (charging)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Display&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;LCD&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Form factor&lt;/td&gt;
&lt;td&gt;Tower&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Pure sine wave output — safe for all &lt;span class="caps"&gt;PSU&lt;/span&gt;&amp;nbsp;types.&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;USB&lt;/span&gt;-C port for charging laptops or phones during&amp;nbsp;outages.&lt;/li&gt;
&lt;li&gt;Slightly higher wattage than the &lt;span class="caps"&gt;BR1500G&lt;/span&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;More expensive than the &lt;span class="caps"&gt;BR1500G&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;Battery is not hot-swappable (internal replacement&amp;nbsp;required).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Users with Active &lt;span class="caps"&gt;PFC&lt;/span&gt; power supplies who want the safest&amp;nbsp;waveform.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;New:&lt;/strong&gt; $220–260 &lt;span class="caps"&gt;USD&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;#3: &lt;span class="caps"&gt;APC&lt;/span&gt; Smart-&lt;span class="caps"&gt;UPS&lt;/span&gt; &lt;span class="caps"&gt;SMT1500RM2U&lt;/span&gt;&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;For rack homelabs, the &lt;span class="caps"&gt;SMT1500RM2U&lt;/span&gt; is the standard. It provides 1500 &lt;span class="caps"&gt;VA&lt;/span&gt; / 1000 W in a 2U rackmount form factor, with optional &lt;span class="caps"&gt;SNMP&lt;/span&gt; network management and external battery&amp;nbsp;packs.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;VA&lt;/span&gt; / Watt&lt;/td&gt;
&lt;td&gt;1500 &lt;span class="caps"&gt;VA&lt;/span&gt; / 1000 W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Outlets&lt;/td&gt;
&lt;td&gt;8 (all battery-backed)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runtime @ 50% load&lt;/td&gt;
&lt;td&gt;~18 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network card&lt;/td&gt;
&lt;td&gt;Optional (&lt;span class="caps"&gt;AP9640&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Form factor&lt;/td&gt;
&lt;td&gt;2U rackmount&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;External battery&lt;/td&gt;
&lt;td&gt;✅ (&lt;span class="caps"&gt;SURT48XLBP&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Rackmount form factor fits standard 19&amp;#8221;&amp;nbsp;racks.&lt;/li&gt;
&lt;li&gt;Higher wattage supports dual-socket&amp;nbsp;servers.&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;SNMP&lt;/span&gt; network card enables remote monitoring and email&amp;nbsp;alerts.&lt;/li&gt;
&lt;li&gt;Pure sine wave&amp;nbsp;output.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Loud fans (40–50&amp;nbsp;dB).&lt;/li&gt;
&lt;li&gt;Heavy (~30&amp;nbsp;kg).&lt;/li&gt;
&lt;li&gt;Expensive&amp;nbsp;($600–800).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Rack homelabs with 500–800 W&amp;nbsp;loads.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;New:&lt;/strong&gt; $600–800 &lt;span class="caps"&gt;USD&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Used (eBay):&lt;/strong&gt;&amp;nbsp;$250–400&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;#4: &lt;span class="caps"&gt;APC&lt;/span&gt; Back-&lt;span class="caps"&gt;UPS&lt;/span&gt; &lt;span class="caps"&gt;BX1500M&lt;/span&gt;&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;The &lt;span class="caps"&gt;BX1500M&lt;/span&gt; is the budget alternative to the &lt;span class="caps"&gt;BR1500G&lt;/span&gt;. It provides 1500 &lt;span class="caps"&gt;VA&lt;/span&gt; / 900 W with &lt;span class="caps"&gt;AVR&lt;/span&gt; but lacks the &lt;span class="caps"&gt;LCD&lt;/span&gt; display and some premium&amp;nbsp;features.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;VA&lt;/span&gt; / Watt&lt;/td&gt;
&lt;td&gt;1500 &lt;span class="caps"&gt;VA&lt;/span&gt; / 900 W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Outlets&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runtime @ 50% load&lt;/td&gt;
&lt;td&gt;~10 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Display&lt;/td&gt;
&lt;td&gt;LEDs only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Form factor&lt;/td&gt;
&lt;td&gt;Tower&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Cheaper than the &lt;span class="caps"&gt;BR1500G&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;Same wattage and outlet&amp;nbsp;count.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;No &lt;span class="caps"&gt;LCD&lt;/span&gt; display (LEDs only show battery&amp;nbsp;status).&lt;/li&gt;
&lt;li&gt;No network card&amp;nbsp;option.&lt;/li&gt;
&lt;li&gt;Step-approximated sine&amp;nbsp;wave.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Budget homelabs that do not need &lt;span class="caps"&gt;LCD&lt;/span&gt;&amp;nbsp;monitoring.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;New:&lt;/strong&gt; $140–170 &lt;span class="caps"&gt;USD&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;#5: &lt;span class="caps"&gt;APC&lt;/span&gt; Smart-&lt;span class="caps"&gt;UPS&lt;/span&gt; &lt;span class="caps"&gt;SMC1500C&lt;/span&gt;&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;The &lt;span class="caps"&gt;SMC1500C&lt;/span&gt; is a compact Smart-&lt;span class="caps"&gt;UPS&lt;/span&gt; tower with pure sine wave, &lt;span class="caps"&gt;LCD&lt;/span&gt;, and cloud monitoring via &lt;span class="caps"&gt;APC&lt;/span&gt;&amp;#8217;s SmartConnect&amp;nbsp;service.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;VA&lt;/span&gt; / Watt&lt;/td&gt;
&lt;td&gt;1500 &lt;span class="caps"&gt;VA&lt;/span&gt; / 900 W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Outlets&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runtime @ 50% load&lt;/td&gt;
&lt;td&gt;~12 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Display&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;LCD&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloud monitoring&lt;/td&gt;
&lt;td&gt;SmartConnect (optional)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Form factor&lt;/td&gt;
&lt;td&gt;Tower&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Pure sine&amp;nbsp;wave.&lt;/li&gt;
&lt;li&gt;Cloud monitoring without a network card (via&amp;nbsp;Ethernet).&lt;/li&gt;
&lt;li&gt;SmartConnect sends mobile alerts for&amp;nbsp;outages.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;SmartConnect requires internet and an &lt;span class="caps"&gt;APC&lt;/span&gt;&amp;nbsp;account.&lt;/li&gt;
&lt;li&gt;Slightly more expensive than the &lt;span class="caps"&gt;BR1500G&lt;/span&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Users who want remote monitoring without buying a network&amp;nbsp;card.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;New:&lt;/strong&gt; $250–300 &lt;span class="caps"&gt;USD&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Quick Comparison&amp;nbsp;Table&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;VA&lt;/span&gt; / Watt&lt;/th&gt;
&lt;th&gt;Outlets&lt;/th&gt;
&lt;th&gt;Runtime @ 50%&lt;/th&gt;
&lt;th&gt;Pure Sine&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;LCD&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Rackmount&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;BR1500G&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1500 / 865&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;~12 min&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;$180–220&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;BR1500MS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1500 / 900&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;~11 min&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;$220–260&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;SMT1500RM2U&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1500 / 1000&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;~18 min&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;$600–800&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;BX1500M&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1500 / 900&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;~10 min&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;$140–170&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;SMC1500C&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1500 / 900&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;~12 min&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;$250–300&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Calculate Your Load Before&amp;nbsp;Buying&lt;/h3&gt;
&lt;p&gt;Use a Kill-A-Watt meter&amp;nbsp;or &lt;code&gt;powertop&lt;/code&gt; to measure your homelab&amp;#8217;s actual wattage. Add 20%&amp;nbsp;headroom.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Estimate power on Linux&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;powertop
powertop
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 2: Use &lt;span class="caps"&gt;NUT&lt;/span&gt; for Automated&amp;nbsp;Shutdown&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Install NUT on Proxmox&lt;/span&gt;
apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;nut
&lt;span class="c1"&gt;# Edit /etc/nut/ups.conf to add your APC UPS (usbhid-ups driver)&lt;/span&gt;
&lt;span class="c1"&gt;# Edit /etc/nut/upsmon.conf to set shutdown threshold (e.g., 20% battery)&lt;/span&gt;
systemctl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;nut-client
systemctl&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;nut-client
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 3: Replace Batteries Every 3–5&amp;nbsp;Years&lt;/h3&gt;
&lt;p&gt;&lt;span class="caps"&gt;SLA&lt;/span&gt; batteries degrade. A 5-year-old battery may provide only 2 minutes of runtime. Replace proactively with genuine &lt;span class="caps"&gt;APC&lt;/span&gt; &lt;span class="caps"&gt;RBC&lt;/span&gt; batteries or compatible third-party&amp;nbsp;packs.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;For most homelabbers, the &lt;strong&gt;&lt;span class="caps"&gt;APC&lt;/span&gt; Back-&lt;span class="caps"&gt;UPS&lt;/span&gt; Pro &lt;span class="caps"&gt;BR1500G&lt;/span&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;span class="caps"&gt;BR1500MS&lt;/span&gt;&lt;/strong&gt; is the ideal choice. They offer enough wattage for a mini &lt;span class="caps"&gt;PC&lt;/span&gt; or tower server, &lt;span class="caps"&gt;USB&lt;/span&gt; monitoring, and &lt;span class="caps"&gt;NUT&lt;/span&gt; compatibility. For rack servers, the &lt;strong&gt;Smart-&lt;span class="caps"&gt;UPS&lt;/span&gt; &lt;span class="caps"&gt;SMT1500RM2U&lt;/span&gt;&lt;/strong&gt; is the professional standard. Budget users can start with the &lt;strong&gt;&lt;span class="caps"&gt;BX1500M&lt;/span&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;Our&amp;nbsp;Recommendation&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mini &lt;span class="caps"&gt;PC&lt;/span&gt; homelab (1 node):&lt;/strong&gt; &lt;span class="caps"&gt;BR1500G&lt;/span&gt; or &lt;span class="caps"&gt;BR1500MS&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tower server / &lt;span class="caps"&gt;NAS&lt;/span&gt; (2–3 nodes):&lt;/strong&gt; &lt;span class="caps"&gt;BR1500MS&lt;/span&gt; (pure sine&amp;nbsp;wave)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rack server (500+ W):&lt;/strong&gt; &lt;span class="caps"&gt;SMT1500RM2U&lt;/span&gt; + external battery&amp;nbsp;pack&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;APC&lt;/span&gt; &lt;span class="caps"&gt;UPS&lt;/span&gt; units:&lt;/strong&gt; Amazon, B&amp;amp;H, Newegg affiliate&amp;nbsp;links&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Replacement batteries:&lt;/strong&gt; &lt;span class="caps"&gt;RBC123&lt;/span&gt;, &lt;span class="caps"&gt;RBC7&lt;/span&gt;, &lt;span class="caps"&gt;RBC55&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Kill-A-Watt meters:&lt;/strong&gt; For load&amp;nbsp;measurement&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;NUT&lt;/span&gt; accessories:&lt;/strong&gt; &lt;span class="caps"&gt;USB&lt;/span&gt; cables, network&amp;nbsp;cards&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;why-this-matters&lt;/code&gt; → &lt;code&gt;ups-for-homelab&lt;/code&gt; — &amp;#8220;general &lt;span class="caps"&gt;UPS&lt;/span&gt; buying&amp;nbsp;guide&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;item-1&lt;/code&gt; → &lt;code&gt;best-ups-for-home-server&lt;/code&gt; — &amp;#8220;&lt;span class="caps"&gt;UPS&lt;/span&gt; recommendations for home&amp;nbsp;servers&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;proxmox-beginner-guide-2026&lt;/code&gt; — &amp;#8220;protect your Proxmox host with a &lt;span class="caps"&gt;UPS&lt;/span&gt;&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;What &lt;span class="caps"&gt;APC&lt;/span&gt; &lt;span class="caps"&gt;UPS&lt;/span&gt; runs your lab?&lt;/strong&gt; Share your model and runtime in the&amp;nbsp;comments.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subscribe&lt;/strong&gt; for power efficiency guides, &lt;span class="caps"&gt;UPS&lt;/span&gt; reviews, and homelab safety&amp;nbsp;tips.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Guides"/><category term="apc ups"/><category term="homelab"/><category term="power protection"/><category term="uninterruptible power supply"/><category term="backup power"/><category term="apc back-ups"/></entry><entry><title>Beelink Mini PC Proxmox: The Ultimate Self-Hosted Guide for 2026</title><link href="https://steadypub.com/2026/06/beelink-mini-pc-proxmox/" rel="alternate"/><published>2026-06-05T00:00:00+07:00</published><updated>2026-06-05T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/beelink-mini-pc-proxmox/</id><summary type="html">&lt;p&gt;A step-by-step guide to installing Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; on Beelink mini PCs (&lt;span class="caps"&gt;SER5&lt;/span&gt;, &lt;span class="caps"&gt;SER6&lt;/span&gt;, U59). Covers &lt;span class="caps"&gt;BIOS&lt;/span&gt; tweaks, &lt;span class="caps"&gt;NIC&lt;/span&gt; quirks, storage setup, and first &lt;span class="caps"&gt;VM&lt;/span&gt;&amp;nbsp;creation.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~12 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelabbers turning a Beelink mini &lt;span class="caps"&gt;PC&lt;/span&gt; into a Proxmox&amp;nbsp;node&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is Beelink Mini &lt;span class="caps"&gt;PC&lt;/span&gt;&amp;nbsp;Proxmox?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Beelink is a leading Chinese manufacturer of compact, power-efficient mini PCs. Models like the &lt;strong&gt;&lt;span class="caps"&gt;SER5&lt;/span&gt;&lt;/strong&gt; (&lt;span class="caps"&gt;AMD&lt;/span&gt; Ryzen 5 5560U), &lt;strong&gt;&lt;span class="caps"&gt;SER6&lt;/span&gt;&lt;/strong&gt; (Ryzen 7 &lt;span class="caps"&gt;7735HS&lt;/span&gt;), and &lt;strong&gt;U59&lt;/strong&gt; (Intel N5105) are popular homelab choices because they cost $150–$400, idle at 6–15W, and fit in a network closet. Installing Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; turns these tiny boxes into full-featured virtualization hosts capable of running 5–15 VMs or dozens of &lt;span class="caps"&gt;LXC&lt;/span&gt;&amp;nbsp;containers.&lt;/p&gt;
&lt;h3&gt;A Brief&amp;nbsp;History&lt;/h3&gt;
&lt;p&gt;Beelink gained traction in the homelab community around 2022 after the Intel &lt;span class="caps"&gt;NUC&lt;/span&gt; supply crunch. The &lt;span class="caps"&gt;SER5&lt;/span&gt; and &lt;span class="caps"&gt;SER6&lt;/span&gt; series became the &amp;#8220;go-to&amp;#8221; for budget Proxmox builds because they offer 6–8 core CPUs, &lt;span class="caps"&gt;DDR4&lt;/span&gt; &lt;span class="caps"&gt;SODIMM&lt;/span&gt; slots, and NVMe storage at half the price of a &lt;span class="caps"&gt;NUC&lt;/span&gt;. However, Proxmox installation on Beelink hardware requires &lt;span class="caps"&gt;BIOS&lt;/span&gt; tweaks and &lt;span class="caps"&gt;NIC&lt;/span&gt; driver awareness that standard guides&amp;nbsp;skip.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why Use Beelink Mini &lt;span class="caps"&gt;PC&lt;/span&gt;&amp;nbsp;Proxmox?&lt;/h2&gt;
&lt;h3&gt;Benefit 1: Extreme Power&amp;nbsp;Efficiency&lt;/h3&gt;
&lt;p&gt;A Beelink &lt;span class="caps"&gt;SER6&lt;/span&gt; idles at 8–12W. Under full &lt;span class="caps"&gt;CPU&lt;/span&gt; load, it peaks at 35–45W. Compare that to a used Dell R720 at 80–120W. Over a year, the Beelink costs about $12–18 in electricity, while the R720 costs $90–130. For a small homelab, the Beelink pays for itself in power savings within 18&amp;nbsp;months.&lt;/p&gt;
&lt;h3&gt;Benefit 2: Silent&amp;nbsp;Operation&lt;/h3&gt;
&lt;p&gt;Beelink mini PCs use laptop-style cooling: a single heat pipe and a small blower fan. At idle, they are nearly silent (20–25 dB). Even under load, they are quieter than any rack server. This makes them ideal for living rooms, apartments, or&amp;nbsp;offices.&lt;/p&gt;
&lt;h3&gt;Benefit 3: Low Cost of&amp;nbsp;Entry&lt;/h3&gt;
&lt;p&gt;A used &lt;span class="caps"&gt;SER5&lt;/span&gt; with 16 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; and a 512 &lt;span class="caps"&gt;GB&lt;/span&gt; NVMe costs $180–250. That is less than a single enterprise &lt;span class="caps"&gt;CPU&lt;/span&gt;. You can build a 2-node Proxmox cluster for under $500, complete with Ceph or &lt;span class="caps"&gt;ZFS&lt;/span&gt;&amp;nbsp;replication.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;h3&gt;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Beelink mini &lt;span class="caps"&gt;PC&lt;/span&gt; (&lt;span class="caps"&gt;SER5&lt;/span&gt;, &lt;span class="caps"&gt;SER6&lt;/span&gt;, U59, or&amp;nbsp;equivalent)&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;USB&lt;/span&gt; flash drive (8 &lt;span class="caps"&gt;GB&lt;/span&gt;+)&lt;/li&gt;
&lt;li&gt;Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; 8.2 &lt;span class="caps"&gt;ISO&lt;/span&gt; (download from &lt;a href="https://www.proxmox.com"&gt;proxmox.com&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;BalenaEtcher or Rufus (to write the &lt;span class="caps"&gt;ISO&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;Keyboard and monitor (for initial &lt;span class="caps"&gt;BIOS&lt;/span&gt;/Proxmox install&amp;nbsp;only)&lt;/li&gt;
&lt;li&gt;Ethernet cable (Wi-Fi is not recommended for Proxmox&amp;nbsp;hosts)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Method 1: Standard&amp;nbsp;Installation&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Download the Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; &lt;span class="caps"&gt;ISO&lt;/span&gt;&lt;/strong&gt; and write it to the &lt;span class="caps"&gt;USB&lt;/span&gt; drive with&amp;nbsp;BalenaEtcher.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Plug the &lt;span class="caps"&gt;USB&lt;/span&gt; into the Beelink&lt;/strong&gt; and power on.&amp;nbsp;Press &lt;code&gt;F7&lt;/code&gt; (or &lt;code&gt;Del&lt;/code&gt; to enter &lt;span class="caps"&gt;BIOS&lt;/span&gt;) to select the &lt;span class="caps"&gt;USB&lt;/span&gt; boot&amp;nbsp;device.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;In the &lt;span class="caps"&gt;BIOS&lt;/span&gt;&lt;/strong&gt;, make the following&amp;nbsp;changes:&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Boot Mode&lt;/strong&gt;: &lt;span class="caps"&gt;UEFI&lt;/span&gt; (disable Legacy/&lt;span class="caps"&gt;CSM&lt;/span&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Secure Boot&lt;/strong&gt;:&amp;nbsp;Disable.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;VT&lt;/span&gt;-d / &lt;span class="caps"&gt;AMD&lt;/span&gt;-Vi&lt;/strong&gt;: Enable (for &lt;span class="caps"&gt;PCI&lt;/span&gt; passthrough&amp;nbsp;later).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Above 4G Decoding&lt;/strong&gt;: Enable (if available, helps with &lt;span class="caps"&gt;GPU&lt;/span&gt;&amp;nbsp;passthrough).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Watchdog&lt;/strong&gt;: Disable (can cause unexpected reboots on some Beelink&amp;nbsp;units).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Boot the Proxmox installer&lt;/strong&gt;. Choose &amp;#8220;Install Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;.&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Disk selection&lt;/strong&gt;: Select the internal NVMe or &lt;span class="caps"&gt;SSD&lt;/span&gt;. If you have two drives (e.g., NVMe + &lt;span class="caps"&gt;SATA&lt;/span&gt;), you can install Proxmox on the smaller drive and use the larger for &lt;span class="caps"&gt;VM&lt;/span&gt;&amp;nbsp;storage.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Network config&lt;/strong&gt;: Set a static &lt;span class="caps"&gt;IP&lt;/span&gt;.&amp;nbsp;Use &lt;code&gt;enp1s0&lt;/code&gt; or &lt;code&gt;eno1&lt;/code&gt; as the primary interface. Note that Realtek NICs on some Beelink models may show&amp;nbsp;as &lt;code&gt;r8169&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Finish the install&lt;/strong&gt;. Reboot and remove the &lt;span class="caps"&gt;USB&lt;/span&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Method 2: Headless Installation&amp;nbsp;(Advanced)&lt;/h3&gt;
&lt;p&gt;If you cannot attach a monitor, you can install Debian 12 via preseed, then add the Proxmox repo. This is not recommended for beginners, but it&amp;nbsp;works:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# After Debian 12 minimal install&lt;/span&gt;
su&lt;span class="w"&gt; &lt;/span&gt;-
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;deb http://download.proxmox.com/debian/pve bookworm pve-no-subscription&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/apt/sources.list.d/pve.list
wget&lt;span class="w"&gt; &lt;/span&gt;https://enterprise.proxmox.com/debian/proxmox-release-bookworm.gpg&lt;span class="w"&gt; &lt;/span&gt;-O&lt;span class="w"&gt; &lt;/span&gt;/etc/apt/keyrings/proxmox-release-bookworm.gpg
apt&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;proxmox-ve
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Basic Setup and&amp;nbsp;Configuration&lt;/h2&gt;
&lt;h3&gt;Step 1: First Boot and Web &lt;span class="caps"&gt;UI&lt;/span&gt;&amp;nbsp;Access&lt;/h3&gt;
&lt;p&gt;After installation, the Beelink will boot into the Proxmox console. The screen shows the &lt;span class="caps"&gt;IP&lt;/span&gt; address. From another computer,&amp;nbsp;open:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;https://192.168.1.100:8006
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Log in&amp;nbsp;with &lt;code&gt;root&lt;/code&gt; and the password you set during&amp;nbsp;install.&lt;/p&gt;
&lt;h3&gt;Step 2: Update&amp;nbsp;Proxmox&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# On the Proxmox shell (or via web UI -&amp;gt; Shell)&lt;/span&gt;
apt&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;dist-upgrade&lt;span class="w"&gt; &lt;/span&gt;-y
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Step 3: Fix Realtek &lt;span class="caps"&gt;NIC&lt;/span&gt;&amp;nbsp;Stability&lt;/h3&gt;
&lt;p&gt;Some Beelink models (especially U59 and early &lt;span class="caps"&gt;SER5&lt;/span&gt;) use Realtek &lt;span class="caps"&gt;RTL8111H&lt;/span&gt; NICs that can drop packets under load. Proxmox uses&amp;nbsp;the &lt;code&gt;r8169&lt;/code&gt; driver by default, but&amp;nbsp;the &lt;code&gt;r8168&lt;/code&gt; driver is more&amp;nbsp;stable.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Install the r8168 driver from the Proxmox repo or compile it&lt;/span&gt;
apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;r8168-dkms
&lt;span class="c1"&gt;# Blacklist the old driver&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;blacklist r8169&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/modprobe.d/blacklist.conf
update-initramfs&lt;span class="w"&gt; &lt;/span&gt;-u
reboot
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After reboot,&amp;nbsp;verify:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ethtool&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;enp1s0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;driver
&lt;span class="c1"&gt;# Should show r8168&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Step 4: Configure&amp;nbsp;Storage&lt;/h3&gt;
&lt;p&gt;Beelink units often have one NVMe and one &lt;span class="caps"&gt;SATA&lt;/span&gt; M.2 or 2.5&amp;#8221; bay. Use the NVMe for Proxmox &lt;span class="caps"&gt;OS&lt;/span&gt; and &lt;span class="caps"&gt;VM&lt;/span&gt; disks, and the &lt;span class="caps"&gt;SATA&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt; for backups or &lt;span class="caps"&gt;ISO&lt;/span&gt;&amp;nbsp;storage.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# List disks&lt;/span&gt;
lsblk
&lt;span class="c1"&gt;# Create a ZFS pool on the second SSD (optional)&lt;/span&gt;
zpool&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;tank&lt;span class="w"&gt; &lt;/span&gt;/dev/sdb
&lt;span class="c1"&gt;# Or add it as an LVM thin pool&lt;/span&gt;
pvcreate&lt;span class="w"&gt; &lt;/span&gt;/dev/sdb
vgcreate&lt;span class="w"&gt; &lt;/span&gt;vm-data&lt;span class="w"&gt; &lt;/span&gt;/dev/sdb
lvcreate&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;%FREE&lt;span class="w"&gt; &lt;/span&gt;-T&lt;span class="w"&gt; &lt;/span&gt;vm-data/thin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the Proxmox web &lt;span class="caps"&gt;UI&lt;/span&gt;, go to &lt;strong&gt;Datacenter → Storage&lt;/strong&gt; and add the new&amp;nbsp;pool.&lt;/p&gt;
&lt;h3&gt;Step 5: Enable Nested Virtualization (for &lt;span class="caps"&gt;LXC&lt;/span&gt; or test&amp;nbsp;VMs)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Check if nested is enabled&lt;/span&gt;
cat&lt;span class="w"&gt; &lt;/span&gt;/sys/module/kvm_intel/parameters/nested
&lt;span class="c1"&gt;# If N, enable it:&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;options kvm_intel nested=1&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/modprobe.d/kvm-nested.conf
modprobe&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="w"&gt; &lt;/span&gt;kvm_intel&lt;span class="w"&gt; &lt;/span&gt;kvm
modprobe&lt;span class="w"&gt; &lt;/span&gt;kvm_intel
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Advanced&amp;nbsp;Features&lt;/h2&gt;
&lt;h3&gt;Feature 1: &lt;span class="caps"&gt;GPU&lt;/span&gt; Passthrough (&lt;span class="caps"&gt;AMD&lt;/span&gt;&amp;nbsp;iGPU)&lt;/h3&gt;
&lt;p&gt;Beelink &lt;span class="caps"&gt;SER5&lt;/span&gt;/&lt;span class="caps"&gt;SER6&lt;/span&gt; use &lt;span class="caps"&gt;AMD&lt;/span&gt; Radeon integrated graphics. You can passthrough the iGPU to a Windows &lt;span class="caps"&gt;VM&lt;/span&gt; for light gaming or to a Linux &lt;span class="caps"&gt;VM&lt;/span&gt; for&amp;nbsp;transcoding.&lt;/p&gt;
&lt;p&gt;Requirements:
- Enable &lt;strong&gt;&lt;span class="caps"&gt;AMD&lt;/span&gt;-Vi&lt;/strong&gt; and &lt;strong&gt;&lt;span class="caps"&gt;IOMMU&lt;/span&gt;&lt;/strong&gt; in &lt;span class="caps"&gt;BIOS&lt;/span&gt;.
-&amp;nbsp;Add &lt;code&gt;amd_iommu=on&lt;/code&gt; to &lt;span class="caps"&gt;GRUB&lt;/span&gt;.
- Blacklist&amp;nbsp;the &lt;code&gt;amdgpu&lt;/code&gt; driver on the&amp;nbsp;host.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# /etc/default/grub&lt;/span&gt;
&lt;span class="nv"&gt;GRUB_CMDLINE_LINUX_DEFAULT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;quiet amd_iommu=on iommu=pt&amp;quot;&lt;/span&gt;
update-grub
reboot
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In Proxmox, add the &lt;span class="caps"&gt;PCI&lt;/span&gt; device to the &lt;span class="caps"&gt;VM&lt;/span&gt; (via web &lt;span class="caps"&gt;UI&lt;/span&gt; → Hardware → Add → &lt;span class="caps"&gt;PCI&lt;/span&gt; Device).&amp;nbsp;Use &lt;code&gt;rombar=0&lt;/code&gt; if the &lt;span class="caps"&gt;VM&lt;/span&gt;&amp;nbsp;hangs.&lt;/p&gt;
&lt;h3&gt;Feature 2: &lt;span class="caps"&gt;USB&lt;/span&gt; Passthrough for&amp;nbsp;Zigbee/Z-Wave&lt;/h3&gt;
&lt;p&gt;Beelink units have 4–6 &lt;span class="caps"&gt;USB&lt;/span&gt; ports. You can pass &lt;span class="caps"&gt;USB&lt;/span&gt; devices directly to VMs or &lt;span class="caps"&gt;LXC&lt;/span&gt; containers. For a Home Assistant &lt;span class="caps"&gt;VM&lt;/span&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# On Proxmox host&lt;/span&gt;
lsusb
&lt;span class="c1"&gt;# Find your Zigbee coordinator (e.g., Silicon Labs CP210x)&lt;/span&gt;
&lt;span class="c1"&gt;# In VM Hardware -&amp;gt; Add USB Device -&amp;gt; Use Port or Vendor ID&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Feature 3: Power&amp;nbsp;Management&lt;/h3&gt;
&lt;p&gt;Set &lt;span class="caps"&gt;CPU&lt;/span&gt; governor&amp;nbsp;to &lt;code&gt;powersave&lt;/code&gt; for lower heat and&amp;nbsp;noise:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;cpufrequtils
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;GOVERNOR=&amp;quot;powersave&amp;quot;&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/default/cpufrequtils
systemctl&lt;span class="w"&gt; &lt;/span&gt;restart&lt;span class="w"&gt; &lt;/span&gt;cpufrequtils
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For &lt;span class="caps"&gt;AMD&lt;/span&gt; Ryzen,&amp;nbsp;install &lt;code&gt;amd-pstate&lt;/code&gt; driver if supported by your kernel for better frequency&amp;nbsp;scaling.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Integrating with Your&amp;nbsp;Homelab&lt;/h2&gt;
&lt;h3&gt;Integration 1: Proxmox&amp;nbsp;Cluster&lt;/h3&gt;
&lt;p&gt;You can cluster multiple Beelink units for &lt;span class="caps"&gt;HA&lt;/span&gt;. Each node needs a unique hostname, static &lt;span class="caps"&gt;IP&lt;/span&gt;, and matching Proxmox&amp;nbsp;version.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# On the first node&lt;/span&gt;
pvecm&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;beelink-cluster
&lt;span class="c1"&gt;# On the second node&lt;/span&gt;
pvecm&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.10.10
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt; A 2-node cluster is not recommended for &lt;span class="caps"&gt;HA&lt;/span&gt; (quorum issues). Use a third node (even a Raspberry Pi with qdevice) or set expected votes to&amp;nbsp;1.&lt;/p&gt;
&lt;h3&gt;Integration 2: Backup to &lt;span class="caps"&gt;NAS&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Use Proxmox Backup Server&amp;nbsp;or &lt;code&gt;vzdump&lt;/code&gt; to a Synology/&lt;span class="caps"&gt;NAS&lt;/span&gt;&amp;nbsp;share:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Mount an NFS share&lt;/span&gt;
mkdir&lt;span class="w"&gt; &lt;/span&gt;/mnt/nfs-backup
mount&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;nfs&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.10.5:/volume1/backup&lt;span class="w"&gt; &lt;/span&gt;/mnt/nfs-backup
&lt;span class="c1"&gt;# Add to /etc/fstab for persistence&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the web &lt;span class="caps"&gt;UI&lt;/span&gt;, add &lt;strong&gt;Datacenter → Storage → &lt;span class="caps"&gt;NFS&lt;/span&gt;&lt;/strong&gt; pointing to the&amp;nbsp;share.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Alternatives to&amp;nbsp;Consider&lt;/h2&gt;
&lt;h3&gt;Alternative 1: Minisforum &lt;span class="caps"&gt;MS&lt;/span&gt;-01&lt;/h3&gt;
&lt;p&gt;The &lt;span class="caps"&gt;MS&lt;/span&gt;-01 has dual 10GbE &lt;span class="caps"&gt;SFP&lt;/span&gt;+ ports, an Intel i9-12900H, and a PCIe 4.0 x16 slot. It is the Beelink &amp;#8220;upgrade&amp;#8221; for users who need 10GbE or &lt;span class="caps"&gt;GPU&lt;/span&gt; expansion. It costs&amp;nbsp;$600–800.&lt;/p&gt;
&lt;h3&gt;Alternative 2: Intel &lt;span class="caps"&gt;NUC&lt;/span&gt; 13&amp;nbsp;Pro&lt;/h3&gt;
&lt;p&gt;Intel&amp;#8217;s &lt;span class="caps"&gt;NUC&lt;/span&gt; line is more expensive but offers Thunderbolt 4, better Linux driver support, and official Proxmox compatibility. A NUC13i5 costs $500–700&amp;nbsp;barebones.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Frequently Asked&amp;nbsp;Questions&lt;/h2&gt;
&lt;h3&gt;Question 1: Can I run Proxmox on a Beelink with only 8 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;?&lt;/h3&gt;
&lt;p&gt;Yes, but it is tight. Proxmox itself uses ~2 &lt;span class="caps"&gt;GB&lt;/span&gt;. You can run 2–3 small &lt;span class="caps"&gt;LXC&lt;/span&gt; containers. For a comfortable lab, upgrade to 16 &lt;span class="caps"&gt;GB&lt;/span&gt; (max supported on most models is 32–64 &lt;span class="caps"&gt;GB&lt;/span&gt;).&lt;/p&gt;
&lt;h3&gt;Question 2: Does the Beelink support &lt;span class="caps"&gt;ECC&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;?&lt;/h3&gt;
&lt;p&gt;No. Beelink uses consumer SODIMMs (non-&lt;span class="caps"&gt;ECC&lt;/span&gt;). If you need &lt;span class="caps"&gt;ECC&lt;/span&gt;, move to a Supermicro or Rack server. For a small homelab, non-&lt;span class="caps"&gt;ECC&lt;/span&gt; is acceptable if you use &lt;span class="caps"&gt;ZFS&lt;/span&gt; and scrub&amp;nbsp;regularly.&lt;/p&gt;
&lt;h3&gt;Question 3: Can I add a 2.5 GbE &lt;span class="caps"&gt;USB&lt;/span&gt; &lt;span class="caps"&gt;NIC&lt;/span&gt;?&lt;/h3&gt;
&lt;p&gt;Yes. &lt;span class="caps"&gt;USB&lt;/span&gt; 3.0 Realtek &lt;span class="caps"&gt;RTL8156B&lt;/span&gt; adapters work out of the box on Proxmox 8.x. Use them for a dedicated storage network or &lt;span class="caps"&gt;VLAN&lt;/span&gt;&amp;nbsp;trunk.&lt;/p&gt;
&lt;h3&gt;Question 4: Will the Beelink overheat in a&amp;nbsp;closet?&lt;/h3&gt;
&lt;p&gt;Ambient temperature matters. If your closet is above 30°C, the Beelink may throttle. Add a small &lt;span class="caps"&gt;USB&lt;/span&gt; fan or ensure passive ventilation.&amp;nbsp;Use &lt;code&gt;sensors&lt;/code&gt; to monitor&amp;nbsp;temps:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;lm-sensors
sensors
&lt;span class="c1"&gt;# Look for k10temp (AMD) or coretemp (Intel)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Beelink mini PCs are the best-kept secret in the homelab world. They offer enough &lt;span class="caps"&gt;CPU&lt;/span&gt;, &lt;span class="caps"&gt;RAM&lt;/span&gt;, and storage for a small-to-medium Proxmox deployment at a fraction of the cost and power of a rack server. The installation is straightforward, but pay attention to &lt;span class="caps"&gt;BIOS&lt;/span&gt; settings (disable Secure Boot, enable &lt;span class="caps"&gt;IOMMU&lt;/span&gt;) and &lt;span class="caps"&gt;NIC&lt;/span&gt; driver stability (switch&amp;nbsp;to &lt;code&gt;r8168&lt;/code&gt; if&amp;nbsp;needed).&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;[internal_link] New to Proxmox? Read our &lt;a href="https://steadypub.com/2026/06/proxmox-beginner-guide-2026/"&gt;Proxmox beginner guide&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;[internal_link] Ready to deploy apps? See our &lt;a href="https://steadypub.com/2026/06/docker-compose-for-beginners/"&gt;Docker Compose for beginners&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;[internal_link] Need a rack server later? Check our &lt;a href="https://steadypub.com/2026/06/best-rack-server-for-homelab/"&gt;best rack server guide&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Beelink &lt;span class="caps"&gt;SER5&lt;/span&gt;/&lt;span class="caps"&gt;SER6&lt;/span&gt;&lt;/strong&gt;: Amazon or AliExpress affiliate&amp;nbsp;links&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;USB&lt;/span&gt; NICs&lt;/strong&gt;: &lt;span class="caps"&gt;RTL8156B&lt;/span&gt; 2.5 GbE&amp;nbsp;adapters&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;: Crucial &lt;span class="caps"&gt;DDR4&lt;/span&gt; &lt;span class="caps"&gt;SODIMM&lt;/span&gt;&amp;nbsp;upgrades&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Storage&lt;/strong&gt;: Samsung 980/990 NVMe&amp;nbsp;SSDs&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;installation&lt;/code&gt; → &lt;code&gt;proxmox-beginner-guide-2026&lt;/code&gt; — &amp;#8220;our comprehensive Proxmox install&amp;nbsp;guide&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;integration&lt;/code&gt; → &lt;code&gt;docker-compose-for-beginners&lt;/code&gt; — &amp;#8220;deploy apps on your Beelink&amp;nbsp;node&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;alternatives&lt;/code&gt; → &lt;code&gt;best-rack-server-for-homelab&lt;/code&gt; — &amp;#8220;when you outgrow a mini &lt;span class="caps"&gt;PC&lt;/span&gt;&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] What Beelink model are you running? Share your Proxmox specs and temps&amp;nbsp;below!&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for mini &lt;span class="caps"&gt;PC&lt;/span&gt; reviews, power efficiency tips, and Proxmox&amp;nbsp;guides.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Tool Guides"/><category term="proxmox"/><category term="beelink"/><category term="mini pc"/><category term="homelab"/><category term="self-hosted"/><category term="install"/></entry><entry><title>Best Rack Server for Homelab in 2026: A Curated Guide</title><link href="https://steadypub.com/2026/06/best-rack-server-for-homelab/" rel="alternate"/><published>2026-06-05T00:00:00+07:00</published><updated>2026-06-05T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/best-rack-server-for-homelab/</id><summary type="html">&lt;p&gt;A curated ranking of the best used and new rack servers for homelab builds in 2026. Includes real specs, pricing, power draw, and noise&amp;nbsp;levels.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~14 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab builders looking for rack-mounted server&amp;nbsp;hardware&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why a Rack Server for Your&amp;nbsp;Homelab?&lt;/h2&gt;
&lt;p&gt;A rack server gives you enterprise-grade reliability, expandability, and often multiple &lt;span class="caps"&gt;CPU&lt;/span&gt; sockets, hot-swap bays, and &lt;span class="caps"&gt;IPMI&lt;/span&gt;/iDRAC/iLO remote management. While mini PCs and tower servers are great for beginners, a rack server is the natural upgrade when you need more &lt;span class="caps"&gt;RAM&lt;/span&gt; slots, PCIe lanes, or storage bays. The used market is flooded with decommissioned datacenter gear, making it possible to build a 32-core, 128 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; beast for less than a high-end mini &lt;span class="caps"&gt;PC&lt;/span&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Evaluation&amp;nbsp;Criteria&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Criteria&lt;/th&gt;
&lt;th&gt;Why It Matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Price-to-Performance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Used enterprise gear depreciates fast; target high core/&lt;span class="caps"&gt;RAM&lt;/span&gt; per dollar.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Power &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; Noise&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Older generations draw more power and use louder fans. Aim for 80 Plus Platinum or better.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Expandability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;PCIe slots, &lt;span class="caps"&gt;RAM&lt;/span&gt; slots, and drive bays determine future-proofing.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Remote Management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;iDRAC (Dell), iLO (&lt;span class="caps"&gt;HP&lt;/span&gt;), &lt;span class="caps"&gt;IPMI&lt;/span&gt; (Supermicro) let you manage headless without a monitor.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Community Support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Models with large communities have better &lt;span class="caps"&gt;BIOS&lt;/span&gt; modding, fan-quieting guides, and spare parts.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;#1: Dell PowerEdge R720 /&amp;nbsp;R720xd&lt;/h2&gt;
&lt;h3&gt;Why It Tops Our&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;The R720 is the &amp;#8220;gold standard&amp;#8221; of used homelab rack servers. It balances performance, expandability, and community support. The xd variant adds extra drive bays for storage-focused builds. With two E5-2680 v2 CPUs (20 cores total), 128 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;DDR3&lt;/span&gt; &lt;span class="caps"&gt;ECC&lt;/span&gt;, and an H710 &lt;span class="caps"&gt;RAID&lt;/span&gt; controller, it can handle dozens of VMs or a full Kubernetes&amp;nbsp;cluster.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Form Factor&lt;/td&gt;
&lt;td&gt;2U rack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CPUs&lt;/td&gt;
&lt;td&gt;2× Intel Xeon E5-2600 v1/v2 (up to 12 cores each)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;24× &lt;span class="caps"&gt;DDR3&lt;/span&gt; &lt;span class="caps"&gt;DIMM&lt;/span&gt; slots (up to 768 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;ECC&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;8× 3.5&amp;#8221; (R720) or 12× 3.5&amp;#8221; (R720xd) hot-swap bays&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PCIe&lt;/td&gt;
&lt;td&gt;7× PCIe 3.0 slots (full-height)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NICs&lt;/td&gt;
&lt;td&gt;4× 1GbE Broadcom (upgradeable to 10GbE)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Remote Mgmt&lt;/td&gt;
&lt;td&gt;iDRAC 7 Enterprise (dedicated &lt;span class="caps"&gt;NIC&lt;/span&gt;, &lt;span class="caps"&gt;HTML5&lt;/span&gt; console)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Power&lt;/td&gt;
&lt;td&gt;2× 750W/1100W 80 Plus Platinum&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Massive community (r/homelab, ServeTheHome) with fan-quieting guides, &lt;span class="caps"&gt;BIOS&lt;/span&gt; mods, and&amp;nbsp;parts.&lt;/li&gt;
&lt;li&gt;iDRAC Enterprise is the best remote management experience in its&amp;nbsp;class.&lt;/li&gt;
&lt;li&gt;24 &lt;span class="caps"&gt;RAM&lt;/span&gt; slots let you scale cheaply with used &lt;span class="caps"&gt;DDR3&lt;/span&gt; &lt;span class="caps"&gt;ECC&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;H710 Mini Mono supports &lt;span class="caps"&gt;RAID&lt;/span&gt; 10 and passthrough for &lt;span class="caps"&gt;ZFS&lt;/span&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="caps"&gt;DDR3&lt;/span&gt; is slower and higher power than &lt;span class="caps"&gt;DDR4&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;Default fans are loud; you need &lt;span class="caps"&gt;IPMI&lt;/span&gt; fan scripts or custom&amp;nbsp;curves.&lt;/li&gt;
&lt;li&gt;2U means it needs a rack or shelf; not&amp;nbsp;apartment-friendly.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Medium to advanced homelabs running 20+ VMs, Proxmox clusters, or &lt;span class="caps"&gt;NAS&lt;/span&gt;/media&amp;nbsp;servers.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Used barebones: &lt;strong&gt;$180–$260 &lt;span class="caps"&gt;USD&lt;/span&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Fully configured (2× E5-2680 v2, 128 &lt;span class="caps"&gt;GB&lt;/span&gt;, H710): &lt;strong&gt;$350–$500 &lt;span class="caps"&gt;USD&lt;/span&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;#2: &lt;span class="caps"&gt;HP&lt;/span&gt; ProLiant DL380p&amp;nbsp;Gen8&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;The DL380p Gen8 is &lt;span class="caps"&gt;HP&lt;/span&gt;&amp;#8217;s direct competitor to the R720. It offers similar specs with &lt;span class="caps"&gt;HP&lt;/span&gt;&amp;#8217;s iLO 4 remote management. The build quality is excellent, and the tool-less chassis is a joy to work on. &lt;span class="caps"&gt;HP&lt;/span&gt; Smart Array P420i supports &lt;span class="caps"&gt;RAID&lt;/span&gt; and &lt;span class="caps"&gt;HBA&lt;/span&gt; mode for &lt;span class="caps"&gt;ZFS&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Form Factor&lt;/td&gt;
&lt;td&gt;2U rack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CPUs&lt;/td&gt;
&lt;td&gt;2× Intel Xeon E5-2600 v1/v2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;24× &lt;span class="caps"&gt;DDR3&lt;/span&gt; &lt;span class="caps"&gt;DIMM&lt;/span&gt; slots (up to 768 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;ECC&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;8× 2.5&amp;#8221; (&lt;span class="caps"&gt;SFF&lt;/span&gt;) or 12× 3.5&amp;#8221; (&lt;span class="caps"&gt;LFF&lt;/span&gt;) hot-swap bays&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PCIe&lt;/td&gt;
&lt;td&gt;6× PCIe 3.0 slots&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NICs&lt;/td&gt;
&lt;td&gt;4× 1GbE (Broadcom)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Remote Mgmt&lt;/td&gt;
&lt;td&gt;iLO 4 Advanced (&lt;span class="caps"&gt;HTML5&lt;/span&gt; console with license)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Power&lt;/td&gt;
&lt;td&gt;2× 460W–750W 80 Plus Platinum&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;iLO 4 Advanced is rock-solid; virtual media mounting is&amp;nbsp;seamless.&lt;/li&gt;
&lt;li&gt;Tool-less drive bays and PCIe risers make maintenance&amp;nbsp;easy.&lt;/li&gt;
&lt;li&gt;Large firmware library on &lt;span class="caps"&gt;HPE&lt;/span&gt;&amp;#8217;s website (requires support contract for some &lt;span class="caps"&gt;BIOS&lt;/span&gt;&amp;nbsp;updates).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;iLO 4 Advanced requires a license (often included on used units, but&amp;nbsp;verify).&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;HP&lt;/span&gt; custom drive trays and firmware can be picky with non-&lt;span class="caps"&gt;HP&lt;/span&gt;&amp;nbsp;drives.&lt;/li&gt;
&lt;li&gt;Slightly less PCIe flexibility than the&amp;nbsp;R720.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Users who want a reliable, well-built 2U server with excellent remote&amp;nbsp;management.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Used barebones: &lt;strong&gt;$160–$240 &lt;span class="caps"&gt;USD&lt;/span&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Fully configured (2× E5-2660 v2, 128 &lt;span class="caps"&gt;GB&lt;/span&gt;, P420i): &lt;strong&gt;$320–$480 &lt;span class="caps"&gt;USD&lt;/span&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;#3: Dell PowerEdge&amp;nbsp;R730&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;The R730 is the newer &lt;span class="caps"&gt;DDR4&lt;/span&gt; sibling of the R720. It supports E5-2600 v3/v4 CPUs (&lt;span class="caps"&gt;AVX2&lt;/span&gt;, &lt;span class="caps"&gt;DDR4&lt;/span&gt;), giving you better performance per watt and lower idle power. It is the sweet spot if you want modern hardware without paying the &lt;span class="caps"&gt;DDR5&lt;/span&gt;&amp;nbsp;premium.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Form Factor&lt;/td&gt;
&lt;td&gt;2U rack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CPUs&lt;/td&gt;
&lt;td&gt;2× Intel Xeon E5-2600 v3/v4 (up to 22 cores each)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;24× &lt;span class="caps"&gt;DDR4&lt;/span&gt; &lt;span class="caps"&gt;DIMM&lt;/span&gt; slots (up to 1.5 &lt;span class="caps"&gt;TB&lt;/span&gt; &lt;span class="caps"&gt;ECC&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;8× 3.5&amp;#8221; or 16× 2.5&amp;#8221; hot-swap bays&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PCIe&lt;/td&gt;
&lt;td&gt;7× PCIe 3.0 slots&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NICs&lt;/td&gt;
&lt;td&gt;4× 1GbE (upgradeable to 10GbE/25GbE)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Remote Mgmt&lt;/td&gt;
&lt;td&gt;iDRAC 8 Enterprise&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Power&lt;/td&gt;
&lt;td&gt;2× 750W/1100W 80 Plus Platinum&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="caps"&gt;DDR4&lt;/span&gt; &lt;span class="caps"&gt;ECC&lt;/span&gt; is faster, cheaper per &lt;span class="caps"&gt;GB&lt;/span&gt; now, and lower&amp;nbsp;power.&lt;/li&gt;
&lt;li&gt;E5 v4 CPUs have excellent single-threaded performance for&amp;nbsp;VMs.&lt;/li&gt;
&lt;li&gt;iDRAC 8 has a cleaner &lt;span class="caps"&gt;HTML5&lt;/span&gt; &lt;span class="caps"&gt;UI&lt;/span&gt; and better mobile&amp;nbsp;support.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Significantly more expensive than R720 on the used&amp;nbsp;market.&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;DDR4&lt;/span&gt; RDIMMs were expensive until recently; still pricier than &lt;span class="caps"&gt;DDR3&lt;/span&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Users who want modern hardware and plan to run &lt;span class="caps"&gt;GPU&lt;/span&gt; passthrough or high-&lt;span class="caps"&gt;RAM&lt;/span&gt;&amp;nbsp;workloads.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Used barebones: &lt;strong&gt;$350–$500 &lt;span class="caps"&gt;USD&lt;/span&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Fully configured (2× E5-2680 v4, 128 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;DDR4&lt;/span&gt;, H730): &lt;strong&gt;$600–$850 &lt;span class="caps"&gt;USD&lt;/span&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;#4: Lenovo ThinkSystem &lt;span class="caps"&gt;SR250&lt;/span&gt;&amp;nbsp;V2&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;If you want a &lt;strong&gt;new&lt;/strong&gt; rack server with a warranty, the &lt;span class="caps"&gt;SR250&lt;/span&gt; V2 is a compact 1U option with modern Xeon E-2300 CPUs. It&amp;#8217;s not a dual-socket beast, but it is quiet, power-efficient, and perfect for a small homelab or edge compute&amp;nbsp;node.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Form Factor&lt;/td&gt;
&lt;td&gt;1U rack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CPUs&lt;/td&gt;
&lt;td&gt;1× Intel Xeon E-2300 (up to 8 cores) or Pentium/Celeron&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;4× &lt;span class="caps"&gt;DDR4&lt;/span&gt; &lt;span class="caps"&gt;UDIMM&lt;/span&gt; slots (up to 128 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;ECC&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;4× 3.5&amp;#8221; or 8× 2.5&amp;#8221; hot-swap bays&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PCIe&lt;/td&gt;
&lt;td&gt;2× PCIe 4.0 slots&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NICs&lt;/td&gt;
&lt;td&gt;2× 1GbE (Intel)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Remote Mgmt&lt;/td&gt;
&lt;td&gt;Lenovo XClarity (basic)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Power&lt;/td&gt;
&lt;td&gt;1× 300W 80 Plus Platinum&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Brand new with 3-year warranty and quiet operation (under 35 dB at&amp;nbsp;idle).&lt;/li&gt;
&lt;li&gt;PCIe 4.0 supports modern NVMe HBAs and&amp;nbsp;GPUs.&lt;/li&gt;
&lt;li&gt;Very low power draw (30–60W&amp;nbsp;idle).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Single &lt;span class="caps"&gt;CPU&lt;/span&gt; and limited &lt;span class="caps"&gt;RAM&lt;/span&gt; slots cap&amp;nbsp;scalability.&lt;/li&gt;
&lt;li&gt;Higher upfront cost than used dual-socket&amp;nbsp;gear.&lt;/li&gt;
&lt;li&gt;XClarity is not as mature as&amp;nbsp;iDRAC/iLO.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Small homelabs, edge nodes, or users who want a quiet, modern 1U&amp;nbsp;server.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;New barebones: &lt;strong&gt;$800–$1,100 &lt;span class="caps"&gt;USD&lt;/span&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Configured (E-2378, 64 &lt;span class="caps"&gt;GB&lt;/span&gt;, 4× 4 &lt;span class="caps"&gt;TB&lt;/span&gt;): &lt;strong&gt;$1,400–$1,800 &lt;span class="caps"&gt;USD&lt;/span&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;#5: Supermicro &lt;span class="caps"&gt;SYS&lt;/span&gt;-5019D-&lt;span class="caps"&gt;FN8TP&lt;/span&gt;&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;Supermicro is the go-to for raw, no-frills hardware. The 5019D-&lt;span class="caps"&gt;FN8TP&lt;/span&gt; is a 1U server with an Intel Xeon D-&lt;span class="caps"&gt;2146NT&lt;/span&gt; (8 cores, 16 threads, 45W &lt;span class="caps"&gt;TDP&lt;/span&gt;). It has dual 10GbE &lt;span class="caps"&gt;SFP&lt;/span&gt;+ ports built in, making it ideal for a 10GbE homelab&amp;nbsp;core.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Form Factor&lt;/td&gt;
&lt;td&gt;1U rack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CPUs&lt;/td&gt;
&lt;td&gt;1× Intel Xeon D-&lt;span class="caps"&gt;2146NT&lt;/span&gt; (8C/16T, SoC)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;4× &lt;span class="caps"&gt;DDR4&lt;/span&gt; &lt;span class="caps"&gt;DIMM&lt;/span&gt; slots (up to 512 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;ECC&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;8× 2.5&amp;#8221; hot-swap bays + 2× M.2 NVMe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PCIe&lt;/td&gt;
&lt;td&gt;1× PCIe 3.0 x16 (half-height)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NICs&lt;/td&gt;
&lt;td&gt;2× 10GbE &lt;span class="caps"&gt;SFP&lt;/span&gt;+ + 2× 1GbE &lt;span class="caps"&gt;RJ45&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Remote Mgmt&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;IPMI&lt;/span&gt; 2.0 + &lt;span class="caps"&gt;KVM&lt;/span&gt;-over-&lt;span class="caps"&gt;IP&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Power&lt;/td&gt;
&lt;td&gt;1× 400W 80 Plus Platinum&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Built-in 10GbE &lt;span class="caps"&gt;SFP&lt;/span&gt;+ eliminates the need for add-in&amp;nbsp;NICs.&lt;/li&gt;
&lt;li&gt;Very low power (35–50W idle) for an 8-core&amp;nbsp;server.&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;IPMI&lt;/span&gt; is open-standard and works with any&amp;nbsp;browser.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Single SoC &lt;span class="caps"&gt;CPU&lt;/span&gt;; no upgrade&amp;nbsp;path.&lt;/li&gt;
&lt;li&gt;Limited PCIe expansion (only one&amp;nbsp;slot).&lt;/li&gt;
&lt;li&gt;Supermicro&amp;#8217;s &lt;span class="caps"&gt;BIOS&lt;/span&gt; interface is less polished than Dell/&lt;span class="caps"&gt;HP&lt;/span&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;10GbE homelab enthusiasts who need a compact, efficient core&amp;nbsp;server.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Used barebones: &lt;strong&gt;$400–$550 &lt;span class="caps"&gt;USD&lt;/span&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Configured (64 &lt;span class="caps"&gt;GB&lt;/span&gt;, 4× 2 &lt;span class="caps"&gt;TB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt;): &lt;strong&gt;$700–$950 &lt;span class="caps"&gt;USD&lt;/span&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Quick Comparison&amp;nbsp;Table&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Form&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Max &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Drive Bays&lt;/th&gt;
&lt;th&gt;Remote Mgmt&lt;/th&gt;
&lt;th&gt;Idle Power&lt;/th&gt;
&lt;th&gt;Used Price&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Dell R720&lt;/td&gt;
&lt;td&gt;2U&lt;/td&gt;
&lt;td&gt;2× E5 v2&lt;/td&gt;
&lt;td&gt;768 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;DDR3&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;8/12× 3.5&amp;#8221;&lt;/td&gt;
&lt;td&gt;iDRAC 7&lt;/td&gt;
&lt;td&gt;80–120W&lt;/td&gt;
&lt;td&gt;$350–$500&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;HP&lt;/span&gt; DL380p G8&lt;/td&gt;
&lt;td&gt;2U&lt;/td&gt;
&lt;td&gt;2× E5 v2&lt;/td&gt;
&lt;td&gt;768 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;DDR3&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;8/12× 2.5&amp;#8221;/3.5&amp;#8221;&lt;/td&gt;
&lt;td&gt;iLO 4&lt;/td&gt;
&lt;td&gt;80–110W&lt;/td&gt;
&lt;td&gt;$320–$480&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dell R730&lt;/td&gt;
&lt;td&gt;2U&lt;/td&gt;
&lt;td&gt;2× E5 v4&lt;/td&gt;
&lt;td&gt;1.5 &lt;span class="caps"&gt;TB&lt;/span&gt; &lt;span class="caps"&gt;DDR4&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;8/16× 3.5&amp;#8221;/2.5&amp;#8221;&lt;/td&gt;
&lt;td&gt;iDRAC 8&lt;/td&gt;
&lt;td&gt;60–90W&lt;/td&gt;
&lt;td&gt;$600–$850&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lenovo &lt;span class="caps"&gt;SR250&lt;/span&gt; V2&lt;/td&gt;
&lt;td&gt;1U&lt;/td&gt;
&lt;td&gt;1× E-2300&lt;/td&gt;
&lt;td&gt;128 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;DDR4&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;4× 3.5&amp;#8221;&lt;/td&gt;
&lt;td&gt;XClarity&lt;/td&gt;
&lt;td&gt;30–50W&lt;/td&gt;
&lt;td&gt;$1,400+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Supermicro 5019D&lt;/td&gt;
&lt;td&gt;1U&lt;/td&gt;
&lt;td&gt;1× D-&lt;span class="caps"&gt;2146NT&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;512 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;DDR4&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;8× 2.5&amp;#8221;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;IPMI&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;35–50W&lt;/td&gt;
&lt;td&gt;$700–$950&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Fan&amp;nbsp;Quietening&lt;/h3&gt;
&lt;p&gt;Dell and &lt;span class="caps"&gt;HP&lt;/span&gt; servers default to aggressive fan curves. Use &lt;span class="caps"&gt;IPMI&lt;/span&gt; commands to set manual fan speeds. For&amp;nbsp;Dell: &lt;code&gt;ipmitool raw 0x30 0x30 0x02 0xff 0x0a&lt;/code&gt; sets 10% fan speed. Monitor temps; do not go below 10% if ambient is above&amp;nbsp;22°C.&lt;/p&gt;
&lt;h3&gt;Tip 2: &lt;span class="caps"&gt;HBA&lt;/span&gt; vs &lt;span class="caps"&gt;RAID&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;If you plan to run &lt;span class="caps"&gt;ZFS&lt;/span&gt;, TrueNAS, or Proxmox with Ceph, flash your &lt;span class="caps"&gt;RAID&lt;/span&gt; controller to &lt;span class="caps"&gt;IT&lt;/span&gt; mode (&lt;span class="caps"&gt;HBA&lt;/span&gt;). Dell H710 and &lt;span class="caps"&gt;HP&lt;/span&gt; P420i can both be cross-flashed. This gives direct disk access, which is critical for &lt;span class="caps"&gt;ZFS&lt;/span&gt; health&amp;nbsp;monitoring.&lt;/p&gt;
&lt;h3&gt;Tip 3: Power&amp;nbsp;Math&lt;/h3&gt;
&lt;p&gt;A dual E5 v2 server at 100W idle costs about &lt;strong&gt;$0.30/day&lt;/strong&gt; ($9/month) at $0.13/kWh. An R730 at 70W idle is ~$6.50/month. A 1U Xeon D at 40W is ~$3.80/month. Factor power into your 5-year total cost of&amp;nbsp;ownership.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;For most homelabbers, the &lt;strong&gt;Dell R720&lt;/strong&gt; offers the best balance of price, performance, and community support. If you need modern &lt;span class="caps"&gt;DDR4&lt;/span&gt; and lower power, the &lt;strong&gt;R730&lt;/strong&gt; is worth the premium. For a quiet, warranty-backed build, the &lt;strong&gt;Lenovo &lt;span class="caps"&gt;SR250&lt;/span&gt; V2&lt;/strong&gt; is a solid new option. And if 10GbE is your priority, the &lt;strong&gt;Supermicro 5019D&lt;/strong&gt; is&amp;nbsp;unbeatable.&lt;/p&gt;
&lt;h3&gt;Our&amp;nbsp;Recommendation&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Budget build:&lt;/strong&gt; Dell R720 with 2× E5-2660 v2, 64 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;DDR3&lt;/span&gt;, H710 (&lt;span class="caps"&gt;IT&lt;/span&gt; mode).&amp;nbsp;~$350.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Performance build:&lt;/strong&gt; Dell R730 with 2× E5-2680 v4, 128 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;DDR4&lt;/span&gt;, H730.&amp;nbsp;~$750.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Quiet build:&lt;/strong&gt; Lenovo &lt;span class="caps"&gt;SR250&lt;/span&gt; V2 or Supermicro 5019D.&amp;nbsp;~$1,000+.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dell R720 / R730&lt;/strong&gt;: eBay used server links (local pickup or verified&amp;nbsp;seller)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;HP&lt;/span&gt; DL380p Gen8&lt;/strong&gt;: eBay or ServerMonkey&amp;nbsp;links&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Supermicro 5019D&lt;/strong&gt;: Newegg or B&amp;amp;H&amp;nbsp;links&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pro-tips&lt;/strong&gt;: Rack rails, cable management, and &lt;span class="caps"&gt;UPS&lt;/span&gt; affiliate&amp;nbsp;links&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;why-this-matters&lt;/code&gt; → &lt;code&gt;proxmox-beginner-guide-2026&lt;/code&gt; — &amp;#8220;install Proxmox on your new rack&amp;nbsp;server&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;item-1&lt;/code&gt; → &lt;code&gt;homelab-server-hardware-2026&lt;/code&gt; — &amp;#8220;deep dive into &lt;span class="caps"&gt;CPU&lt;/span&gt; and &lt;span class="caps"&gt;RAM&lt;/span&gt;&amp;nbsp;choices&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;ups-for-homelab&lt;/code&gt; — &amp;#8220;protect your rack server with a &lt;span class="caps"&gt;UPS&lt;/span&gt;&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] What rack server are you running in your homelab? Share your specs and fan-quieting tricks&amp;nbsp;below!&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for more hardware guides, deal alerts, and self-hosting&amp;nbsp;tutorials.&lt;/li&gt;
&lt;li&gt;[internal_link] Next up: read our complete &lt;a href="https://steadypub.com/2026/06/homelab-server-hardware-2026/"&gt;homelab server hardware guide&lt;/a&gt; to plan your&amp;nbsp;build.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Guides"/><category term="rack server"/><category term="homelab"/><category term="self-hosted"/><category term="hardware"/><category term="dell"/><category term="hp"/><category term="lenovo"/></entry><entry><title>Best Self-Hosted Apps 2026: The Essential Homelab Stack</title><link href="https://steadypub.com/2026/06/best-self-hosted-apps-2026/" rel="alternate"/><published>2026-06-05T00:00:00+07:00</published><updated>2026-06-05T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/best-self-hosted-apps-2026/</id><summary type="html">&lt;p&gt;A curated ranking of the best self-hosted apps for 2026. Covers productivity, media, security, and infrastructure tools with real setup requirements and use&amp;nbsp;cases.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~14 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Self-hosters looking for the best apps to run in their&amp;nbsp;homelab&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why Self-Hosted Apps&amp;nbsp;Matter&lt;/h2&gt;
&lt;p&gt;Running your own apps gives you privacy, control, and no monthly subscriptions. Instead of trusting Google, Dropbox, or Spotify with your data, you run open-source alternatives on your own hardware. In 2026, the self-hosting ecosystem is mature: Docker images are polished, backup tools are automated, and community support is massive. This guide lists the best apps in each category, ranked by stability, ease of setup, and real-world&amp;nbsp;utility.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Evaluation&amp;nbsp;Criteria&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Criteria&lt;/th&gt;
&lt;th&gt;Why It Matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ease of Setup&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Does it have a maintained Docker image or a one-line installer?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Documentation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Is there a wiki, active Reddit community, or official docs?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Resource Usage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Does it run on a 2 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; mini &lt;span class="caps"&gt;PC&lt;/span&gt; or require a 16 &lt;span class="caps"&gt;GB&lt;/span&gt; server?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Update Frequency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Is the project actively maintained? Avoid abandonware.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mobile Apps&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Does it have iOS/Android apps or a good responsive web &lt;span class="caps"&gt;UI&lt;/span&gt;?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data Portability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Can you export your data easily if you want to switch later?&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;#1: Nextcloud (Files, Collaboration,&amp;nbsp;Office)&lt;/h2&gt;
&lt;h3&gt;Why It Tops Our&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;Nextcloud is the Swiss Army knife of self-hosting. It replaces Google Drive, Dropbox, Google Docs, Google Calendar, and even Google Photos. With the right apps, you can edit Office documents, manage tasks, and host video&amp;nbsp;calls.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Category&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;File sync, productivity, collaboration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Install&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Docker Compose (official &lt;span class="caps"&gt;AIO&lt;/span&gt; or manual)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1 &lt;span class="caps"&gt;GB&lt;/span&gt; minimum, 4 &lt;span class="caps"&gt;GB&lt;/span&gt; recommended with Collabora&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Depends on user data; 10 &lt;span class="caps"&gt;GB&lt;/span&gt;+ for system&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Database&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;PostgreSQL (recommended) or MariaDB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mobile&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;iOS, Android (excellent)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;License&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;AGPL&lt;/span&gt;-3.0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Huge app ecosystem: Calendar, Contacts, Mail, Notes, Tasks, Deck,&amp;nbsp;Talk.&lt;/li&gt;
&lt;li&gt;End-to-end encryption for external&amp;nbsp;storage.&lt;/li&gt;
&lt;li&gt;Federated sharing: share files with other Nextcloud&amp;nbsp;instances.&lt;/li&gt;
&lt;li&gt;Collabora Online or OnlyOffice integration for document&amp;nbsp;editing.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Can be heavy if you enable every&amp;nbsp;app.&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;PHP&lt;/span&gt;-based; requires tuning for performance (OPcache,&amp;nbsp;Redis).&lt;/li&gt;
&lt;li&gt;WebDAV sync can be slow with large files (use the desktop client&amp;nbsp;instead).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Anyone who wants to replace Google Workspace or Microsoft 365 with a private&amp;nbsp;alternative.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Free&lt;/strong&gt; (open&amp;nbsp;source).&lt;/li&gt;
&lt;li&gt;Optional enterprise support or hosted plans (Nextcloud&amp;nbsp;GmbH).&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;#2: Immich (Photo &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; Video&amp;nbsp;Backup)&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;Immich is the best self-hosted Google Photos replacement in 2026. It has a gorgeous mobile app, &lt;span class="caps"&gt;AI&lt;/span&gt;-powered facial recognition, automatic background upload, and album sharing. It is fast, actively developed, and handles tens of thousands of photos without&amp;nbsp;choking.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Category&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Photo/video backup, gallery&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Install&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Docker Compose (official)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;4 &lt;span class="caps"&gt;GB&lt;/span&gt; minimum, 8 &lt;span class="caps"&gt;GB&lt;/span&gt; recommended (&lt;span class="caps"&gt;ML&lt;/span&gt; models)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2× your photo library (thumbnails + originals)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Database&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;PostgreSQL + Redis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mobile&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;iOS, Android (excellent, auto-upload)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;License&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;MIT&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Auto-upload in the background with&amp;nbsp;deduplication.&lt;/li&gt;
&lt;li&gt;Facial recognition, object detection, and duplicate&amp;nbsp;finder.&lt;/li&gt;
&lt;li&gt;Albums, shared links, and partner&amp;nbsp;sharing.&lt;/li&gt;
&lt;li&gt;Timeline view and map view&amp;nbsp;(geolocation).&lt;/li&gt;
&lt;li&gt;Hardware transcoding support (Intel QuickSync, &lt;span class="caps"&gt;NVIDIA&lt;/span&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="caps"&gt;ML&lt;/span&gt; features require significant &lt;span class="caps"&gt;RAM&lt;/span&gt; (8 &lt;span class="caps"&gt;GB&lt;/span&gt;+ for large&amp;nbsp;libraries).&lt;/li&gt;
&lt;li&gt;Does not support raw video editing (it is a backup tool, not a&amp;nbsp;studio).&lt;/li&gt;
&lt;li&gt;Initial indexing can take days for 50,000+&amp;nbsp;photos.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Families or photographers who want a private, unlimited photo&amp;nbsp;cloud.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Free&lt;/strong&gt; (open&amp;nbsp;source).&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;#3: Jellyfin (Media&amp;nbsp;Server)&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;Jellyfin is the open-source alternative to Plex and Emby. It streams your movies, &lt;span class="caps"&gt;TV&lt;/span&gt; shows, music, and audiobooks to any device. Unlike Plex, it does not require a login or subscription, and it does not phone&amp;nbsp;home.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Category&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Media streaming, library management&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Install&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Docker Compose or native package&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;512 &lt;span class="caps"&gt;MB&lt;/span&gt; minimum, 2 &lt;span class="caps"&gt;GB&lt;/span&gt; recommended with transcoding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1–2 &lt;span class="caps"&gt;GB&lt;/span&gt; for metadata + your media library&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Database&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;SQLite (embedded)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mobile&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;iOS, Android, Web, Roku, Android &lt;span class="caps"&gt;TV&lt;/span&gt;, Kodi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;License&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;GPL&lt;/span&gt;-2.0+&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;No subscriptions, no telemetry, no mandatory&amp;nbsp;accounts.&lt;/li&gt;
&lt;li&gt;Excellent hardware transcoding (Intel QuickSync, &lt;span class="caps"&gt;NVIDIA&lt;/span&gt; &lt;span class="caps"&gt;NVENC&lt;/span&gt;, &lt;span class="caps"&gt;AMD&lt;/span&gt; &lt;span class="caps"&gt;VAAPI&lt;/span&gt;).&lt;/li&gt;
&lt;li&gt;Rich metadata scraping (TheMovieDB, &lt;span class="caps"&gt;TVDB&lt;/span&gt;,&amp;nbsp;MusicBrainz).&lt;/li&gt;
&lt;li&gt;Live &lt;span class="caps"&gt;TV&lt;/span&gt; and &lt;span class="caps"&gt;DVR&lt;/span&gt; support with a tuner&amp;nbsp;(HDHomeRun).&lt;/li&gt;
&lt;li&gt;Plugins for subtitles, trailers, and intro&amp;nbsp;skipping.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="caps"&gt;UI&lt;/span&gt; is less polished than Plex (improving rapidly in&amp;nbsp;2025–2026).&lt;/li&gt;
&lt;li&gt;No official cloud sync (must use a &lt;span class="caps"&gt;VPN&lt;/span&gt; or reverse&amp;nbsp;proxy).&lt;/li&gt;
&lt;li&gt;Transcoding requires a capable &lt;span class="caps"&gt;CPU&lt;/span&gt; or &lt;span class="caps"&gt;GPU&lt;/span&gt;; weak hardware will struggle with&amp;nbsp;4K.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Users who want a private Netflix without surrendering viewing&amp;nbsp;data.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Free&lt;/strong&gt; (open&amp;nbsp;source).&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;#4: Pi-hole (Network-Wide Ad&amp;nbsp;Blocking)&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;Pi-hole blocks ads at the &lt;span class="caps"&gt;DNS&lt;/span&gt; level for your entire network. Every device—phone, tablet, smart &lt;span class="caps"&gt;TV&lt;/span&gt;, IoT gadget—gets ad-free browsing without installing browser extensions. It also blocks telemetry and malicious&amp;nbsp;domains.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Category&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt; sinkhole, ad blocker, privacy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Install&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Docker Compose or one-line installer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;512 &lt;span class="caps"&gt;MB&lt;/span&gt; minimum&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2 &lt;span class="caps"&gt;GB&lt;/span&gt; (logs and blocklists)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Database&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;SQLite (embedded)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mobile&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Web &lt;span class="caps"&gt;UI&lt;/span&gt; (admin)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;License&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;EUPL&lt;/span&gt;-1.2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Network-wide blocking: no per-device&amp;nbsp;setup.&lt;/li&gt;
&lt;li&gt;Blocklists are community-curated (StevenBlack, &lt;span class="caps"&gt;OISD&lt;/span&gt;,&amp;nbsp;Hagezi).&lt;/li&gt;
&lt;li&gt;Local &lt;span class="caps"&gt;DNS&lt;/span&gt; resolution:&amp;nbsp;map &lt;code&gt;home.local&lt;/code&gt; to your server &lt;span class="caps"&gt;IP&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;DHCP&lt;/span&gt; server option (can replace your router&amp;#8217;s &lt;span class="caps"&gt;DHCP&lt;/span&gt;).&lt;/li&gt;
&lt;li&gt;Query log and stats&amp;nbsp;dashboard.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Blocks legitimate domains sometimes (false positives). Whitelisting is&amp;nbsp;needed.&lt;/li&gt;
&lt;li&gt;Does not block &amp;#8220;first-party&amp;#8221; ads (e.g., YouTube ads inside the app)&amp;nbsp;perfectly.&lt;/li&gt;
&lt;li&gt;Requires your router to use Pi-hole as the &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;server.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Every homelab. It should be the first app you&amp;nbsp;install.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Free&lt;/strong&gt;&amp;nbsp;(donation-supported).&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;#5: Portainer (Container&amp;nbsp;Management)&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;Portainer is a web &lt;span class="caps"&gt;UI&lt;/span&gt; for managing Docker, Docker Swarm, and Kubernetes. It turns complex &lt;span class="caps"&gt;CLI&lt;/span&gt; commands into clickable buttons. For beginners, it is the best way to deploy, update, and inspect containers without&amp;nbsp;memorizing &lt;code&gt;docker&lt;/code&gt; flags.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Category&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Container management, DevOps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Install&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Docker Compose (one container)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;256 &lt;span class="caps"&gt;MB&lt;/span&gt; minimum&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Database&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;SQLite (embedded)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mobile&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Responsive web &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;License&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Zlib (&lt;span class="caps"&gt;CE&lt;/span&gt; edition)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Deploy stacks from Docker Compose &lt;span class="caps"&gt;YAML&lt;/span&gt;&amp;nbsp;files.&lt;/li&gt;
&lt;li&gt;Built-in templates for popular apps (&lt;span class="caps"&gt;NGINX&lt;/span&gt;, MySQL,&amp;nbsp;Redis).&lt;/li&gt;
&lt;li&gt;Container logs, stats, and console access in the&amp;nbsp;browser.&lt;/li&gt;
&lt;li&gt;User management and &lt;span class="caps"&gt;RBAC&lt;/span&gt; (role-based access&amp;nbsp;control).&lt;/li&gt;
&lt;li&gt;Supports Docker, Swarm, Kubernetes, and&amp;nbsp;Nomad.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="caps"&gt;CE&lt;/span&gt; edition lacks some enterprise features (&lt;span class="caps"&gt;SSO&lt;/span&gt;, advanced &lt;span class="caps"&gt;RBAC&lt;/span&gt;).&lt;/li&gt;
&lt;li&gt;Can accidentally delete volumes if not careful (no&amp;nbsp;undo).&lt;/li&gt;
&lt;li&gt;Not a replacement for learning Docker Compose; it complements&amp;nbsp;it.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Beginners who want a &lt;span class="caps"&gt;GUI&lt;/span&gt; for Docker and intermediate users who want to manage remote&amp;nbsp;nodes.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Free&lt;/strong&gt; (&lt;span class="caps"&gt;CE&lt;/span&gt;&amp;nbsp;edition).&lt;/li&gt;
&lt;li&gt;Business edition: $199/year for 5&amp;nbsp;nodes.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Quick Comparison&amp;nbsp;Table&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;App&lt;/th&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Storage&lt;/th&gt;
&lt;th&gt;Mobile&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Nextcloud&lt;/td&gt;
&lt;td&gt;Productivity&lt;/td&gt;
&lt;td&gt;4 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;10 &lt;span class="caps"&gt;GB&lt;/span&gt;+&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Replace Google Workspace&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Immich&lt;/td&gt;
&lt;td&gt;Photos&lt;/td&gt;
&lt;td&gt;8 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;2× library&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Replace Google Photos&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Jellyfin&lt;/td&gt;
&lt;td&gt;Media&lt;/td&gt;
&lt;td&gt;2 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1–2 &lt;span class="caps"&gt;GB&lt;/span&gt; + media&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Replace Plex/Netflix&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pi-hole&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt;/Ad block&lt;/td&gt;
&lt;td&gt;512 &lt;span class="caps"&gt;MB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;2 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Network-wide privacy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Portainer&lt;/td&gt;
&lt;td&gt;DevOps&lt;/td&gt;
&lt;td&gt;256 &lt;span class="caps"&gt;MB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Docker &lt;span class="caps"&gt;GUI&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Use a Reverse&amp;nbsp;Proxy&lt;/h3&gt;
&lt;p&gt;All these apps expose web UIs. Use &lt;strong&gt;&lt;span class="caps"&gt;NGINX&lt;/span&gt; Proxy Manager&lt;/strong&gt; or &lt;strong&gt;Traefik&lt;/strong&gt; to give them subdomains&amp;nbsp;(&lt;code&gt;nextcloud.yourdomain.com&lt;/code&gt;, &lt;code&gt;jellyfin.yourdomain.com&lt;/code&gt;) and automatic Let&amp;#8217;s Encrypt &lt;span class="caps"&gt;SSL&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;Tip 2: Backup Your&amp;nbsp;Data&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Nextcloud: Use&amp;nbsp;the &lt;code&gt;occ&lt;/code&gt; command or the built-in backup&amp;nbsp;app.&lt;/li&gt;
&lt;li&gt;Immich: Backup the PostgreSQL database and&amp;nbsp;the &lt;code&gt;upload&lt;/code&gt; directory.&lt;/li&gt;
&lt;li&gt;Jellyfin:&amp;nbsp;Backup &lt;code&gt;/config&lt;/code&gt; and your&amp;nbsp;media.&lt;/li&gt;
&lt;li&gt;Pi-hole:&amp;nbsp;Backup &lt;code&gt;/etc/pihole&lt;/code&gt; and &lt;code&gt;/etc/dnsmasq.d&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Use a 3-2-1 strategy: 3 copies, 2 media, 1&amp;nbsp;offsite.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Tip 3: Update&amp;nbsp;Regularly&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Update all containers via Portainer&lt;/span&gt;
&lt;span class="c1"&gt;# Or via CLI:&lt;/span&gt;
docker-compose&lt;span class="w"&gt; &lt;/span&gt;pull&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Watchtower can automate this, but test updates in a staging environment&amp;nbsp;first.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;The &amp;#8220;essential stack&amp;#8221; for 2026 is:
1. &lt;strong&gt;Pi-hole&lt;/strong&gt; for network privacy.
2. &lt;strong&gt;Nextcloud&lt;/strong&gt; for files and productivity.
3. &lt;strong&gt;Immich&lt;/strong&gt; for photo backup.
4. &lt;strong&gt;Jellyfin&lt;/strong&gt; for media.
5. &lt;strong&gt;Portainer&lt;/strong&gt; for&amp;nbsp;management.&lt;/p&gt;
&lt;p&gt;These five apps cover 90% of what the average self-hoster needs. They are all free, actively maintained, and run comfortably on a $300 mini &lt;span class="caps"&gt;PC&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;Our&amp;nbsp;Recommendation&lt;/h3&gt;
&lt;p&gt;Start with Pi-hole and Nextcloud. Add Jellyfin if you have a media library. Add Immich if you take photos. Add Portainer when you are tired of the &lt;span class="caps"&gt;CLI&lt;/span&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Nextcloud&lt;/strong&gt;: Hosted Nextcloud providers or official&amp;nbsp;merchandise&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Immich&lt;/strong&gt;: Donation links (GitHub&amp;nbsp;Sponsors)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Jellyfin&lt;/strong&gt;: Donation links or Jellyfin.org&amp;nbsp;store&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hardware&lt;/strong&gt;: Mini &lt;span class="caps"&gt;PC&lt;/span&gt; affiliate links for running the&amp;nbsp;stack&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Storage&lt;/strong&gt;: &lt;span class="caps"&gt;NAS&lt;/span&gt; and hard drive affiliate&amp;nbsp;links&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;why-this-matters&lt;/code&gt; → &lt;code&gt;docker-compose-for-beginners&lt;/code&gt; — &amp;#8220;how to deploy these apps with Docker&amp;nbsp;Compose&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;item-1&lt;/code&gt; → &lt;code&gt;nextcloud-docker-compose&lt;/code&gt; — &amp;#8220;deep dive into Nextcloud&amp;nbsp;setup&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;item-2&lt;/code&gt; → &lt;code&gt;immich-docker-compose-setup&lt;/code&gt; — &amp;#8220;Immich installation&amp;nbsp;guide&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;item-3&lt;/code&gt; → &lt;code&gt;self-hosted-media-server-setup&lt;/code&gt; — &amp;#8220;Jellyfin setup&amp;nbsp;guide&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;item-4&lt;/code&gt; → &lt;code&gt;homelab-ad-blocking-pihole&lt;/code&gt; — &amp;#8220;Pi-hole installation&amp;nbsp;guide&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;item-5&lt;/code&gt; → &lt;code&gt;portainer-setup-guide&lt;/code&gt; — &amp;#8220;Portainer installation&amp;nbsp;guide&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;proxmox-beginner-guide-2026&lt;/code&gt; — &amp;#8220;start with a Proxmox&amp;nbsp;host&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] What are your top 5 self-hosted apps? Share your stack in the&amp;nbsp;comments!&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for app reviews, Docker Compose templates, and security&amp;nbsp;updates.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Guides"/><category term="self-hosted"/><category term="apps"/><category term="homelab"/><category term="2026"/><category term="nextcloud"/><category term="jellyfin"/><category term="immich"/><category term="pihole"/></entry><entry><title>Best UPS for Home Server 2026: Power Protection for Your Homelab</title><link href="https://steadypub.com/2026/06/best-ups-for-home-server/" rel="alternate"/><published>2026-06-05T00:00:00+07:00</published><updated>2026-06-05T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/best-ups-for-home-server/</id><summary type="html">&lt;p&gt;A curated ranking of the best &lt;span class="caps"&gt;UPS&lt;/span&gt; units for home servers in 2026. Covers &lt;span class="caps"&gt;APC&lt;/span&gt;, CyberPower, and Eaton models with real runtime calculations, sizing math, and &lt;span class="caps"&gt;NUT&lt;/span&gt;&amp;nbsp;integration.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~12 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Home server owners who want clean power and graceful&amp;nbsp;shutdowns&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why a &lt;span class="caps"&gt;UPS&lt;/span&gt; for Your Home&amp;nbsp;Server?&lt;/h2&gt;
&lt;p&gt;A &lt;span class="caps"&gt;UPS&lt;/span&gt; (Uninterruptible Power Supply) does two critical things: it filters dirty power (surges, brownouts) and provides battery backup during outages long enough for your server to shut down gracefully. A hard shutdown can corrupt &lt;span class="caps"&gt;ZFS&lt;/span&gt; pools, damage databases, and kill spinning disks. A &lt;span class="caps"&gt;UPS&lt;/span&gt; is the cheapest insurance you can buy for your&amp;nbsp;data.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Evaluation&amp;nbsp;Criteria&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Criteria&lt;/th&gt;
&lt;th&gt;Why It Matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;VA&lt;/span&gt; / Watt Rating&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;VA&lt;/span&gt; is apparent power; Watts is real power. Match the wattage to your load, not just the &lt;span class="caps"&gt;VA&lt;/span&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Runtime&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;How long the &lt;span class="caps"&gt;UPS&lt;/span&gt; can power your load at 50% draw.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Topology&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Line-interactive (common, good for homelab) vs. Online double-conversion (best, expensive).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Outlets&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Ensure enough battery-backed outlets for server, switch, router, and modem.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;USB&lt;/span&gt; / Network Management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;USB&lt;/span&gt; or &lt;span class="caps"&gt;SNMP&lt;/span&gt; card lets the &lt;span class="caps"&gt;UPS&lt;/span&gt; signal the &lt;span class="caps"&gt;OS&lt;/span&gt; to shut down before battery depletion.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Pure Sine Wave&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Critical for Active &lt;span class="caps"&gt;PFC&lt;/span&gt; power supplies in modern servers.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Expandability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Some &lt;span class="caps"&gt;APC&lt;/span&gt; units accept external battery packs (&lt;span class="caps"&gt;EBM&lt;/span&gt;) to extend runtime.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;#1: &lt;span class="caps"&gt;APC&lt;/span&gt; Back-&lt;span class="caps"&gt;UPS&lt;/span&gt; Pro &lt;span class="caps"&gt;BR1500G&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;span class="caps"&gt;BR1500G&lt;/span&gt; is the standard home server &lt;span class="caps"&gt;UPS&lt;/span&gt;. It offers 1500 &lt;span class="caps"&gt;VA&lt;/span&gt; / 865 W, 10 outlets, &lt;span class="caps"&gt;USB&lt;/span&gt; management, and &lt;span class="caps"&gt;APC&lt;/span&gt;&amp;#8217;s PowerChute software. The &lt;span class="caps"&gt;LCD&lt;/span&gt; shows load percentage and runtime. It is reliable, widely available, and integrates seamlessly with &lt;span class="caps"&gt;NUT&lt;/span&gt; on Linux and&amp;nbsp;Proxmox.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Specs:&lt;/strong&gt; 1500 &lt;span class="caps"&gt;VA&lt;/span&gt; / 865 W | 10 outlets | ~12 min @ 50% | &lt;span class="caps"&gt;USB&lt;/span&gt; |&amp;nbsp;$180–220&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Small-to-medium home servers with a load under 500&amp;nbsp;W.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;#2: CyberPower &lt;span class="caps"&gt;CP1500PFCLCD&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;span class="caps"&gt;CP1500PFCLCD&lt;/span&gt; uses a &lt;strong&gt;pure sine wave&lt;/strong&gt; inverter, which is critical for Active &lt;span class="caps"&gt;PFC&lt;/span&gt; power supplies. It offers 1500 &lt;span class="caps"&gt;VA&lt;/span&gt; / 900 W, 12 outlets, and a &lt;span class="caps"&gt;USB&lt;/span&gt; charging port. CyberPower&amp;#8217;s software is Linux-friendly and supports &lt;span class="caps"&gt;NUT&lt;/span&gt; out of the&amp;nbsp;box.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Specs:&lt;/strong&gt; 1500 &lt;span class="caps"&gt;VA&lt;/span&gt; / 900 W | 12 outlets | ~10 min @ 50% | Pure sine |&amp;nbsp;$170–210&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Users with Active &lt;span class="caps"&gt;PFC&lt;/span&gt; PSUs who want pure sine wave on a&amp;nbsp;budget.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;#3: &lt;span class="caps"&gt;APC&lt;/span&gt; Smart-&lt;span class="caps"&gt;UPS&lt;/span&gt; &lt;span class="caps"&gt;SMT1500RM2U&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;For rack servers, the &lt;span class="caps"&gt;SMT1500RM2U&lt;/span&gt; is the industry standard. It is a 2U rackmount unit with 1500 &lt;span class="caps"&gt;VA&lt;/span&gt; / 1000 W, optional &lt;span class="caps"&gt;SNMP&lt;/span&gt; network card, and support for external battery modules. It is overkill for a mini &lt;span class="caps"&gt;PC&lt;/span&gt; but essential for a rack&amp;nbsp;server.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Specs:&lt;/strong&gt; 1500 &lt;span class="caps"&gt;VA&lt;/span&gt; / 1000 W | 8 outlets | ~18 min @ 50% | Rackmount |&amp;nbsp;$600–800&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Rack homelabs with 500–800 W&amp;nbsp;loads.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;#4: Eaton&amp;nbsp;5E650iUSB&lt;/h2&gt;
&lt;p&gt;For very small servers (one mini &lt;span class="caps"&gt;PC&lt;/span&gt; + router), the Eaton 5E650iUSB is a compact, budget-friendly &lt;span class="caps"&gt;UPS&lt;/span&gt;. It provides 650 &lt;span class="caps"&gt;VA&lt;/span&gt; / 360 W, which is enough for a low-power&amp;nbsp;setup.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Specs:&lt;/strong&gt; 650 &lt;span class="caps"&gt;VA&lt;/span&gt; / 360 W | 4 outlets | ~8 min @ 50% |&amp;nbsp;$60–80&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Single-node mini &lt;span class="caps"&gt;PC&lt;/span&gt; servers with a load under 200&amp;nbsp;W.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;#5: &lt;span class="caps"&gt;APC&lt;/span&gt; Back-&lt;span class="caps"&gt;UPS&lt;/span&gt; &lt;span class="caps"&gt;BR1500MS&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;span class="caps"&gt;BR1500MS&lt;/span&gt; is the pure sine wave version of the &lt;span class="caps"&gt;BR1500G&lt;/span&gt; with a &lt;span class="caps"&gt;USB&lt;/span&gt;-C charging port and &lt;span class="caps"&gt;AVR&lt;/span&gt;. It is the safest choice for modern Active &lt;span class="caps"&gt;PFC&lt;/span&gt; power&amp;nbsp;supplies.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Specs:&lt;/strong&gt; 1500 &lt;span class="caps"&gt;VA&lt;/span&gt; / 900 W | 10 outlets | ~11 min @ 50% | Pure sine |&amp;nbsp;$220–260&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Users who want the best waveform protection and &lt;span class="caps"&gt;USB&lt;/span&gt;-C&amp;nbsp;charging.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Quick Comparison&amp;nbsp;Table&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;VA&lt;/span&gt; / Watt&lt;/th&gt;
&lt;th&gt;Outlets&lt;/th&gt;
&lt;th&gt;Runtime @ 50%&lt;/th&gt;
&lt;th&gt;Pure Sine&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;APC&lt;/span&gt; &lt;span class="caps"&gt;BR1500G&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1500 / 865&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;~12 min&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;$180–220&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CyberPower &lt;span class="caps"&gt;CP1500PFCLCD&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1500 / 900&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;~10 min&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;$170–210&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;APC&lt;/span&gt; &lt;span class="caps"&gt;SMT1500RM2U&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1500 / 1000&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;~18 min&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;$600–800&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Eaton 5E650iUSB&lt;/td&gt;
&lt;td&gt;650 / 360&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;~8 min&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;$60–80&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;APC&lt;/span&gt; &lt;span class="caps"&gt;BR1500MS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1500 / 900&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;~11 min&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;$220–260&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Calculate Your&amp;nbsp;Load&lt;/h3&gt;
&lt;p&gt;Use a Kill-A-Watt meter to measure actual wattage. Add 20%&amp;nbsp;headroom.&lt;/p&gt;
&lt;h3&gt;Tip 2: Use &lt;span class="caps"&gt;NUT&lt;/span&gt; for Automated&amp;nbsp;Shutdown&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;nut
&lt;span class="c1"&gt;# Configure /etc/nut/ups.conf with usbhid-ups driver&lt;/span&gt;
&lt;span class="c1"&gt;# Set shutdown threshold in /etc/nut/upsmon.conf&lt;/span&gt;
systemctl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;nut-client
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 3: Replace Batteries Every 3–5&amp;nbsp;Years&lt;/h3&gt;
&lt;p&gt;&lt;span class="caps"&gt;SLA&lt;/span&gt; batteries degrade. Replace proactively to maintain&amp;nbsp;runtime.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;For most home servers, the &lt;strong&gt;&lt;span class="caps"&gt;APC&lt;/span&gt; Back-&lt;span class="caps"&gt;UPS&lt;/span&gt; Pro &lt;span class="caps"&gt;BR1500G&lt;/span&gt;&lt;/strong&gt; or the &lt;strong&gt;CyberPower &lt;span class="caps"&gt;CP1500PFCLCD&lt;/span&gt;&lt;/strong&gt; is the sweet spot. They offer enough wattage for a mini &lt;span class="caps"&gt;PC&lt;/span&gt; or tower server, have &lt;span class="caps"&gt;USB&lt;/span&gt; monitoring, and support &lt;span class="caps"&gt;NUT&lt;/span&gt;. If you have a rack server, step up to the &lt;strong&gt;&lt;span class="caps"&gt;APC&lt;/span&gt; Smart-&lt;span class="caps"&gt;UPS&lt;/span&gt; &lt;span class="caps"&gt;SMT1500RM2U&lt;/span&gt;&lt;/strong&gt;. For a single-node mini &lt;span class="caps"&gt;PC&lt;/span&gt;, the &lt;strong&gt;Eaton 5E650iUSB&lt;/strong&gt; is a budget-friendly&amp;nbsp;start.&lt;/p&gt;
&lt;h3&gt;Our&amp;nbsp;Recommendation&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mini &lt;span class="caps"&gt;PC&lt;/span&gt; server (1 node):&lt;/strong&gt; Eaton 5E650iUSB ($70) or CyberPower &lt;span class="caps"&gt;CP1500PFCLCD&lt;/span&gt;&amp;nbsp;($190)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tower server / &lt;span class="caps"&gt;NAS&lt;/span&gt; (2–3 nodes):&lt;/strong&gt; &lt;span class="caps"&gt;APC&lt;/span&gt; &lt;span class="caps"&gt;BR1500G&lt;/span&gt; ($200) or CyberPower &lt;span class="caps"&gt;CP1500PFCLCD&lt;/span&gt;&amp;nbsp;($190)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rack server (500+ W):&lt;/strong&gt; &lt;span class="caps"&gt;APC&lt;/span&gt; &lt;span class="caps"&gt;SMT1500RM2U&lt;/span&gt; ($700) + external battery&amp;nbsp;pack&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;APC&lt;/span&gt; / CyberPower / Eaton:&lt;/strong&gt; Amazon, B&amp;amp;H, or Newegg affiliate&amp;nbsp;links&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Replacement batteries:&lt;/strong&gt; &lt;span class="caps"&gt;RBC123&lt;/span&gt;, &lt;span class="caps"&gt;RBC7&lt;/span&gt;, and generic 12V 7Ah battery&amp;nbsp;packs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;NUT&lt;/span&gt; accessories:&lt;/strong&gt; &lt;span class="caps"&gt;USB&lt;/span&gt; cables, network&amp;nbsp;cards&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;why-this-matters&lt;/code&gt; → &lt;code&gt;ups-for-homelab&lt;/code&gt; — &amp;#8220;general &lt;span class="caps"&gt;UPS&lt;/span&gt; guide for&amp;nbsp;homelabs&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;item-1&lt;/code&gt; → &lt;code&gt;apc-ups-homelab&lt;/code&gt; — &amp;#8220;deep dive into &lt;span class="caps"&gt;APC&lt;/span&gt; &lt;span class="caps"&gt;UPS&lt;/span&gt;&amp;nbsp;models&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;proxmox-beginner-guide-2026&lt;/code&gt; — &amp;#8220;protect your Proxmox&amp;nbsp;host&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;What &lt;span class="caps"&gt;UPS&lt;/span&gt; keeps your server alive?&lt;/strong&gt; Share your model and runtime&amp;nbsp;below.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subscribe&lt;/strong&gt; for power efficiency guides and homelab safety&amp;nbsp;tips.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Guides"/><category term="best ups for home server"/><category term="ups homelab"/><category term="power backup"/><category term="uninterruptible power supply"/><category term="apc"/><category term="cyberpower"/></entry><entry><title>Best VPS for Homelab 2026: Self-Hosting in the Cloud</title><link href="https://steadypub.com/2026/06/best-vps-for-homelab/" rel="alternate"/><published>2026-06-05T00:00:00+07:00</published><updated>2026-06-05T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/best-vps-for-homelab/</id><summary type="html">&lt;p&gt;Compare the best &lt;span class="caps"&gt;VPS&lt;/span&gt; providers for homelab self-hosting in 2026. Hetzner, DigitalOcean, Vultr, Linode, and Oracle Cloud ranked by performance, price, and&amp;nbsp;features.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~14 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelabbers choosing a &lt;span class="caps"&gt;VPS&lt;/span&gt; to extend their self-hosted&amp;nbsp;infrastructure&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why a &lt;span class="caps"&gt;VPS&lt;/span&gt; for Your&amp;nbsp;Homelab?&lt;/h2&gt;
&lt;p&gt;A &lt;span class="caps"&gt;VPS&lt;/span&gt; (Virtual Private Server) is a rented virtual machine in a data center. For homelabbers, it solves three problems:
1. &lt;strong&gt;Public &lt;span class="caps"&gt;IP&lt;/span&gt; and open ports:&lt;/strong&gt; Residential ISPs block port 25, 80, and 443. A &lt;span class="caps"&gt;VPS&lt;/span&gt; has all ports open.
2. &lt;strong&gt;Static &lt;span class="caps"&gt;IP&lt;/span&gt;:&lt;/strong&gt; Most home ISPs use dynamic IPs. A &lt;span class="caps"&gt;VPS&lt;/span&gt; gives you a stable &lt;span class="caps"&gt;IP&lt;/span&gt; for &lt;span class="caps"&gt;DNS&lt;/span&gt; records.
3. &lt;strong&gt;Uptime and power:&lt;/strong&gt; Data centers have redundant power and internet. Your services stay online even when your house loses&amp;nbsp;power.&lt;/p&gt;
&lt;p&gt;A &lt;span class="caps"&gt;VPS&lt;/span&gt; is not a replacement for your homelab — it is an extension. You run public-facing services (website, &lt;span class="caps"&gt;VPN&lt;/span&gt;, email) on the &lt;span class="caps"&gt;VPS&lt;/span&gt; while keeping private data (photos, documents, media) at&amp;nbsp;home.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Top &lt;span class="caps"&gt;VPS&lt;/span&gt; Providers for Homelab&amp;nbsp;Self-Hosting&lt;/h2&gt;
&lt;h3&gt;#1: Hetzner&amp;nbsp;Cloud&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Price-to-performance and European&amp;nbsp;hosting.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plan&lt;/th&gt;
&lt;th&gt;Specs&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;CX11&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1 vCPU, 2 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, 20 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;€3.79/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;CPX11&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;2 vCPU, 2 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, 40 &lt;span class="caps"&gt;GB&lt;/span&gt; NVMe&lt;/td&gt;
&lt;td&gt;€4.51/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;CX21&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;2 vCPU, 4 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, 40 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;€5.35/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;CPX21&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;2 vCPU, 4 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, 80 &lt;span class="caps"&gt;GB&lt;/span&gt; NVMe&lt;/td&gt;
&lt;td&gt;€6.14/month&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;
- Best price-to-performance in the industry.
- No bandwidth overage charges (20 &lt;span class="caps"&gt;TB&lt;/span&gt; included).
- Custom &lt;span class="caps"&gt;ISO&lt;/span&gt; support (install any &lt;span class="caps"&gt;OS&lt;/span&gt;).
- Excellent network (German data centers).
- IPv6&amp;nbsp;support.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;
- European data centers only (latency for Asia/Americas).
- No phone support (ticket/email only).
- Anti-spam verification required for &lt;span class="caps"&gt;SMTP&lt;/span&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;#2:&amp;nbsp;DigitalOcean&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Beginners and&amp;nbsp;developers.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plan&lt;/th&gt;
&lt;th&gt;Specs&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Basic Droplet&lt;/td&gt;
&lt;td&gt;1 vCPU, 512 &lt;span class="caps"&gt;MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, 10 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$4/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Basic Droplet&lt;/td&gt;
&lt;td&gt;1 vCPU, 1 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, 25 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$6/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Basic Droplet&lt;/td&gt;
&lt;td&gt;1 vCPU, 2 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, 50 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$12/month&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;
- Simplest &lt;span class="caps"&gt;UI&lt;/span&gt; in the industry.
- Excellent documentation and tutorials.
- Managed Kubernetes, databases, and load balancers.
- 99.99% uptime &lt;span class="caps"&gt;SLA&lt;/span&gt;.
- Good &lt;span class="caps"&gt;API&lt;/span&gt; and &lt;span class="caps"&gt;CLI&lt;/span&gt;&amp;nbsp;(&lt;code&gt;doctl&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;
- More expensive than Hetzner for similar specs.
- No custom &lt;span class="caps"&gt;ISO&lt;/span&gt; support.
- Bandwidth overages after 500 &lt;span class="caps"&gt;GB&lt;/span&gt;–4 &lt;span class="caps"&gt;TB&lt;/span&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;#3:&amp;nbsp;Vultr&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Global presence and custom &lt;span class="caps"&gt;OS&lt;/span&gt;.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plan&lt;/th&gt;
&lt;th&gt;Specs&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cloud Compute&lt;/td&gt;
&lt;td&gt;1 vCPU, 1 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, 25 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$5/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloud Compute&lt;/td&gt;
&lt;td&gt;2 vCPU, 2 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, 55 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$10/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloud Compute&lt;/td&gt;
&lt;td&gt;2 vCPU, 4 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, 80 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$20/month&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;
- 30+ global locations.
- Custom &lt;span class="caps"&gt;ISO&lt;/span&gt; and snapshot support.
- Bare metal instances available.
- Hourly billing.
- Fast NVMe&amp;nbsp;storage.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;
- Support is ticket-only.
- &lt;span class="caps"&gt;IP&lt;/span&gt; reputation issues in some&amp;nbsp;locations.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;#4: Linode&amp;nbsp;(Akamai)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Support and&amp;nbsp;reliability.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plan&lt;/th&gt;
&lt;th&gt;Specs&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Nanode&lt;/td&gt;
&lt;td&gt;1 vCPU, 1 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, 25 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$5/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linode &lt;span class="caps"&gt;2GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1 vCPU, 2 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, 50 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$12/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linode &lt;span class="caps"&gt;4GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;2 vCPU, 4 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, 80 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$24/month&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;
- Excellent customer support (phone, ticket, &lt;span class="caps"&gt;IRC&lt;/span&gt;).
- 99.99% uptime &lt;span class="caps"&gt;SLA&lt;/span&gt;.
- Good documentation and community.
- Managed services (databases,&amp;nbsp;Kubernetes).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;
- More expensive than Hetzner and Vultr.
- Slower innovation than&amp;nbsp;competitors.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;#5: Oracle Cloud Free&amp;nbsp;Tier&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Free&amp;nbsp;resources.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plan&lt;/th&gt;
&lt;th&gt;Specs&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Always Free (&lt;span class="caps"&gt;AMD&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;2x 1/8 &lt;span class="caps"&gt;OCPU&lt;/span&gt;, 1 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Always Free (&lt;span class="caps"&gt;ARM&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;4 &lt;span class="caps"&gt;OCPU&lt;/span&gt;, 24 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Always Free Storage&lt;/td&gt;
&lt;td&gt;200 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;
- Completely free (no expiration).
- Powerful &lt;span class="caps"&gt;ARM&lt;/span&gt; instance (4 cores, 24 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;).
- 10 &lt;span class="caps"&gt;TB&lt;/span&gt; outbound&amp;nbsp;bandwidth.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;
- Account termination risk.
- Difficult signup process.
- No IPv6.
- Limited&amp;nbsp;support.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Comparison&amp;nbsp;Matrix&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;Price (2 vCPU, 4 &lt;span class="caps"&gt;GB&lt;/span&gt;)&lt;/th&gt;
&lt;th&gt;Locations&lt;/th&gt;
&lt;th&gt;Custom &lt;span class="caps"&gt;ISO&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Support&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Hetzner&lt;/td&gt;
&lt;td&gt;Budget performance&lt;/td&gt;
&lt;td&gt;€6.14/month&lt;/td&gt;
&lt;td&gt;3 (&lt;span class="caps"&gt;EU&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DigitalOcean&lt;/td&gt;
&lt;td&gt;Beginners&lt;/td&gt;
&lt;td&gt;$24/month&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vultr&lt;/td&gt;
&lt;td&gt;Global presence&lt;/td&gt;
&lt;td&gt;$20/month&lt;/td&gt;
&lt;td&gt;30+&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Fair&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linode&lt;/td&gt;
&lt;td&gt;Reliability&lt;/td&gt;
&lt;td&gt;$24/month&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Excellent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Oracle Cloud&lt;/td&gt;
&lt;td&gt;Free hosting&lt;/td&gt;
&lt;td&gt;$0/month&lt;/td&gt;
&lt;td&gt;20+&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Poor&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;How to&amp;nbsp;Choose&lt;/h2&gt;
&lt;h3&gt;Scenario 1: &amp;#8220;I want the best performance for the lowest&amp;nbsp;price.&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose Hetzner Cloud.&lt;/strong&gt; The &lt;span class="caps"&gt;CPX21&lt;/span&gt; plan (€6.14) offers NVMe storage, 2 vCPU, and 4 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; — unbeatable&amp;nbsp;value.&lt;/p&gt;
&lt;h3&gt;Scenario 2: &amp;#8220;I want the easiest setup and best&amp;nbsp;documentation.&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose DigitalOcean.&lt;/strong&gt; The tutorials and &lt;span class="caps"&gt;UI&lt;/span&gt; are the most&amp;nbsp;beginner-friendly.&lt;/p&gt;
&lt;h3&gt;Scenario 3: &amp;#8220;I need a &lt;span class="caps"&gt;VPS&lt;/span&gt; in Asia or South&amp;nbsp;America.&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose Vultr.&lt;/strong&gt; They have data centers in Singapore, Mumbai, Sydney, Sao Paulo, and&amp;nbsp;Johannesburg.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Hetzner Cloud is the best &lt;span class="caps"&gt;VPS&lt;/span&gt; for homelab self-hosting in 2026 due to its unbeatable price-to-performance. DigitalOcean is the best for beginners. Vultr is the best for global coverage. Oracle Cloud is the best for free resources. A &lt;span class="caps"&gt;VPS&lt;/span&gt; extends your homelab into the cloud, giving you public IPs, static addresses, and always-on&amp;nbsp;infrastructure.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Choose a provider&lt;/strong&gt; based on your budget and location&amp;nbsp;needs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deploy a &lt;span class="caps"&gt;VPS&lt;/span&gt;&lt;/strong&gt; with Ubuntu 22.04/24.04 &lt;span class="caps"&gt;LTS&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Harden the server&lt;/strong&gt; with &lt;span class="caps"&gt;UFW&lt;/span&gt;, Fail2ban, and &lt;span class="caps"&gt;SSH&lt;/span&gt;&amp;nbsp;keys.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Install Docker&lt;/strong&gt; and deploy your first public&amp;nbsp;service.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Connect to your home&lt;/strong&gt; via WireGuard or&amp;nbsp;Tailscale.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Hetzner Cloud:&lt;/strong&gt; Referral&amp;nbsp;credits.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DigitalOcean:&lt;/strong&gt; Referral&amp;nbsp;credits.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vultr:&lt;/strong&gt; Referral&amp;nbsp;credits.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;VPN&lt;/span&gt; tools:&lt;/strong&gt; Tailscale, WireGuard,&amp;nbsp;NetBird.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;intro&lt;/code&gt; → &lt;code&gt;cheap-vps-for-self-hosting&lt;/code&gt; — &amp;#8220;budget &lt;span class="caps"&gt;VPS&lt;/span&gt;&amp;nbsp;options&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scenario&lt;/code&gt; → &lt;code&gt;vps-for-docker-containers-homelab&lt;/code&gt; — &amp;#8220;deploy Docker on your &lt;span class="caps"&gt;VPS&lt;/span&gt;&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;docker-compose-for-beginners&lt;/code&gt; — &amp;#8220;start deploying&amp;nbsp;containers&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Which &lt;span class="caps"&gt;VPS&lt;/span&gt; runs your homelab?&lt;/strong&gt; Share your provider and specs in the&amp;nbsp;comments.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subscribe&lt;/strong&gt; for &lt;span class="caps"&gt;VPS&lt;/span&gt; reviews, cloud security, and hybrid homelab&amp;nbsp;guides.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Infrastructure"/><category term="best vps for homelab"/><category term="self-hosting vps"/><category term="cloud server"/><category term="homelab"/><category term="hetzner"/><category term="digitalocean"/></entry><entry><title>Cheap VPS for Self-Hosting 2026: Best Budget Cloud Servers for Homelabbers</title><link href="https://steadypub.com/2026/06/cheap-vps-for-self-hosting/" rel="alternate"/><published>2026-06-05T00:00:00+07:00</published><updated>2026-06-05T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/cheap-vps-for-self-hosting/</id><summary type="html">&lt;p&gt;The best cheap &lt;span class="caps"&gt;VPS&lt;/span&gt; providers for self-hosting in 2026. Compare Hetzner, DigitalOcean, Vultr, and Oracle Cloud Free Tier for running Docker, VPNs, and public-facing&amp;nbsp;services.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~14 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelabbers who want a public-facing &lt;span class="caps"&gt;VPS&lt;/span&gt; without breaking the&amp;nbsp;bank&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is a Cheap &lt;span class="caps"&gt;VPS&lt;/span&gt; for&amp;nbsp;Self-Hosting?&lt;/h2&gt;
&lt;p&gt;A cheap &lt;span class="caps"&gt;VPS&lt;/span&gt; is a low-cost virtual private server ($3–10/month) that extends your homelab into the cloud. It provides a public &lt;span class="caps"&gt;IP&lt;/span&gt;, DDoS protection, and 24/7 uptime — things most residential ISPs cannot offer. For self-hosters, a &lt;span class="caps"&gt;VPS&lt;/span&gt; is the bridge between your private &lt;span class="caps"&gt;LAN&lt;/span&gt; and the public&amp;nbsp;internet.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why Use a Cheap &lt;span class="caps"&gt;VPS&lt;/span&gt;?&lt;/h2&gt;
&lt;h3&gt;Public &lt;span class="caps"&gt;IP&lt;/span&gt; and Port&amp;nbsp;Availability&lt;/h3&gt;
&lt;p&gt;Data centers provide static or stable IPs with all ports open. You can run an &lt;span class="caps"&gt;SMTP&lt;/span&gt; relay, a public-facing web server, or a game server without fighting &lt;span class="caps"&gt;CGNAT&lt;/span&gt; or &lt;span class="caps"&gt;ISP&lt;/span&gt;&amp;nbsp;firewalls.&lt;/p&gt;
&lt;h3&gt;Geographic&amp;nbsp;Diversity&lt;/h3&gt;
&lt;p&gt;Hosting a &lt;span class="caps"&gt;VPS&lt;/span&gt; in a different region lets you serve content closer to your users. A &lt;span class="caps"&gt;VPS&lt;/span&gt; in Frankfurt or New York can act as a &lt;span class="caps"&gt;CDN&lt;/span&gt; edge or a failover&amp;nbsp;endpoint.&lt;/p&gt;
&lt;h3&gt;Offsite Backup&amp;nbsp;Target&lt;/h3&gt;
&lt;p&gt;A &lt;span class="caps"&gt;VPS&lt;/span&gt; is an ideal offsite backup target. Run a MinIO container, a restic server, or a BorgBackup repository and schedule nightly backups from your&amp;nbsp;homelab.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Top Cheap &lt;span class="caps"&gt;VPS&lt;/span&gt; Providers for&amp;nbsp;Self-Hosting&lt;/h2&gt;
&lt;h3&gt;#1: Hetzner&amp;nbsp;Cloud&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Why it tops our list:&lt;/strong&gt; Hetzner offers the best price-to-performance ratio in Europe. Their &lt;span class="caps"&gt;ARM64&lt;/span&gt; instances are even&amp;nbsp;cheaper.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plan&lt;/th&gt;
&lt;th&gt;Specs&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;CX11&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1 vCPU, 2 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, 20 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;€3.79/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;CPX11&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;2 vCPU, 2 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, 40 &lt;span class="caps"&gt;GB&lt;/span&gt; NVMe&lt;/td&gt;
&lt;td&gt;€4.51/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;CX21&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;2 vCPU, 4 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, 40 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;€5.35/month&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;
- Cheapest reliable &lt;span class="caps"&gt;VPS&lt;/span&gt; on the market.
- Excellent network performance (German data centers).
- Custom &lt;span class="caps"&gt;ISO&lt;/span&gt; support (install Proxmox, TrueNAS, etc.).
- No bandwidth overage charges (20 &lt;span class="caps"&gt;TB&lt;/span&gt;&amp;nbsp;included).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;
- European data centers only (latency for Asia/Americas).
- No managed services (you are on your own).
- Anti-spam policies require verification for &lt;span class="caps"&gt;SMTP&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Budget-conscious homelabbers who want maximum performance per&amp;nbsp;dollar.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;#2:&amp;nbsp;DigitalOcean&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Why it made the list:&lt;/strong&gt; DigitalOcean has the simplest &lt;span class="caps"&gt;UI&lt;/span&gt; and excellent documentation. Perfect for&amp;nbsp;beginners.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plan&lt;/th&gt;
&lt;th&gt;Specs&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Basic Droplet&lt;/td&gt;
&lt;td&gt;1 vCPU, 512 &lt;span class="caps"&gt;MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, 10 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$4/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Basic Droplet&lt;/td&gt;
&lt;td&gt;1 vCPU, 1 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, 25 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$6/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Basic Droplet&lt;/td&gt;
&lt;td&gt;1 vCPU, 2 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, 50 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$12/month&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;
- Simple, clean &lt;span class="caps"&gt;UI&lt;/span&gt;.
- Excellent documentation and community tutorials.
- 99.99% uptime &lt;span class="caps"&gt;SLA&lt;/span&gt;.
- Managed databases, Kubernetes, and load balancers&amp;nbsp;available.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;
- More expensive than Hetzner for the same specs.
- No custom &lt;span class="caps"&gt;ISO&lt;/span&gt; support.
- Bandwidth overages apply after 500 &lt;span class="caps"&gt;GB&lt;/span&gt;–4 &lt;span class="caps"&gt;TB&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Beginners who want a polished experience and good&amp;nbsp;support.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;#3:&amp;nbsp;Vultr&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Why it made the list:&lt;/strong&gt; Vultr offers the most locations (30+), custom ISOs, and bare metal&amp;nbsp;instances.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plan&lt;/th&gt;
&lt;th&gt;Specs&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cloud Compute&lt;/td&gt;
&lt;td&gt;1 vCPU, 1 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, 25 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$5/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloud Compute&lt;/td&gt;
&lt;td&gt;1 vCPU, 2 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, 50 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$10/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloud Compute&lt;/td&gt;
&lt;td&gt;2 vCPU, 2 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, 55 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$10/month&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;
- 30+ global locations (including Asia, Australia, South America).
- Custom &lt;span class="caps"&gt;ISO&lt;/span&gt; support.
- Bare metal instances available.
- Hourly&amp;nbsp;billing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;
- Support is ticket-only (no live chat).
- Occasional &lt;span class="caps"&gt;IP&lt;/span&gt; reputation issues (previous spam&amp;nbsp;abuse).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Users who need a &lt;span class="caps"&gt;VPS&lt;/span&gt; in a specific region or want custom &lt;span class="caps"&gt;OS&lt;/span&gt;&amp;nbsp;installations.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;#4: Oracle Cloud Free Tier (Always&amp;nbsp;Free)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Why it made the list:&lt;/strong&gt; Oracle offers genuinely free &lt;span class="caps"&gt;VPS&lt;/span&gt; instances that never&amp;nbsp;expire.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plan&lt;/th&gt;
&lt;th&gt;Specs&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Always Free&lt;/td&gt;
&lt;td&gt;2x &lt;span class="caps"&gt;AMD&lt;/span&gt; instances (1/8 &lt;span class="caps"&gt;OCPU&lt;/span&gt;, 1 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Always Free&lt;/td&gt;
&lt;td&gt;1x &lt;span class="caps"&gt;ARM&lt;/span&gt; instance (4 &lt;span class="caps"&gt;OCPU&lt;/span&gt;, 24 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Always Free&lt;/td&gt;
&lt;td&gt;200 &lt;span class="caps"&gt;GB&lt;/span&gt; block storage&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;
- Completely free (no credit card required for some regions).
- &lt;span class="caps"&gt;ARM&lt;/span&gt; instance is powerful (4 cores, 24 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;).
- 10 &lt;span class="caps"&gt;TB&lt;/span&gt; outbound&amp;nbsp;bandwidth/month.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;
- Accounts are sometimes terminated without warning (&amp;#8220;suspicious activity&amp;#8221;).
- Limited support (community forums only).
- Requires verification and can be hard to sign up.
- No&amp;nbsp;IPv6.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Users who want a powerful free server and are willing to risk account&amp;nbsp;instability.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;#5:&amp;nbsp;Racknerd&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Why it made the list:&lt;/strong&gt; Racknerd specializes in ultra-cheap annual plans. They resell ColoCrossing&amp;nbsp;infrastructure.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plan&lt;/th&gt;
&lt;th&gt;Specs&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;KVM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1 vCPU, 1 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, 20 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$11.88/year&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;KVM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1 vCPU, 2 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, 35 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$18.88/year&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;KVM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;2 vCPU, 4 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, 60 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$28.88/year&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;
- Extremely cheap annual plans.
- &lt;span class="caps"&gt;US&lt;/span&gt;-based data centers.
- Full &lt;span class="caps"&gt;KVM&lt;/span&gt;&amp;nbsp;access.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;
- Budget provider (expect less reliable support).
- No managed services.
- Reputation for&amp;nbsp;oversubscription.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Users who want the absolute cheapest &lt;span class="caps"&gt;VPS&lt;/span&gt; for light&amp;nbsp;workloads.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Quick Comparison&amp;nbsp;Table&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;Cheapest Plan&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Best Feature&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Hetzner&lt;/td&gt;
&lt;td&gt;€3.79/month&lt;/td&gt;
&lt;td&gt;2 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Price/performance&lt;/td&gt;
&lt;td&gt;Budget performance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DigitalOcean&lt;/td&gt;
&lt;td&gt;$4/month&lt;/td&gt;
&lt;td&gt;512 &lt;span class="caps"&gt;MB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;UI&lt;/span&gt;/docs&lt;/td&gt;
&lt;td&gt;Beginners&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vultr&lt;/td&gt;
&lt;td&gt;$5/month&lt;/td&gt;
&lt;td&gt;1 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Global locations&lt;/td&gt;
&lt;td&gt;Specific regions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Oracle Cloud&lt;/td&gt;
&lt;td&gt;$0/month&lt;/td&gt;
&lt;td&gt;24 &lt;span class="caps"&gt;GB&lt;/span&gt; (&lt;span class="caps"&gt;ARM&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;Free forever&lt;/td&gt;
&lt;td&gt;Cost-sensitive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Racknerd&lt;/td&gt;
&lt;td&gt;$11.88/year&lt;/td&gt;
&lt;td&gt;1 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Ultra-cheap&lt;/td&gt;
&lt;td&gt;Light workloads&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;How to&amp;nbsp;Choose&lt;/h2&gt;
&lt;h3&gt;Scenario 1: &amp;#8220;I want the cheapest reliable &lt;span class="caps"&gt;VPS&lt;/span&gt; for&amp;nbsp;Docker.&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose Hetzner Cloud.&lt;/strong&gt; The €4.51 &lt;span class="caps"&gt;CPX11&lt;/span&gt; plan (2 vCPU, 2 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, NVMe) outperforms competitors at double the&amp;nbsp;price.&lt;/p&gt;
&lt;h3&gt;Scenario 2: &amp;#8220;I am a beginner and want good&amp;nbsp;documentation.&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose DigitalOcean.&lt;/strong&gt; The tutorials are unmatched, and the &lt;span class="caps"&gt;UI&lt;/span&gt; is the&amp;nbsp;friendliest.&lt;/p&gt;
&lt;h3&gt;Scenario 3: &amp;#8220;I want a free &lt;span class="caps"&gt;VPS&lt;/span&gt; and do not mind&amp;nbsp;risk.&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose Oracle Cloud Free Tier.&lt;/strong&gt; The &lt;span class="caps"&gt;ARM&lt;/span&gt; instance (4 &lt;span class="caps"&gt;OCPU&lt;/span&gt;, 24 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;) is powerful enough for a full homelab&amp;nbsp;stack.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Security Hardening&amp;nbsp;Checklist&lt;/h2&gt;
&lt;p&gt;Before running any public services on a cheap &lt;span class="caps"&gt;VPS&lt;/span&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# 1. Update the system&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;upgrade&lt;span class="w"&gt; &lt;/span&gt;-y

&lt;span class="c1"&gt;# 2. Create a non-root user&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;adduser&lt;span class="w"&gt; &lt;/span&gt;homelab
sudo&lt;span class="w"&gt; &lt;/span&gt;usermod&lt;span class="w"&gt; &lt;/span&gt;-aG&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;homelab

&lt;span class="c1"&gt;# 3. Disable root login and password auth&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;sed&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;s/#PermitRootLogin yes/PermitRootLogin no/&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/ssh/sshd_config
sudo&lt;span class="w"&gt; &lt;/span&gt;sed&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;s/#PasswordAuthentication yes/PasswordAuthentication no/&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/ssh/sshd_config
sudo&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;restart&lt;span class="w"&gt; &lt;/span&gt;sshd

&lt;span class="c1"&gt;# 4. Enable UFW&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;ufw&lt;span class="w"&gt; &lt;/span&gt;default&lt;span class="w"&gt; &lt;/span&gt;deny&lt;span class="w"&gt; &lt;/span&gt;incoming
sudo&lt;span class="w"&gt; &lt;/span&gt;ufw&lt;span class="w"&gt; &lt;/span&gt;default&lt;span class="w"&gt; &lt;/span&gt;allow&lt;span class="w"&gt; &lt;/span&gt;outgoing
sudo&lt;span class="w"&gt; &lt;/span&gt;ufw&lt;span class="w"&gt; &lt;/span&gt;allow&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;22&lt;/span&gt;/tcp
sudo&lt;span class="w"&gt; &lt;/span&gt;ufw&lt;span class="w"&gt; &lt;/span&gt;allow&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;/tcp
sudo&lt;span class="w"&gt; &lt;/span&gt;ufw&lt;span class="w"&gt; &lt;/span&gt;allow&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;443&lt;/span&gt;/tcp
sudo&lt;span class="w"&gt; &lt;/span&gt;ufw&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;enable&lt;/span&gt;

&lt;span class="c1"&gt;# 5. Install Fail2ban&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;fail2ban
sudo&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;fail2ban

&lt;span class="c1"&gt;# 6. Set up automatic security updates&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;unattended-upgrades
sudo&lt;span class="w"&gt; &lt;/span&gt;dpkg-reconfigure&lt;span class="w"&gt; &lt;/span&gt;-plow&lt;span class="w"&gt; &lt;/span&gt;unattended-upgrades
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Hetzner Cloud is the best cheap &lt;span class="caps"&gt;VPS&lt;/span&gt; for self-hosting in 2026. DigitalOcean is the best for beginners. Oracle Cloud Free Tier is the best for zero-cost experimentation. A cheap &lt;span class="caps"&gt;VPS&lt;/span&gt; extends your homelab into the cloud, solving public &lt;span class="caps"&gt;IP&lt;/span&gt;, port blocking, and offsite backup&amp;nbsp;challenges.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Sign up for Hetzner Cloud&lt;/strong&gt; (or your chosen&amp;nbsp;provider).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deploy a &lt;span class="caps"&gt;VPS&lt;/span&gt;&lt;/strong&gt; with Ubuntu 22.04/24.04 &lt;span class="caps"&gt;LTS&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Harden the server&lt;/strong&gt; using the checklist&amp;nbsp;above.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Install Docker&lt;/strong&gt; and deploy your first public&amp;nbsp;service.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Connect via WireGuard&lt;/strong&gt; to your home&amp;nbsp;homelab.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Hetzner Cloud:&lt;/strong&gt; Referral program (€10 credit for referrer and&amp;nbsp;referee).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DigitalOcean:&lt;/strong&gt; Referral program ($200 credit for 60&amp;nbsp;days).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vultr:&lt;/strong&gt; Referral program ($25&amp;nbsp;credit).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tailscale / WireGuard:&lt;/strong&gt; &lt;span class="caps"&gt;VPN&lt;/span&gt; tools for hybrid cloud&amp;nbsp;setup.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;intro&lt;/code&gt; → &lt;code&gt;vps-for-docker-containers-homelab&lt;/code&gt; — &amp;#8220;deploy Docker on your &lt;span class="caps"&gt;VPS&lt;/span&gt;&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;security&lt;/code&gt; → &lt;code&gt;homelab-security-monitoring&lt;/code&gt; — &amp;#8220;monitor your &lt;span class="caps"&gt;VPS&lt;/span&gt;&amp;nbsp;security&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;docker-compose-for-beginners&lt;/code&gt; — &amp;#8220;deploy your first&amp;nbsp;containers&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Which &lt;span class="caps"&gt;VPS&lt;/span&gt; provider do you use?&lt;/strong&gt; Share your cost and performance in the&amp;nbsp;comments.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subscribe&lt;/strong&gt; for &lt;span class="caps"&gt;VPS&lt;/span&gt; reviews, cloud security guides, and hybrid homelab&amp;nbsp;tips.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Infrastructure"/><category term="cheap vps"/><category term="self-hosting"/><category term="budget vps"/><category term="homelab"/><category term="cloud server"/><category term="hetzner"/><category term="digitalocean"/></entry><entry><title>DNS Filtering in the Homelab: A Complete Guide to Network-Wide Ad Blocking</title><link href="https://steadypub.com/2026/06/dns-filtering-homelab/" rel="alternate"/><published>2026-06-05T00:00:00+07:00</published><updated>2026-06-05T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/dns-filtering-homelab/</id><summary type="html">&lt;p&gt;Master &lt;span class="caps"&gt;DNS&lt;/span&gt; filtering for your homelab. Learn how Pi-hole, AdGuard Home, and Unblock work to block ads, malware, and trackers at the network level. Includes setup, blocklists, and advanced DoH/DoT&amp;nbsp;configuration.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~15 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelabbers who want to clean up their network&amp;nbsp;traffic&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;Filtering?&lt;/h2&gt;
&lt;h3&gt;What Exactly Is&amp;nbsp;It?&lt;/h3&gt;
&lt;p&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt; filtering is the practice of intercepting &lt;span class="caps"&gt;DNS&lt;/span&gt; queries — the requests your devices make to translate domain names&amp;nbsp;like &lt;code&gt;google.com&lt;/code&gt; into &lt;span class="caps"&gt;IP&lt;/span&gt; addresses — and blocking queries to known malicious, ad-serving, or tracking domains. Instead of returning the real &lt;span class="caps"&gt;IP&lt;/span&gt; address, the &lt;span class="caps"&gt;DNS&lt;/span&gt; filter&amp;nbsp;returns &lt;code&gt;0.0.0.0&lt;/code&gt; or &lt;code&gt;NXDOMAIN&lt;/code&gt;, preventing the connection&amp;nbsp;entirely.&lt;/p&gt;
&lt;p&gt;This is the most efficient way to block ads because it happens at the network level. Every device on your network — phones, smart TVs, IoT devices, laptops — benefits without installing software on each&amp;nbsp;device.&lt;/p&gt;
&lt;h3&gt;A Brief&amp;nbsp;History&lt;/h3&gt;
&lt;p&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt;-level ad blocking started with custom hosts files in the 1990s. In 2015, Pi-hole popularized the concept as a network-wide &lt;span class="caps"&gt;DNS&lt;/span&gt; sinkhole. By 2020, AdGuard Home emerged with a modern &lt;span class="caps"&gt;UI&lt;/span&gt; and native encrypted &lt;span class="caps"&gt;DNS&lt;/span&gt; support. Today, &lt;span class="caps"&gt;DNS&lt;/span&gt; filtering is a standard layer in every privacy-conscious&amp;nbsp;network.&lt;/p&gt;
&lt;h3&gt;Why It Matters&amp;nbsp;Today&lt;/h3&gt;
&lt;p&gt;Modern homes have 20–50 connected devices. Each one phones home to trackers, telemetry servers, and ad networks. &lt;span class="caps"&gt;DNS&lt;/span&gt; filtering:
- &lt;strong&gt;Blocks ads on smart TVs&lt;/strong&gt; where you cannot install ad blockers.
- &lt;strong&gt;Stops IoT devices&lt;/strong&gt; from leaking data to Chinese or &lt;span class="caps"&gt;US&lt;/span&gt; cloud servers.
- &lt;strong&gt;Reduces bandwidth usage&lt;/strong&gt; by preventing ad and tracking payloads from downloading.
- &lt;strong&gt;Improves page load times&lt;/strong&gt; by eliminating &lt;span class="caps"&gt;DNS&lt;/span&gt; lookups for blocked&amp;nbsp;domains.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why It&amp;nbsp;Matters&lt;/h2&gt;
&lt;h3&gt;Benefit 1: Network-Wide&amp;nbsp;Protection&lt;/h3&gt;
&lt;p&gt;One &lt;span class="caps"&gt;DNS&lt;/span&gt; filter protects every device. A Pi-hole or AdGuard Home instance on a Raspberry Pi covers your entire &lt;span class="caps"&gt;LAN&lt;/span&gt;. No per-device configuration, no browser extensions, no &lt;span class="caps"&gt;VPN&lt;/span&gt;&amp;nbsp;apps.&lt;/p&gt;
&lt;h3&gt;Benefit 2: Malware and Phishing&amp;nbsp;Blocking&lt;/h3&gt;
&lt;p&gt;Blocklists like Hagezi, StevenBlack, and MalwareDomainList include known malicious domains. If a family member clicks a phishing link, the &lt;span class="caps"&gt;DNS&lt;/span&gt; filter blocks the resolution before any connection is&amp;nbsp;made.&lt;/p&gt;
&lt;h3&gt;Benefit 3: Telemetry&amp;nbsp;Reduction&lt;/h3&gt;
&lt;p&gt;Windows, Android, smart TVs, and IoT devices constantly send telemetry. &lt;span class="caps"&gt;DNS&lt;/span&gt; filters block domains&amp;nbsp;like &lt;code&gt;telemetry.microsoft.com&lt;/code&gt;, &lt;code&gt;metrics.icloud.com&lt;/code&gt;,&amp;nbsp;and &lt;code&gt;crashlytics.com&lt;/code&gt;. Your devices still function; they just stop&amp;nbsp;reporting.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Device&lt;/th&gt;
&lt;th&gt;Common Telemetry Domains Blocked&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Windows&lt;/td&gt;
&lt;td&gt;&lt;code&gt;telemetry.microsoft.com&lt;/code&gt;, &lt;code&gt;vortex.data.microsoft.com&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Android&lt;/td&gt;
&lt;td&gt;&lt;code&gt;google-analytics.com&lt;/code&gt;, &lt;code&gt;crashlytics.com&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Smart &lt;span class="caps"&gt;TV&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;samsungads.com&lt;/code&gt;, &lt;code&gt;vizio.com&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IoT&lt;/td&gt;
&lt;td&gt;&lt;code&gt;tuya.com&lt;/code&gt;, &lt;code&gt;Xiaomi cloud domains&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Core&amp;nbsp;Principles&lt;/h2&gt;
&lt;hr&gt;
&lt;h2&gt;Principle 1: The &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;Sinkhole&lt;/h2&gt;
&lt;h3&gt;Explanation&lt;/h3&gt;
&lt;p&gt;A &lt;span class="caps"&gt;DNS&lt;/span&gt; sinkhole is a &lt;span class="caps"&gt;DNS&lt;/span&gt; server that returns a false &lt;span class="caps"&gt;IP&lt;/span&gt; for blocked domains. When your phone asks&amp;nbsp;for &lt;code&gt;ads.google.com&lt;/code&gt;, the sinkhole&amp;nbsp;returns &lt;code&gt;0.0.0.0&lt;/code&gt;. The phone tries to connect&amp;nbsp;to &lt;code&gt;0.0.0.0&lt;/code&gt;, fails instantly, and the ad never loads. This is faster than waiting for the real server to&amp;nbsp;timeout.&lt;/p&gt;
&lt;h3&gt;Example&lt;/h3&gt;
&lt;p&gt;Normal &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;flow:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Device → Router DNS (ISP) → Recursive resolver → Root → TLD → Authoritative → IP returned
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Filtered &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;flow:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;Device&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;→&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Pi&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;hole&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;AdGuard&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;local&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;→&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Checks&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;blocklist&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;→&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;If&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;blocked&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;returns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;                                         &lt;/span&gt;→&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;If&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;allowed&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;forwards&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;upstream&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;resolver&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Principle 2: Blocklists and&amp;nbsp;Whitelists&lt;/h2&gt;
&lt;h3&gt;Explanation&lt;/h3&gt;
&lt;p&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt; filters use blocklists (also called &amp;#8220;gravity lists&amp;#8221; or &amp;#8220;filter lists&amp;#8221;) — text files containing millions of domains to block. The quality of your filtering depends on the lists you choose. Too few lists = ads leak through. Too many aggressive lists = false positives (legitimate sites&amp;nbsp;break).&lt;/p&gt;
&lt;h3&gt;Example&lt;/h3&gt;
&lt;p&gt;Recommended blocklist combination for a balanced&amp;nbsp;homelab:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Blocklist&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;th&gt;Size&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;StevenBlack&lt;/td&gt;
&lt;td&gt;Ads, malware, tracking&lt;/td&gt;
&lt;td&gt;~150K domains&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;OISD&lt;/span&gt; Full&lt;/td&gt;
&lt;td&gt;Aggressive ad/tracker blocking&lt;/td&gt;
&lt;td&gt;~200K domains&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hagezi Multi &lt;span class="caps"&gt;NORMAL&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Balanced, low false positives&lt;/td&gt;
&lt;td&gt;~300K domains&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NoCoin Filter&lt;/td&gt;
&lt;td&gt;Cryptojacking scripts&lt;/td&gt;
&lt;td&gt;~15K domains&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MalwareDomainList&lt;/td&gt;
&lt;td&gt;Known malware domains&lt;/td&gt;
&lt;td&gt;~25K domains&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Whitelist essentials:&lt;/strong&gt;&amp;nbsp;- &lt;code&gt;google.com&lt;/code&gt; (sometimes blocked by overzealous lists)&amp;nbsp;- &lt;code&gt;github.com&lt;/code&gt; (required for updates)&amp;nbsp;- &lt;code&gt;cdn.jsdelivr.net&lt;/code&gt; (used by many legitimate sites)
- Your banking domains (add manually if&amp;nbsp;broken)&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Principle 3: Encrypted &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;(DoH/DoT)&lt;/h2&gt;
&lt;h3&gt;Explanation&lt;/h3&gt;
&lt;p&gt;Standard &lt;span class="caps"&gt;DNS&lt;/span&gt; is unencrypted. Your &lt;span class="caps"&gt;ISP&lt;/span&gt; can see every domain you visit. &lt;span class="caps"&gt;DNS&lt;/span&gt;-over-&lt;span class="caps"&gt;HTTPS&lt;/span&gt; (DoH) and &lt;span class="caps"&gt;DNS&lt;/span&gt;-over-&lt;span class="caps"&gt;TLS&lt;/span&gt; (DoT) encrypt the &lt;span class="caps"&gt;DNS&lt;/span&gt; query between your filter and the upstream resolver. This prevents:
- &lt;strong&gt;&lt;span class="caps"&gt;ISP&lt;/span&gt; snooping&lt;/strong&gt; (selling your browsing data)
- &lt;strong&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt; hijacking&lt;/strong&gt; (redirecting you to fake sites)
- &lt;strong&gt;Man-in-the-middle attacks&lt;/strong&gt; on &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;queries&lt;/p&gt;
&lt;h3&gt;Example&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt;-over-&lt;span class="caps"&gt;TLS&lt;/span&gt; (DoT)&lt;/strong&gt; uses port 853 and wraps &lt;span class="caps"&gt;DNS&lt;/span&gt; in a &lt;span class="caps"&gt;TLS&lt;/span&gt; tunnel. &lt;strong&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt;-over-&lt;span class="caps"&gt;HTTPS&lt;/span&gt; (DoH)&lt;/strong&gt; uses port 443 and sends &lt;span class="caps"&gt;DNS&lt;/span&gt; queries as &lt;span class="caps"&gt;HTTPS&lt;/span&gt; requests. DoH is harder to block because it looks like normal web&amp;nbsp;traffic.&lt;/p&gt;
&lt;p&gt;Upstream resolvers supporting DoH/DoT:&amp;nbsp;- &lt;code&gt;https://dns.cloudflare.com/dns-query&lt;/code&gt; (Cloudflare)&amp;nbsp;- &lt;code&gt;https://dns.quad9.net/dns-query&lt;/code&gt; (Quad9, malware filtering)&amp;nbsp;- &lt;code&gt;https://dns.adguard-dns.com/dns-query&lt;/code&gt; (AdGuard, ad filtering)&amp;nbsp;- &lt;code&gt;tls://dns.google&lt;/code&gt; (Google)&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Applying This to Your&amp;nbsp;Homelab&lt;/h2&gt;
&lt;h3&gt;Homelab Setup&amp;nbsp;Example&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;The Privacy-First&amp;nbsp;Stack&amp;#8221;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Services:
- &lt;strong&gt;AdGuard Home&lt;/strong&gt; (primary &lt;span class="caps"&gt;DNS&lt;/span&gt; sinkhole + DoH upstream)
- &lt;strong&gt;Unbound&lt;/strong&gt; (local recursive resolver for non-blocked queries)
- &lt;strong&gt;WireGuard&lt;/strong&gt; (remote &lt;span class="caps"&gt;DNS&lt;/span&gt; when away from&amp;nbsp;home)&lt;/p&gt;
&lt;p&gt;Configuration:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Router DHCP → DNS = AdGuard Home (192.168.1.2)
AdGuard Home → Upstream = 127.0.0.1:5335 (Unbound)
Unbound → Root servers (no third-party resolver)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This setup means:
- Blocked domains: stopped at AdGuard Home.
- Allowed domains: resolved recursively by Unbound (no Cloudflare, no Google, no &lt;span class="caps"&gt;ISP&lt;/span&gt;).
- Mobile devices: use WireGuard to tunnel &lt;span class="caps"&gt;DNS&lt;/span&gt; back to AdGuard&amp;nbsp;Home.&lt;/p&gt;
&lt;h3&gt;Practical&amp;nbsp;Steps&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Step 1: Install AdGuard Home via Docker&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;adguardhome&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;53&lt;/span&gt;:53/tcp&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;53&lt;/span&gt;:53/udp&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;:80/tcp&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;443&lt;/span&gt;:443/tcp&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3000&lt;/span&gt;:3000/tcp&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;853&lt;/span&gt;:853/tcp&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;/workdir:/opt/adguardhome/work&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;/confdir:/opt/adguardhome/conf&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--cap-add&lt;span class="o"&gt;=&lt;/span&gt;NET_ADMIN&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--restart&lt;span class="o"&gt;=&lt;/span&gt;always&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;adguard/adguardhome:latest

&lt;span class="c1"&gt;# Step 2: Configure upstream DNS in AdGuard&lt;/span&gt;
&lt;span class="c1"&gt;# Settings → DNS settings → Upstream DNS servers&lt;/span&gt;
&lt;span class="c1"&gt;# Add: tls://dns.quad9.net&lt;/span&gt;
&lt;span class="c1"&gt;# Add: https://dns.cloudflare.com/dns-query&lt;/span&gt;

&lt;span class="c1"&gt;# Step 3: Install Unbound as a local recursive resolver&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;unbound
&lt;span class="c1"&gt;# Configure /etc/unbound/unbound.conf to listen on 127.0.0.1:5335&lt;/span&gt;

&lt;span class="c1"&gt;# Step 4: Set your router&amp;#39;s DNS to the AdGuard Home IP&lt;/span&gt;
&lt;span class="c1"&gt;# Or configure DHCP to push the AdGuard IP as DNS&lt;/span&gt;

&lt;span class="c1"&gt;# Step 5: Test&lt;/span&gt;
nslookup&lt;span class="w"&gt; &lt;/span&gt;doubleclick.net&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.1.2
&lt;span class="c1"&gt;# Should return 0.0.0.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Common Mistakes to&amp;nbsp;Avoid&lt;/h2&gt;
&lt;h3&gt;Mistake 1: Using Only Default&amp;nbsp;Blocklists&lt;/h3&gt;
&lt;p&gt;The default blocklists in Pi-hole and AdGuard Home are good but incomplete. Add &lt;span class="caps"&gt;OISD&lt;/span&gt;, Hagezi, and NoCoin for comprehensive coverage. Update lists weekly (automated in both&amp;nbsp;tools).&lt;/p&gt;
&lt;h3&gt;Mistake 2: Blocking Too&amp;nbsp;Aggressively&lt;/h3&gt;
&lt;p&gt;Aggressive lists&amp;nbsp;like &lt;code&gt;1Hosts (Xtra)&lt;/code&gt; break Netflix, YouTube, and banking sites. Start&amp;nbsp;with &lt;code&gt;NORMAL&lt;/code&gt; or &lt;code&gt;PRO&lt;/code&gt; lists. Only&amp;nbsp;add &lt;code&gt;Xtra&lt;/code&gt; if you are willing to maintain a large&amp;nbsp;whitelist.&lt;/p&gt;
&lt;h3&gt;Mistake 3: Not Encrypting Upstream &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;If your upstream &lt;span class="caps"&gt;DNS&lt;/span&gt; is unencrypted&amp;nbsp;(&lt;code&gt;8.8.8.8&lt;/code&gt;, &lt;code&gt;1.1.1.1&lt;/code&gt;), your &lt;span class="caps"&gt;ISP&lt;/span&gt; can still see your queries via &lt;span class="caps"&gt;SNI&lt;/span&gt; or traffic analysis. Always enable DoH or DoT. If you use Unbound, the queries are encrypted to root servers via &lt;span class="caps"&gt;DNSSEC&lt;/span&gt; (not transport encryption, but authenticity&amp;nbsp;verified).&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt; filtering is the first layer of defense in a secure homelab. It blocks ads, malware, and telemetry for every device on your network — no client-side software required. AdGuard Home or Pi-hole paired with Unbound gives you a fast, private, and self-sufficient &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;infrastructure.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Deploy AdGuard Home&lt;/strong&gt; or Pi-hole in&amp;nbsp;Docker.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Add 3–5 blocklists&lt;/strong&gt; (StevenBlack, &lt;span class="caps"&gt;OISD&lt;/span&gt;,&amp;nbsp;Hagezi).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enable DoH/DoT&lt;/strong&gt; to encrypt upstream&amp;nbsp;queries.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Install Unbound&lt;/strong&gt; if you want recursive resolution without third&amp;nbsp;parties.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Monitor query logs&lt;/strong&gt; for a week to identify false&amp;nbsp;positives.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Raspberry Pi:&lt;/strong&gt; Pi 4 or Pi 5 for running&amp;nbsp;Pi-hole/AdGuard.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mini PCs:&lt;/strong&gt; Intel N100 for 24/7 &lt;span class="caps"&gt;DNS&lt;/span&gt; +&amp;nbsp;Docker.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Networking:&lt;/strong&gt; &lt;span class="caps"&gt;TP&lt;/span&gt;-Link Omada or UniFi for managed &lt;span class="caps"&gt;DNS&lt;/span&gt; &lt;span class="caps"&gt;DHCP&lt;/span&gt;&amp;nbsp;options.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Books:&lt;/strong&gt; &amp;#8220;&lt;span class="caps"&gt;DNS&lt;/span&gt; Security&amp;#8221; by Allan&amp;nbsp;Liska.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;what-is&lt;/code&gt; → &lt;code&gt;pihole-vs-adguard-home&lt;/code&gt; — &amp;#8220;compare the two leading &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;filters&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;principle-3&lt;/code&gt; → &lt;code&gt;adguard-home-docker&lt;/code&gt; — &amp;#8220;step-by-step AdGuard Home&amp;nbsp;setup&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;applying-it&lt;/code&gt; → &lt;code&gt;pihole-setup-guide&lt;/code&gt; — &amp;#8220;Pi-hole installation&amp;nbsp;guide&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;homelab-networking-basics&lt;/code&gt; — &amp;#8220;fundamentals of homelab &lt;span class="caps"&gt;DNS&lt;/span&gt; and &lt;span class="caps"&gt;DHCP&lt;/span&gt;&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;What blocklists run your network?&lt;/strong&gt; Share your &lt;span class="caps"&gt;DNS&lt;/span&gt; filter setup in the&amp;nbsp;comments.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subscribe&lt;/strong&gt; for &lt;span class="caps"&gt;DNS&lt;/span&gt; privacy guides, blocklist reviews, and homelab security&amp;nbsp;tips.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Networking"/><category term="dns filtering"/><category term="homelab"/><category term="ad blocking"/><category term="pi-hole"/><category term="adguard home"/><category term="unbound"/><category term="dns over https"/></entry><entry><title>Docker Compose vs Podman: Which One Wins for Your Homelab?</title><link href="https://steadypub.com/2026/06/docker-compose-vs-podman/" rel="alternate"/><published>2026-06-05T00:00:00+07:00</published><updated>2026-06-05T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/docker-compose-vs-podman/</id><summary type="html">&lt;p&gt;A head-to-head comparison of Docker Compose and Podman for homelab self-hosting. Learn which container engine fits your workflow, security model, and systemd&amp;nbsp;integration.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~11 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelabbers choosing a container engine for self-hosted&amp;nbsp;apps&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The Docker Compose vs Podman&amp;nbsp;Dilemma&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Docker Compose is the de facto standard for multi-container apps. It uses a&amp;nbsp;single &lt;code&gt;docker-compose.yml&lt;/code&gt; file to define networks, volumes, and services. Podman is a daemonless, rootless container engine that is compatible with Docker &lt;span class="caps"&gt;CLI&lt;/span&gt; but does not require a background service. It is the default on Red Hat Enterprise Linux and Fedora, and it is gaining traction in security-focused&amp;nbsp;homelabs.&lt;/p&gt;
&lt;h3&gt;Key Differences at a&amp;nbsp;Glance&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Docker Compose&lt;/th&gt;
&lt;th&gt;Podman&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Daemon&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;dockerd&lt;/code&gt; runs as root&lt;/td&gt;
&lt;td&gt;Daemonless; containers run as user&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rootless&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Possible but complex&lt;/td&gt;
&lt;td&gt;Native and default&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Compose&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;docker-compose&lt;/code&gt; (Python)&amp;nbsp;or &lt;code&gt;docker compose&lt;/code&gt; (Go plugin)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;podman-compose&lt;/code&gt; (Python)&amp;nbsp;or &lt;code&gt;podman-compose&lt;/code&gt; (native)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Pods&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Not native (uses &amp;#8220;services&amp;#8221;)&lt;/td&gt;
&lt;td&gt;Native pod concept (like Kubernetes)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Systemd&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual setup&lt;/td&gt;
&lt;td&gt;Native &lt;code&gt;podman generate systemd&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Kubernetes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Can generate K8s &lt;span class="caps"&gt;YAML&lt;/span&gt; from pods&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Image format&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;OCI&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;OCI&lt;/span&gt; (fully compatible)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Learning curve&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Gentle&lt;/td&gt;
&lt;td&gt;Moderate (different networking model)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Community&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Massive&lt;/td&gt;
&lt;td&gt;Growing fast; Red Hat backed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Option A: Docker&amp;nbsp;Compose&lt;/h2&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ecosystem dominance:&lt;/strong&gt; Every self-hosting guide, GitHub repo, and blog post assumes Docker Compose.&amp;nbsp;Copy-paste &lt;code&gt;docker-compose.yml&lt;/code&gt; and it&amp;nbsp;works.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Docker Hub:&lt;/strong&gt; Largest image registry with one-click&amp;nbsp;pulls.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Swarm mode:&lt;/strong&gt; Optional built-in clustering for multi-node&amp;nbsp;setups.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rich tooling:&lt;/strong&gt; Portainer, Watchtower, and Diun are built around&amp;nbsp;Docker.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Volume management:&lt;/strong&gt; Named volumes and bind mounts are well-documented and&amp;nbsp;stable.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Networking:&lt;/strong&gt; &lt;code&gt;docker network create&lt;/code&gt; and service discovery are&amp;nbsp;automatic.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Root&amp;nbsp;daemon:&lt;/strong&gt; &lt;code&gt;dockerd&lt;/code&gt; runs as root. A container escape can compromise the&amp;nbsp;host.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Docker Desktop licensing:&lt;/strong&gt; On macOS/Windows, commercial use requires a paid license (Linux is&amp;nbsp;free).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Socket security:&lt;/strong&gt; The Docker socket&amp;nbsp;(&lt;code&gt;/var/run/docker.sock&lt;/code&gt;) is a well-known attack&amp;nbsp;vector.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Image bloat:&lt;/strong&gt; Official images often include more than needed; scanning is&amp;nbsp;essential.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Users who want maximum compatibility with existing guides and&amp;nbsp;tools.&lt;/li&gt;
&lt;li&gt;Homelabs with many apps managed via Portainer or&amp;nbsp;Dockge.&lt;/li&gt;
&lt;li&gt;Teams who need to&amp;nbsp;share &lt;code&gt;docker-compose.yml&lt;/code&gt; files without&amp;nbsp;explanation.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Free&lt;/strong&gt; on Linux (Docker&amp;nbsp;Engine).&lt;/li&gt;
&lt;li&gt;Docker Desktop: free for personal use; paid for companies&amp;nbsp;($5/user/month).&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Option B:&amp;nbsp;Podman&lt;/h2&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Rootless by default:&lt;/strong&gt; Containers run as your user. Even if a container is compromised, the attacker has your user privileges, not&amp;nbsp;root.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Daemonless:&lt;/strong&gt; No background service. Containers are child processes of your shell. If you log out, containers stop (unless you&amp;nbsp;use &lt;code&gt;podman generate systemd&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pod concept:&lt;/strong&gt; Group containers into pods that share a network namespace. This mirrors Kubernetes and makes migration&amp;nbsp;easier.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Systemd&amp;nbsp;integration:&lt;/strong&gt; &lt;code&gt;podman generate systemd --new&lt;/code&gt; creates unit files that auto-start on&amp;nbsp;boot.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Docker &lt;span class="caps"&gt;CLI&lt;/span&gt;&amp;nbsp;compatible:&lt;/strong&gt; &lt;code&gt;alias docker=podman&lt;/code&gt; works for 90% of&amp;nbsp;commands.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No socket required:&lt;/strong&gt; Podman does not expose a Unix socket, eliminating a major attack&amp;nbsp;vector.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Compose&amp;nbsp;support:&lt;/strong&gt; &lt;code&gt;podman-compose&lt;/code&gt; is a Python wrapper around Docker Compose. It works for most files but has edge cases&amp;nbsp;(e.g., &lt;code&gt;depends_on&lt;/code&gt; health checks, build&amp;nbsp;contexts).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Networking model:&lt;/strong&gt; Rootless containers&amp;nbsp;use &lt;code&gt;slirp4netns&lt;/code&gt; or &lt;code&gt;pasta&lt;/code&gt; for networking. Port forwarding and &lt;span class="caps"&gt;DNS&lt;/span&gt; behave differently than&amp;nbsp;Docker.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Smaller community:&lt;/strong&gt; Fewer homelab guides target Podman. You may need to adapt Docker&amp;nbsp;tutorials.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Volume permissions:&lt;/strong&gt; Rootless &lt;span class="caps"&gt;UID&lt;/span&gt; mapping can cause permission issues with bind mounts (e.g., Plex media&amp;nbsp;folders).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Security-conscious users who want to minimize root&amp;nbsp;access.&lt;/li&gt;
&lt;li&gt;Fedora, &lt;span class="caps"&gt;RHEL&lt;/span&gt;, and CentOS Stream users (Podman is&amp;nbsp;pre-installed).&lt;/li&gt;
&lt;li&gt;Users who want to experiment with Kubernetes pods&amp;nbsp;locally.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Free&lt;/strong&gt; (Apache 2.0&amp;nbsp;license).&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Option C: The Podman + Docker Compose&amp;nbsp;Path&lt;/h2&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Podman can run Docker Compose files directly&amp;nbsp;with &lt;code&gt;podman compose&lt;/code&gt; (via&amp;nbsp;the &lt;code&gt;podman-compose&lt;/code&gt; plugin or the Docker Compose &lt;span class="caps"&gt;CLI&lt;/span&gt;&amp;nbsp;plugin).&lt;/li&gt;
&lt;li&gt;This gives you the security of Podman with the ecosystem of Docker&amp;nbsp;Compose.&lt;/li&gt;
&lt;li&gt;You can migrate incrementally: keep&amp;nbsp;your &lt;code&gt;docker-compose.yml&lt;/code&gt; files and switch the&amp;nbsp;engine.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;podman-compose&lt;/code&gt; is not 100% compatible. Complex&amp;nbsp;builds, &lt;code&gt;network_mode: host&lt;/code&gt;, and some health checks may&amp;nbsp;fail.&lt;/li&gt;
&lt;li&gt;You need to&amp;nbsp;install &lt;code&gt;podman-docker&lt;/code&gt; package for full &lt;span class="caps"&gt;CLI&lt;/span&gt;&amp;nbsp;compatibility.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Users who want to test Podman without rewriting their entire&amp;nbsp;stack.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Free.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Comparison&amp;nbsp;Matrix&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;Docker Compose&lt;/th&gt;
&lt;th&gt;Podman&lt;/th&gt;
&lt;th&gt;Winner&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Copy-paste from Reddit&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌ May need tweaks&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Docker Compose&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security / rootless&lt;/td&gt;
&lt;td&gt;❌ Complex&lt;/td&gt;
&lt;td&gt;✅ Native&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Podman&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Systemd auto-start&lt;/td&gt;
&lt;td&gt;✅ Manual&lt;/td&gt;
&lt;td&gt;✅ Native&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Podman&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kubernetes learning&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅ Pods + K8s &lt;span class="caps"&gt;YAML&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Podman&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Portainer / Dockge&lt;/td&gt;
&lt;td&gt;✅ Native&lt;/td&gt;
&lt;td&gt;❌ Limited&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Docker Compose&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Windows / macOS&lt;/td&gt;
&lt;td&gt;✅ Docker Desktop&lt;/td&gt;
&lt;td&gt;❌ Linux only (mostly)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Docker Compose&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Image building&lt;/td&gt;
&lt;td&gt;✅ &lt;code&gt;docker build&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅ &lt;code&gt;podman build&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Tie&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Which Should You&amp;nbsp;Choose?&lt;/h2&gt;
&lt;h3&gt;Scenario 1: &amp;#8220;I just want to run Immich, Jellyfin, and&amp;nbsp;Nextcloud.&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose Docker Compose.&lt;/strong&gt;&amp;nbsp;The &lt;code&gt;docker-compose.yml&lt;/code&gt; files from the official docs will work without modification. Portainer gives you a &lt;span class="caps"&gt;GUI&lt;/span&gt;, and Watchtower keeps images&amp;nbsp;updated.&lt;/p&gt;
&lt;h3&gt;Scenario 2: &amp;#8220;I run Fedora on my home server and want maximum&amp;nbsp;security.&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose Podman.&lt;/strong&gt;&amp;nbsp;Use &lt;code&gt;podman-compose&lt;/code&gt; for your existing stacks. Generate systemd units for auto-start. Enjoy rootless containers and no&amp;nbsp;daemon.&lt;/p&gt;
&lt;h3&gt;Scenario 3: &amp;#8220;I plan to move to Kubernetes&amp;nbsp;eventually.&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose Podman.&lt;/strong&gt; Its pod concept is a stepping stone to Kubernetes. You can export pods to &lt;span class="caps"&gt;YAML&lt;/span&gt; and import them into a K3s cluster&amp;nbsp;later.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Migration Path: Docker to&amp;nbsp;Podman&lt;/h2&gt;
&lt;h3&gt;Step 1: Install&amp;nbsp;Podman&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Debian/Ubuntu&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;podman&lt;span class="w"&gt; &lt;/span&gt;podman-compose&lt;span class="w"&gt; &lt;/span&gt;podman-docker

&lt;span class="c1"&gt;# Fedora&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;dnf&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;podman&lt;span class="w"&gt; &lt;/span&gt;podman-compose
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Step 2: Test Your Compose&amp;nbsp;File&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# In your app directory&lt;/span&gt;
podman-compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;span class="c1"&gt;# Check logs&lt;/span&gt;
podman-compose&lt;span class="w"&gt; &lt;/span&gt;logs&lt;span class="w"&gt; &lt;/span&gt;-f
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Step 3: Fix Common&amp;nbsp;Issues&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Port binding:&lt;/strong&gt; Rootless Podman cannot bind ports &amp;lt; 1024.&amp;nbsp;Use &lt;code&gt;8080:80&lt;/code&gt; instead&amp;nbsp;of &lt;code&gt;80:80&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt;:&lt;/strong&gt;&amp;nbsp;Use &lt;code&gt;podman network create&lt;/code&gt; and attach containers to it. Rootless &lt;span class="caps"&gt;DNS&lt;/span&gt; is less automatic than&amp;nbsp;Docker.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Volumes:&lt;/strong&gt; Ensure the host directory is owned by your user.&amp;nbsp;Use &lt;code&gt;:Z&lt;/code&gt; for SELinux labels:
  &amp;#8220;`yaml
  volumes:&lt;ul&gt;
&lt;li&gt;./data:/data:Z&amp;nbsp;&amp;#8220;`&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Step 4: Generate Systemd&amp;nbsp;Units&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Create a systemd unit for auto-start&lt;/span&gt;
podman&lt;span class="w"&gt; &lt;/span&gt;generate&lt;span class="w"&gt; &lt;/span&gt;systemd&lt;span class="w"&gt; &lt;/span&gt;--new&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;mycontainer&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;~/.config/systemd/user/mycontainer.service
systemctl&lt;span class="w"&gt; &lt;/span&gt;--user&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mycontainer.service
systemctl&lt;span class="w"&gt; &lt;/span&gt;--user&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;mycontainer.service
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;The&amp;nbsp;Verdict&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Verdict&lt;/th&gt;
&lt;th&gt;Recommendation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for beginners&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Docker Compose (guides, GUIs, community)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for security&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Podman (rootless, daemonless, no socket)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for Red Hat ecosystems&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Podman (native, supported, pre-installed)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best long-term flexibility&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Podman (pods, K8s export, systemd)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Docker Compose is the easy button. It works everywhere, and everyone writes guides for it. Podman is the secure, future-proof option. It is harder to learn but pays dividends in security and systemd integration. If you are on Ubuntu/Debian and want to get apps running today, use Docker Compose. If you are on Fedora or &lt;span class="caps"&gt;RHEL&lt;/span&gt; and care about rootless security, use&amp;nbsp;Podman.&lt;/p&gt;
&lt;h3&gt;Ready to Get&amp;nbsp;Started?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;[internal_link] New to containers? Read our &lt;a href="https://steadypub.com/2026/06/docker-compose-for-beginners/"&gt;Docker Compose for beginners&lt;/a&gt;&amp;nbsp;guide.&lt;/li&gt;
&lt;li&gt;[internal_link] Ready to deploy apps? See our &lt;a href="https://steadypub.com/2026/06/portainer-setup-guide/"&gt;Portainer setup guide&lt;/a&gt; for a web &lt;span class="caps"&gt;UI&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;[internal_link] Need a media server? Check our &lt;a href="https://steadypub.com/2026/06/self-hosted-media-server-setup/"&gt;Jellyfin setup&lt;/a&gt; with Docker&amp;nbsp;Compose.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Docker / Podman books&lt;/strong&gt;: &amp;#8220;Docker Deep Dive&amp;#8221; and &amp;#8220;Podman in&amp;nbsp;Action&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Linux distros&lt;/strong&gt;: Fedora Server or Ubuntu Server affiliate&amp;nbsp;links&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Courses&lt;/strong&gt;: Linux Foundation or A Cloud Guru container&amp;nbsp;courses&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;intro-dilemma&lt;/code&gt; → &lt;code&gt;docker-compose-for-beginners&lt;/code&gt; — &amp;#8220;our comprehensive Docker Compose setup&amp;nbsp;guide&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;migration-path&lt;/code&gt; → &lt;code&gt;portainer-setup-guide&lt;/code&gt; — &amp;#8220;manage containers with a &lt;span class="caps"&gt;GUI&lt;/span&gt;&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;self-hosted-media-server-setup&lt;/code&gt; — &amp;#8220;deploy Jellyfin with Docker&amp;nbsp;Compose&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] Are you Team Docker or Team Podman? Vote below and tell us&amp;nbsp;why!&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for container security tips, compose file templates, and app deployment&amp;nbsp;guides.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Comparisons"/><category term="docker compose"/><category term="podman"/><category term="homelab"/><category term="containers"/><category term="self-hosted"/><category term="comparison"/></entry><entry><title>Grafana Docker Compose Setup: Beautiful Dashboards for Your Homelab</title><link href="https://steadypub.com/2026/06/grafana-docker-compose/" rel="alternate"/><published>2026-06-05T00:00:00+07:00</published><updated>2026-06-05T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/grafana-docker-compose/</id><summary type="html">&lt;p&gt;Deploy Grafana with Docker Compose for homelab dashboards. Connect to Prometheus, InfluxDB, Loki, and other data sources. Import community dashboards and create custom&amp;nbsp;panels.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~12 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelabbers wanting visual monitoring&amp;nbsp;dashboards&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is&amp;nbsp;Grafana?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Grafana is an open-source analytics and visualization platform. It connects to dozens of data sources — Prometheus, InfluxDB, MySQL, Loki, Elasticsearch — and lets you create beautiful, interactive dashboards. It is the industry standard for monitoring visualization and the perfect complement to Prometheus in your&amp;nbsp;homelab.&lt;/p&gt;
&lt;h3&gt;Key&amp;nbsp;Benefits&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Benefit&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data source agnostic&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Prometheus, InfluxDB, MySQL, PostgreSQL, Loki, and 50+ more&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Community dashboards&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Thousands of pre-built dashboards on grafana.com&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Alerting&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Built-in alert rules with email, Slack, Telegram, and webhook support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Variables&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Dynamic dashboards that adapt to different hosts or services&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Annotations&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Mark events (deployments, outages) on graphs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Plugins&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Extend with panel types, data sources, and apps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Multi-tenant&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Organizations and role-based access control&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;h3&gt;Hardware&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Any Docker host (mini &lt;span class="caps"&gt;PC&lt;/span&gt;, server, or &lt;span class="caps"&gt;VM&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;512MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; for Grafana (&lt;span class="caps"&gt;1GB&lt;/span&gt; recommended with many&amp;nbsp;dashboards)&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;1GB&lt;/span&gt; storage for configuration and SQLite&amp;nbsp;database&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Software&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Docker Engine 24.x+ and Docker Compose&amp;nbsp;v2+&lt;/li&gt;
&lt;li&gt;An existing data source (Prometheus, InfluxDB, or&amp;nbsp;similar)&lt;/li&gt;
&lt;li&gt;Modern web&amp;nbsp;browser&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Knowledge&amp;nbsp;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Docker Compose&amp;nbsp;basics&lt;/li&gt;
&lt;li&gt;Understanding of your data source&amp;#8217;s query language (PromQL, InfluxQL, or &lt;span class="caps"&gt;SQL&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;Basic &lt;span class="caps"&gt;JSON&lt;/span&gt;/&lt;span class="caps"&gt;YAML&lt;/span&gt;&amp;nbsp;editing&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Deploy Grafana with Docker&amp;nbsp;Compose&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Run Grafana with persistent storage and proper environment&amp;nbsp;configuration.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Create the project&amp;nbsp;directory:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;~/docker/grafana&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/docker/grafana
mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;data&lt;span class="w"&gt; &lt;/span&gt;provisioning/datasources&lt;span class="w"&gt; &lt;/span&gt;provisioning/dashboards
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Create &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;grafana&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;grafana/grafana:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;grafana&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3000:3000&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;GF_SECURITY_ADMIN_USER=admin&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;GF_SECURITY_ADMIN_PASSWORD=Change...3!&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;GF_USERS_ALLOW_SIGN_UP=false&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;GF_SERVER_ROOT_URL=http://grafana.local&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;GF_INSTALL_PLUGINS=grafana-clock-panel,grafana-simple-json-datasource&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./data:/var/lib/grafana&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./provisioning/datasources:/etc/grafana/provisioning/datasources:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./provisioning/dashboards:/etc/grafana/provisioning/dashboards:ro&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;monitoring&lt;/span&gt;

&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;monitoring&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;bridge&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Create auto-provisioned data source&amp;nbsp;configuration:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;cat&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&amp;lt; &amp;#39;EOF&amp;#39; &amp;gt; provisioning/datasources/prometheus.yml&lt;/span&gt;
&lt;span class="s"&gt;apiVersion: 1&lt;/span&gt;
&lt;span class="s"&gt;datasources:&lt;/span&gt;
&lt;span class="s"&gt;  - name: Prometheus&lt;/span&gt;
&lt;span class="s"&gt;    type: prometheus&lt;/span&gt;
&lt;span class="s"&gt;    access: proxy&lt;/span&gt;
&lt;span class="s"&gt;    url: http://prometheus:9090&lt;/span&gt;
&lt;span class="s"&gt;    isDefault: true&lt;/span&gt;
&lt;span class="s"&gt;    editable: false&lt;/span&gt;
&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Create dashboard provisioning&amp;nbsp;configuration:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;cat&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&amp;lt; &amp;#39;EOF&amp;#39; &amp;gt; provisioning/dashboards/dashboards.yml&lt;/span&gt;
&lt;span class="s"&gt;apiVersion: 1&lt;/span&gt;
&lt;span class="s"&gt;providers:&lt;/span&gt;
&lt;span class="s"&gt;  - name: &amp;#39;default&amp;#39;&lt;/span&gt;
&lt;span class="s"&gt;    orgId: 1&lt;/span&gt;
&lt;span class="s"&gt;    folder: &amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="s"&gt;    type: file&lt;/span&gt;
&lt;span class="s"&gt;    disableDeletion: false&lt;/span&gt;
&lt;span class="s"&gt;    editable: true&lt;/span&gt;
&lt;span class="s"&gt;    options:&lt;/span&gt;
&lt;span class="s"&gt;      path: /var/lib/grafana/dashboards&lt;/span&gt;
&lt;span class="s"&gt;EOF&lt;/span&gt;

mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;data/dashboards
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Deploy:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Access&amp;nbsp;Grafana:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Open &lt;code&gt;http://your-server-ip:3000&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Login: &lt;code&gt;admin&lt;/code&gt; / &lt;code&gt;Change...3!&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Step 2: Import Community&amp;nbsp;Dashboards&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Get instant visualizations without building dashboards from&amp;nbsp;scratch.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Go to Dashboards →&amp;nbsp;Import&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enter a dashboard &lt;span class="caps"&gt;ID&lt;/span&gt; from&amp;nbsp;grafana.com:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dashboard&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;ID&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;th&gt;What It Shows&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Node Exporter Full&lt;/td&gt;
&lt;td&gt;1860&lt;/td&gt;
&lt;td&gt;Prometheus&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;, memory, disk, network, temperature&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Docker Monitoring&lt;/td&gt;
&lt;td&gt;893&lt;/td&gt;
&lt;td&gt;Prometheus&lt;/td&gt;
&lt;td&gt;Container stats, resource usage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;10347&lt;/td&gt;
&lt;td&gt;Prometheus&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;VM&lt;/span&gt;/&lt;span class="caps"&gt;LXC&lt;/span&gt; status, storage, node health&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pi-hole&lt;/td&gt;
&lt;td&gt;10176&lt;/td&gt;
&lt;td&gt;Prometheus&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt; queries, blocked ads, client stats&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AdGuard Home&lt;/td&gt;
&lt;td&gt;14284&lt;/td&gt;
&lt;td&gt;Prometheus&lt;/td&gt;
&lt;td&gt;Query log, filtering stats, clients&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Homelab 3D&lt;/td&gt;
&lt;td&gt;15287&lt;/td&gt;
&lt;td&gt;Prometheus&lt;/td&gt;
&lt;td&gt;3D visual overview of your lab&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Select your Prometheus data source&lt;/strong&gt; and click&amp;nbsp;Import&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The dashboard appears immediately&lt;/strong&gt; with live&amp;nbsp;data&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Step 3: Create a Custom&amp;nbsp;Dashboard&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Build a homelab overview dashboard tailored to your&amp;nbsp;services.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Go to Dashboards → New → New&amp;nbsp;Dashboard&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Add a&amp;nbsp;panel:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Title: &amp;#8220;&lt;span class="caps"&gt;CPU&lt;/span&gt;&amp;nbsp;Usage&amp;#8221;&lt;/li&gt;
&lt;li&gt;Query: &lt;code&gt;100 - (avg by (instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Visualization:&amp;nbsp;Gauge&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Thresholds: 0–60 green, 60–80 yellow, 80–100&amp;nbsp;red&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Add another&amp;nbsp;panel:&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Title: &amp;#8220;Memory&amp;nbsp;Usage&amp;#8221;&lt;/li&gt;
&lt;li&gt;Query: &lt;code&gt;(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Visualization: Time&amp;nbsp;series&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Add a third&amp;nbsp;panel:&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Title: &amp;#8220;Disk Free&amp;nbsp;Space&amp;#8221;&lt;/li&gt;
&lt;li&gt;Query: &lt;code&gt;node_filesystem_avail_bytes / node_filesystem_size_bytes * 100&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Legend: &lt;code&gt;{{mountpoint}}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Visualization: Bar&amp;nbsp;gauge&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Save the dashboard&lt;/strong&gt; as &amp;#8220;Homelab&amp;nbsp;Overview&amp;#8221;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Step 4: Configure&amp;nbsp;Alerting&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Set up Grafana alerts for critical&amp;nbsp;conditions.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Go to Alerting → Contact&amp;nbsp;points&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Create a contact&amp;nbsp;point:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Name: &amp;#8220;Email&amp;nbsp;Alerts&amp;#8221;&lt;/li&gt;
&lt;li&gt;Type:&amp;nbsp;Email&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Addresses: &lt;code&gt;your-email@example.com&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Go to Alerting → Alert rules → New alert&amp;nbsp;rule&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Create a&amp;nbsp;rule:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Name: &amp;#8220;High &lt;span class="caps"&gt;CPU&lt;/span&gt;&amp;nbsp;Usage&amp;#8221;&lt;/li&gt;
&lt;li&gt;Query: &lt;code&gt;100 - (avg by (instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Condition: &lt;span class="caps"&gt;IS&lt;/span&gt; &lt;span class="caps"&gt;ABOVE&lt;/span&gt;&amp;nbsp;80&lt;/li&gt;
&lt;li&gt;Evaluate every:&amp;nbsp;1m&lt;/li&gt;
&lt;li&gt;For:&amp;nbsp;5m&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Contact point: &amp;#8220;Email&amp;nbsp;Alerts&amp;#8221;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Test the alert&lt;/strong&gt; using the &amp;#8220;Test&amp;#8221;&amp;nbsp;button&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Use Environment Variables for&amp;nbsp;Secrets&lt;/h3&gt;
&lt;p&gt;Don&amp;#8217;t hardcode passwords&amp;nbsp;in &lt;code&gt;docker-compose.yml&lt;/code&gt;.&amp;nbsp;Use &lt;code&gt;.env&lt;/code&gt; files:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# .env&lt;/span&gt;
&lt;span class="nv"&gt;GF_SECURITY_ADMIN_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;supersecret
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# docker-compose.yml&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;env_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;.env&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 2: Connect Grafana to Multiple Data&amp;nbsp;Sources&lt;/h3&gt;
&lt;p&gt;Add InfluxDB, Loki, MySQL, or PostgreSQL as additional data sources. You can mix data from multiple sources in a single&amp;nbsp;dashboard.&lt;/p&gt;
&lt;h3&gt;Tip 3: Set Up a Reverse&amp;nbsp;Proxy&lt;/h3&gt;
&lt;p&gt;Expose Grafana through &lt;span class="caps"&gt;NGINX&lt;/span&gt; Proxy Manager or Traefik for &lt;span class="caps"&gt;HTTPS&lt;/span&gt; and custom&amp;nbsp;domains:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;https://grafana.yourdomain.com → http://grafana:3000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 4: Use Dashboard&amp;nbsp;Folders&lt;/h3&gt;
&lt;p&gt;Organize dashboards by category:
- Infrastructure (Node Exporter, Proxmox)
- Applications (Nextcloud, Jellyfin, Pi-hole)
- Security (Wazuh, CrowdSec)
- Networking (UniFi,&amp;nbsp;Omada)&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Troubleshooting Common&amp;nbsp;Issues&lt;/h2&gt;
&lt;h3&gt;Problem 1: &amp;#8220;Dashboard Shows No&amp;nbsp;Data&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Cause:&lt;/strong&gt; Data source not configured, or queries are&amp;nbsp;wrong.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;
- Verify data source at Configuration → Data sources
- Test the query in the Explore tab
- Check Prometheus targets&amp;nbsp;at &lt;code&gt;http://prometheus:9090/targets&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;Problem 2: &amp;#8220;Permission Denied on Data&amp;nbsp;Directory&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Cause:&lt;/strong&gt; Grafana container runs as &lt;span class="caps"&gt;UID&lt;/span&gt; 472 but host directory is owned by&amp;nbsp;root.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;chown&lt;span class="w"&gt; &lt;/span&gt;-R&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;472&lt;/span&gt;:472&lt;span class="w"&gt; &lt;/span&gt;~/docker/grafana/data
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Problem 3: &amp;#8220;Forgot Admin&amp;nbsp;Password&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;grafana&lt;span class="w"&gt; &lt;/span&gt;grafana-cli&lt;span class="w"&gt; &lt;/span&gt;admin&lt;span class="w"&gt; &lt;/span&gt;reset-admin-password&lt;span class="w"&gt; &lt;/span&gt;newpassword
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Grafana turns raw metrics into actionable insights. With Docker Compose, you can deploy it in minutes, import community dashboards, and build custom views of your homelab. Combined with Prometheus, it gives you professional-grade&amp;nbsp;observability.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Add &lt;a href="grafana-loki-logs"&gt;Loki&lt;/a&gt; for log aggregation and error&amp;nbsp;tracking&lt;/li&gt;
&lt;li&gt;Compare with &lt;a href="prometheus-vs-influxdb"&gt;InfluxDB&lt;/a&gt; as an alternative data&amp;nbsp;source&lt;/li&gt;
&lt;li&gt;Explore &lt;a href="prometheus-alertmanager-setup"&gt;Grafana Alerting&lt;/a&gt; for advanced&amp;nbsp;notifications&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Beelink Mini S12 Pro&lt;/strong&gt;: Mini &lt;span class="caps"&gt;PC&lt;/span&gt; for Grafana + Prometheus&amp;nbsp;stack&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Samsung 990 &lt;span class="caps"&gt;EVO&lt;/span&gt;&lt;/strong&gt;: NVMe &lt;span class="caps"&gt;SSD&lt;/span&gt; for fast dashboard&amp;nbsp;loading&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;intro&lt;/code&gt; → &lt;code&gt;prometheus-monitoring-homelab&lt;/code&gt; for metrics&amp;nbsp;collection&lt;/li&gt;
&lt;li&gt;&lt;code&gt;step-2&lt;/code&gt; → &lt;code&gt;grafana-dashboard-homelab&lt;/code&gt; for advanced dashboard&amp;nbsp;ideas&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;grafana-loki-logs&lt;/code&gt; for log&amp;nbsp;aggregation&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] What&amp;#8217;s your favorite Grafana dashboard? Share IDs and&amp;nbsp;screenshots!&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for weekly homelab visualization and dashboard&amp;nbsp;guides.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Tutorials"/><category term="grafana"/><category term="docker compose"/><category term="dashboards"/><category term="monitoring"/><category term="homelab"/><category term="visualization"/></entry><entry><title>Homelab Networking Basics: A Complete Visual Guide for Self-Hosters</title><link href="https://steadypub.com/2026/06/homelab-networking-basics/" rel="alternate"/><published>2026-06-05T00:00:00+07:00</published><updated>2026-06-05T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/homelab-networking-basics/</id><summary type="html">&lt;p&gt;Learn the networking fundamentals every homelab needs: &lt;span class="caps"&gt;IP&lt;/span&gt; addressing, VLANs, subnetting, firewall rules, and how to wire them together. Designed for beginners with copy-paste&amp;nbsp;commands.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~13 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Beginners who want to understand how data moves inside their&amp;nbsp;homelab&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is Homelab&amp;nbsp;Networking?&lt;/h2&gt;
&lt;h3&gt;What Exactly Is&amp;nbsp;It?&lt;/h3&gt;
&lt;p&gt;Homelab networking is the practice of building and managing a local network that supports your self-hosted servers, VMs, containers, and IoT devices. It goes beyond a simple Wi-Fi router: you create subnets, isolate services with VLANs, and forward traffic with reverse proxies. Good networking is the foundation that makes your homelab secure, fast, and&amp;nbsp;scalable.&lt;/p&gt;
&lt;h3&gt;A Brief&amp;nbsp;History&lt;/h3&gt;
&lt;p&gt;In 2000, a home network was a single router and a few PCs. By 2010, &lt;span class="caps"&gt;NAS&lt;/span&gt; devices and media servers introduced the need for static IPs and port forwarding. Today, a modern homelab may have 50+ devices (VMs, containers, smart home gear), making flat networks a security and broadcast nightmare. VLANs, managed switches, and OPNSense/PfSense are now&amp;nbsp;standard.&lt;/p&gt;
&lt;h3&gt;Why It Matters&amp;nbsp;Today&lt;/h3&gt;
&lt;p&gt;Without a structured network, every device can see every other device. A compromised IoT bulb can scan your &lt;span class="caps"&gt;NAS&lt;/span&gt;. A misconfigured firewall can expose your dashboard to the internet. Proper networking is the difference between a toy and a production-grade&amp;nbsp;lab.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why It&amp;nbsp;Matters&lt;/h2&gt;
&lt;h3&gt;Benefit 1: Security&amp;nbsp;Isolation&lt;/h3&gt;
&lt;p&gt;VLANs let you segment your network into logical zones. Your servers, IoT devices, and guest Wi-Fi can be isolated so they cannot talk to each other unless you explicitly allow it. If a cheap camera is hacked, it cannot reach your Proxmox host or your file&amp;nbsp;server.&lt;/p&gt;
&lt;h3&gt;Benefit 2: Traffic&amp;nbsp;Management&lt;/h3&gt;
&lt;p&gt;Subnetting reduces broadcast traffic. In a flat /24 network (254 hosts), every &lt;span class="caps"&gt;ARP&lt;/span&gt; request hits every device. Splitting into /26 subnets (62 hosts each) keeps broadcast noise local and improves&amp;nbsp;performance.&lt;/p&gt;
&lt;h3&gt;Benefit 3: Simplified Access&amp;nbsp;Control&lt;/h3&gt;
&lt;p&gt;Firewall rules are easier to write when you know&amp;nbsp;that &lt;code&gt;192.168.10.0/24&lt;/code&gt; is &amp;#8220;servers&amp;#8221;&amp;nbsp;and &lt;code&gt;192.168.20.0/24&lt;/code&gt; is &amp;#8220;IoT.&amp;#8221; You can apply a single rule: &amp;#8220;Allow IoT to internet, but deny IoT to Servers.&amp;#8221; No per-device &lt;span class="caps"&gt;IP&lt;/span&gt; management&amp;nbsp;needed.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Core&amp;nbsp;Principles&lt;/h2&gt;
&lt;h3&gt;Principle 1: &lt;span class="caps"&gt;IP&lt;/span&gt; Addressing &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;Subnetting&lt;/h3&gt;
&lt;h4&gt;Explanation&lt;/h4&gt;
&lt;p&gt;Every device on your network needs an &lt;span class="caps"&gt;IP&lt;/span&gt; address. The address is split into a &lt;strong&gt;network portion&lt;/strong&gt; and a &lt;strong&gt;host portion&lt;/strong&gt;. A subnet mask&amp;nbsp;(e.g., &lt;code&gt;255.255.255.0&lt;/code&gt; or &lt;code&gt;/24&lt;/code&gt;) defines where the split&amp;nbsp;occurs.&lt;/p&gt;
&lt;p&gt;Common homelab&amp;nbsp;subnets:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Subnet&lt;/th&gt;
&lt;th&gt;Mask&lt;/th&gt;
&lt;th&gt;Usable Hosts&lt;/th&gt;
&lt;th&gt;Typical Use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;192.168.1.0/24&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;255.255.255.0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;254&lt;/td&gt;
&lt;td&gt;Default router &lt;span class="caps"&gt;LAN&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;192.168.10.0/24&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;255.255.255.0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;254&lt;/td&gt;
&lt;td&gt;Servers &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; VMs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;192.168.20.0/24&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;255.255.255.0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;254&lt;/td&gt;
&lt;td&gt;IoT devices&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;10.0.0.0/24&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;255.255.255.0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;254&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;VPN&lt;/span&gt;/tunnel network&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;10.10.10.0/24&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;255.255.255.0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;254&lt;/td&gt;
&lt;td&gt;Guest network&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4&gt;Example&lt;/h4&gt;
&lt;p&gt;You have a Proxmox host&amp;nbsp;at &lt;code&gt;192.168.10.10&lt;/code&gt; and a Pi-hole container&amp;nbsp;at &lt;code&gt;192.168.10.2&lt;/code&gt;. Both are in the same /24, so they communicate directly through the switch. Your router&amp;nbsp;at &lt;code&gt;192.168.1.1&lt;/code&gt; needs a static route or a &lt;span class="caps"&gt;VLAN&lt;/span&gt; interface to&amp;nbsp;reach &lt;code&gt;192.168.10.0/24&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Principle 2: VLANs (Virtual&amp;nbsp;LANs)&lt;/h3&gt;
&lt;h4&gt;Explanation&lt;/h4&gt;
&lt;p&gt;A &lt;span class="caps"&gt;VLAN&lt;/span&gt; tags Ethernet frames with a numeric &lt;span class="caps"&gt;ID&lt;/span&gt; (1–4094). A managed switch uses this &lt;span class="caps"&gt;ID&lt;/span&gt; to decide which ports belong to which logical network. You can have multiple VLANs on a single physical cable using &lt;strong&gt;802.1Q trunking&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Typical &lt;span class="caps"&gt;VLAN&lt;/span&gt; design for a&amp;nbsp;homelab:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;span class="caps"&gt;VLAN&lt;/span&gt; &lt;span class="caps"&gt;ID&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;th&gt;Subnet&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Default&lt;/td&gt;
&lt;td&gt;Router, switches&lt;/td&gt;
&lt;td&gt;&lt;code&gt;192.168.1.0/24&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;Servers&lt;/td&gt;
&lt;td&gt;Proxmox, &lt;span class="caps"&gt;NAS&lt;/span&gt;, VMs&lt;/td&gt;
&lt;td&gt;&lt;code&gt;192.168.10.0/24&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;IoT&lt;/td&gt;
&lt;td&gt;Cameras, bulbs, sensors&lt;/td&gt;
&lt;td&gt;&lt;code&gt;192.168.20.0/24&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;Guest&lt;/td&gt;
&lt;td&gt;Wi-Fi for visitors&lt;/td&gt;
&lt;td&gt;&lt;code&gt;192.168.30.0/24&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;40&lt;/td&gt;
&lt;td&gt;Management&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;IPMI&lt;/span&gt;, iDRAC, switch admin&lt;/td&gt;
&lt;td&gt;&lt;code&gt;192.168.40.0/24&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4&gt;Example&lt;/h4&gt;
&lt;p&gt;On a &lt;span class="caps"&gt;TP&lt;/span&gt;-Link Omada or UniFi switch, you configure:
- Port 1: Trunk (carries VLANs 1, 10, 20, 30, 40)
- Port 2: Access &lt;span class="caps"&gt;VLAN&lt;/span&gt; 10 (connects to Proxmox host)
- Port 3: Access &lt;span class="caps"&gt;VLAN&lt;/span&gt; 20 (connects to IoT&amp;nbsp;hub)&lt;/p&gt;
&lt;p&gt;On Proxmox, you create a Linux&amp;nbsp;bridge &lt;code&gt;vmbr0&lt;/code&gt; with a &lt;span class="caps"&gt;VLAN&lt;/span&gt;-aware interface, then assign &lt;span class="caps"&gt;VLAN&lt;/span&gt; tags to&amp;nbsp;VMs:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# /etc/network/interfaces snippet on Proxmox&lt;/span&gt;
auto&lt;span class="w"&gt; &lt;/span&gt;vmbr0
iface&lt;span class="w"&gt; &lt;/span&gt;vmbr0&lt;span class="w"&gt; &lt;/span&gt;inet&lt;span class="w"&gt; &lt;/span&gt;static
&lt;span class="w"&gt;    &lt;/span&gt;address&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.10.10/24
&lt;span class="w"&gt;    &lt;/span&gt;gateway&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.10.1
&lt;span class="w"&gt;    &lt;/span&gt;bridge-ports&lt;span class="w"&gt; &lt;/span&gt;enp3s0
&lt;span class="w"&gt;    &lt;/span&gt;bridge-vlan-aware&lt;span class="w"&gt; &lt;/span&gt;yes
&lt;span class="w"&gt;    &lt;/span&gt;bridge-vids&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;-4094

&lt;span class="c1"&gt;# Then assign a VM to VLAN 20 via the web UI&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Principle 3: Firewall&amp;nbsp;Rules&lt;/h3&gt;
&lt;h4&gt;Explanation&lt;/h4&gt;
&lt;p&gt;A firewall controls which traffic can cross between subnets or leave your network. In a homelab, the firewall is usually your router (OPNSense, pfSense, OpenWrt, or a UniFi Gateway). Rules are evaluated top-down and are &lt;strong&gt;default deny&lt;/strong&gt; (implicitly block unless&amp;nbsp;allowed).&lt;/p&gt;
&lt;p&gt;A typical rule set for the IoT &lt;span class="caps"&gt;VLAN&lt;/span&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Allow IoT → Internet&amp;nbsp;(any)&lt;/li&gt;
&lt;li&gt;Allow IoT → &lt;span class="caps"&gt;DNS&lt;/span&gt; server (port 53) on Servers &lt;span class="caps"&gt;VLAN&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Deny IoT → Servers &lt;span class="caps"&gt;VLAN&lt;/span&gt;&amp;nbsp;(any)&lt;/li&gt;
&lt;li&gt;Deny IoT → Management &lt;span class="caps"&gt;VLAN&lt;/span&gt;&amp;nbsp;(any)&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;Example&lt;/h4&gt;
&lt;p&gt;In pfSense, under &lt;strong&gt;Firewall → Rules → IoT&lt;/strong&gt;, you would&amp;nbsp;add:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Protocol&lt;/th&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th&gt;Destination&lt;/th&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Pass&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;TCP&lt;/span&gt;/&lt;span class="caps"&gt;UDP&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;IoT net&lt;/td&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;Internet&lt;/td&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;Allow outbound&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pass&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;TCP&lt;/span&gt;/&lt;span class="caps"&gt;UDP&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;IoT net&lt;/td&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;192.168.10.2&lt;/td&gt;
&lt;td&gt;53&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt; to Pi-hole&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Block&lt;/td&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;IoT net&lt;/td&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;Servers net&lt;/td&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;Block servers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Block&lt;/td&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;IoT net&lt;/td&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;Mgmt net&lt;/td&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;Block management&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Applying This to Your&amp;nbsp;Homelab&lt;/h2&gt;
&lt;h3&gt;Homelab Setup&amp;nbsp;Example&lt;/h3&gt;
&lt;p&gt;Imagine a small apartment homelab:
- &lt;strong&gt;Router&lt;/strong&gt;: OPNSense on a mini &lt;span class="caps"&gt;PC&lt;/span&gt; (4 NICs)
- &lt;strong&gt;Switch&lt;/strong&gt;: 8-port managed Gigabit switch (&lt;span class="caps"&gt;VLAN&lt;/span&gt;-aware)
- &lt;strong&gt;Server&lt;/strong&gt;: Proxmox host (1 &lt;span class="caps"&gt;NIC&lt;/span&gt;, &lt;span class="caps"&gt;VLAN&lt;/span&gt; trunk)
- &lt;strong&gt;Wi-Fi&lt;/strong&gt;: UniFi &lt;span class="caps"&gt;AP&lt;/span&gt; (&lt;span class="caps"&gt;SSID&lt;/span&gt; &amp;#8220;Home&amp;#8221; on &lt;span class="caps"&gt;VLAN&lt;/span&gt; 10, &amp;#8220;IoT&amp;#8221; on &lt;span class="caps"&gt;VLAN&lt;/span&gt; 20, &amp;#8220;Guest&amp;#8221; on &lt;span class="caps"&gt;VLAN&lt;/span&gt;&amp;nbsp;30)&lt;/p&gt;
&lt;p&gt;Traffic flow:
1. Your phone connects to &amp;#8220;Home&amp;#8221; (&lt;span class="caps"&gt;VLAN&lt;/span&gt; 10). It gets &lt;span class="caps"&gt;IP&lt;/span&gt; &lt;code&gt;192.168.10.50&lt;/code&gt;.
2. You open the Proxmox web &lt;span class="caps"&gt;UI&lt;/span&gt;&amp;nbsp;at &lt;code&gt;192.168.10.10&lt;/code&gt;. Both are on &lt;span class="caps"&gt;VLAN&lt;/span&gt; 10, so the switch forwards directly.
3. Your smart bulb connects to &amp;#8220;IoT&amp;#8221; (&lt;span class="caps"&gt;VLAN&lt;/span&gt; 20). It gets &lt;span class="caps"&gt;IP&lt;/span&gt; &lt;code&gt;192.168.20.15&lt;/code&gt;.
4. The bulb tries to&amp;nbsp;reach &lt;code&gt;192.168.10.10&lt;/code&gt;. The firewall blocks it.
5. The bulb resolves &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;via &lt;code&gt;192.168.10.2&lt;/code&gt; (Pi-hole) because the firewall allows port&amp;nbsp;53.&lt;/p&gt;
&lt;h3&gt;Practical&amp;nbsp;Steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Assign subnets&lt;/strong&gt; to each &lt;span class="caps"&gt;VLAN&lt;/span&gt;. Document them in a&amp;nbsp;spreadsheet.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configure VLANs&lt;/strong&gt; on your router and switch. Test with a laptop on each &lt;span class="caps"&gt;VLAN&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Set static IPs&lt;/strong&gt; for critical infrastructure (Proxmox, &lt;span class="caps"&gt;NAS&lt;/span&gt;, &lt;span class="caps"&gt;DNS&lt;/span&gt;, gateway). Use &lt;span class="caps"&gt;DHCP&lt;/span&gt;&amp;nbsp;reservations.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Write firewall rules&lt;/strong&gt; from most restrictive (IoT) to least restrictive&amp;nbsp;(Servers).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Test&lt;/strong&gt;&amp;nbsp;with &lt;code&gt;ping&lt;/code&gt; and &lt;code&gt;nmap&lt;/code&gt; from each &lt;span class="caps"&gt;VLAN&lt;/span&gt; to ensure isolation&amp;nbsp;works.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# From a device on the IoT VLAN, test connectivity&lt;/span&gt;
ping&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.10.2&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;# Should fail (firewall block)&lt;/span&gt;
ping&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.1.1.1&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="c1"&gt;# Should succeed (internet allowed)&lt;/span&gt;
nslookup&lt;span class="w"&gt; &lt;/span&gt;google.com&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.10.2&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Should succeed (DNS allowed)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Common Mistakes to&amp;nbsp;Avoid&lt;/h2&gt;
&lt;h3&gt;Mistake 1: Using the Default &lt;span class="caps"&gt;VLAN&lt;/span&gt; for&amp;nbsp;Everything&lt;/h3&gt;
&lt;p&gt;Leaving all devices on &lt;span class="caps"&gt;VLAN&lt;/span&gt; 1 makes isolation impossible. Create dedicated VLANs before you have 50 devices to&amp;nbsp;migrate.&lt;/p&gt;
&lt;h3&gt;Mistake 2: Forgetting the Default&amp;nbsp;Gateway&lt;/h3&gt;
&lt;p&gt;A &lt;span class="caps"&gt;VM&lt;/span&gt; on &lt;span class="caps"&gt;VLAN&lt;/span&gt; 10 needs its default gateway set&amp;nbsp;to &lt;code&gt;192.168.10.1&lt;/code&gt; (the router&amp;#8217;s &lt;span class="caps"&gt;VLAN&lt;/span&gt; interface). If the gateway is wrong, the &lt;span class="caps"&gt;VM&lt;/span&gt; can talk to local peers but cannot reach the&amp;nbsp;internet.&lt;/p&gt;
&lt;h3&gt;Mistake 3: Over-Complicating with Too Many&amp;nbsp;VLANs&lt;/h3&gt;
&lt;p&gt;You do not need a &lt;span class="caps"&gt;VLAN&lt;/span&gt; for every container. A good starting point is: Management, Servers, IoT, Guest. Add more only when you have a clear security&amp;nbsp;reason.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Homelab networking is not magic; it is structured &lt;span class="caps"&gt;IP&lt;/span&gt; addressing, &lt;span class="caps"&gt;VLAN&lt;/span&gt; tagging, and firewall rules. Start with a flat network, then add VLANs as you grow. The most secure lab is one where every device has the least privilege it needs to&amp;nbsp;function.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;[internal_link] Ready to deploy services? See our &lt;a href="https://steadypub.com/2026/06/docker-compose-for-beginners/"&gt;Docker Compose for beginners&lt;/a&gt;&amp;nbsp;guide.&lt;/li&gt;
&lt;li&gt;[internal_link] Need a reverse proxy? Read our &lt;a href="https://steadypub.com/2026/06/nginx-proxy-manager-docker-compose/"&gt;Nginx Proxy Manager Docker Compose guide&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;[internal_link] Want to secure remote access? Learn about &lt;a href="https://steadypub.com/2026/06/vps-vs-homelab-server/"&gt;Tailscale vs WireGuard&lt;/a&gt; for homelab &lt;span class="caps"&gt;VPN&lt;/span&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Networking gear&lt;/strong&gt;: &lt;span class="caps"&gt;TP&lt;/span&gt;-Link Omada, UniFi switches, and OPNSense mini &lt;span class="caps"&gt;PC&lt;/span&gt;&amp;nbsp;links&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cables&lt;/strong&gt;: Monoprice Cat6a and &lt;span class="caps"&gt;SFP&lt;/span&gt;+ &lt;span class="caps"&gt;DAC&lt;/span&gt; cable&amp;nbsp;links&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Books&lt;/strong&gt;: &amp;#8220;The Practice of System and Network Administration&amp;#8221; and &amp;#8220;Computer Networking: A Top-Down&amp;nbsp;Approach&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;what-is&lt;/code&gt; → &lt;code&gt;proxmox-beginner-guide-2026&lt;/code&gt; — &amp;#8220;introduction to Proxmox, where networking&amp;nbsp;begins&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;principle-2&lt;/code&gt; → &lt;code&gt;best-rack-server-for-homelab&lt;/code&gt; — &amp;#8220;hardware with multiple NICs for&amp;nbsp;VLANs&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;applying-it&lt;/code&gt; → &lt;code&gt;docker-compose-for-beginners&lt;/code&gt; — &amp;#8220;deploy apps on your new&amp;nbsp;network&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] What &lt;span class="caps"&gt;VLAN&lt;/span&gt; layout are you running? Share your subnet scheme in the&amp;nbsp;comments!&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for deep dives into OPNSense, WireGuard, and 10GbE&amp;nbsp;networking.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Concepts"/><category term="networking"/><category term="homelab"/><category term="vlan"/><category term="subnetting"/><category term="firewall"/><category term="basics"/><category term="self-hosted"/></entry><entry><title>Homelab Server Hardware 2025: Building the Perfect Self-Hosted Machine</title><link href="https://steadypub.com/2026/06/homelab-server-hardware-2025/" rel="alternate"/><published>2026-06-05T00:00:00+07:00</published><updated>2026-06-05T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/homelab-server-hardware-2025/</id><summary type="html">&lt;p&gt;The best hardware for homelab servers in 2025. Compare mini PCs, tower servers, and rack servers with real power draw, performance benchmarks, and price&amp;nbsp;recommendations.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~16 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Anyone building or upgrading a homelab&amp;nbsp;server&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is Homelab Server&amp;nbsp;Hardware?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Homelab server hardware is the physical machine that runs your self-hosted services. In 2025, the landscape has shifted dramatically: mini PCs based on Intel N100/N305 chips have replaced old rack servers for most users. The only reasons to buy a full rack server today are if you need 64+ &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, multiple GPUs, or 10+ hard&amp;nbsp;drives.&lt;/p&gt;
&lt;h3&gt;Why It Matters&amp;nbsp;Today&lt;/h3&gt;
&lt;p&gt;Electricity costs are rising. A Dell R720 draws 150W+ idle and costs $200+/year in power. A Beelink &lt;span class="caps"&gt;EQ12&lt;/span&gt; (Intel N100) draws 8W idle and costs $12/year. The performance gap has closed enough that a mini &lt;span class="caps"&gt;PC&lt;/span&gt; can handle Proxmox, Docker, media streaming, and file hosting for most&amp;nbsp;households.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Evaluation&amp;nbsp;Criteria&lt;/h2&gt;
&lt;h3&gt;Price-to-Performance&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Form Factor&lt;/th&gt;
&lt;th&gt;Cost New&lt;/th&gt;
&lt;th&gt;Cost Used&lt;/th&gt;
&lt;th&gt;Power Draw&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mini &lt;span class="caps"&gt;PC&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$150–300&lt;/td&gt;
&lt;td&gt;$80–150&lt;/td&gt;
&lt;td&gt;6–25W&lt;/td&gt;
&lt;td&gt;Docker, light VMs, media&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tower Server&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$500–1,500&lt;/td&gt;
&lt;td&gt;$200–500&lt;/td&gt;
&lt;td&gt;40–80W&lt;/td&gt;
&lt;td&gt;Multiple VMs, &lt;span class="caps"&gt;NAS&lt;/span&gt;, transcoding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rack Server&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$1,500–5,000+&lt;/td&gt;
&lt;td&gt;$300–800&lt;/td&gt;
&lt;td&gt;100–200W&lt;/td&gt;
&lt;td&gt;Enterprise workloads, many VMs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Custom Build&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$400–800&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;30–60W&lt;/td&gt;
&lt;td&gt;Flexibility, &lt;span class="caps"&gt;GPU&lt;/span&gt; passthrough&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Feature&amp;nbsp;Set&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Mini &lt;span class="caps"&gt;PC&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Tower Server&lt;/th&gt;
&lt;th&gt;Rack Server&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt; slots&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1–2 (&lt;span class="caps"&gt;SODIMM&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;4–8 (&lt;span class="caps"&gt;DIMM&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;8–24 (&lt;span class="caps"&gt;DIMM&lt;/span&gt;/&lt;span class="caps"&gt;ECC&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Max &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;16–64 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;64–256 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;256 &lt;span class="caps"&gt;GB&lt;/span&gt;–2 &lt;span class="caps"&gt;TB&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage bays&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1–3 M.2&lt;/td&gt;
&lt;td&gt;4–8 &lt;span class="caps"&gt;SATA&lt;/span&gt;/&lt;span class="caps"&gt;SAS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;8–24 &lt;span class="caps"&gt;SATA&lt;/span&gt;/&lt;span class="caps"&gt;SAS&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PCIe slots&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0–1&lt;/td&gt;
&lt;td&gt;2–4&lt;/td&gt;
&lt;td&gt;4–10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;GPU&lt;/span&gt; support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Full&lt;/td&gt;
&lt;td&gt;Full&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Noise&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Silent&lt;/td&gt;
&lt;td&gt;Quiet&lt;/td&gt;
&lt;td&gt;Loud&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;IPMI&lt;/span&gt; / iDRAC&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Sometimes&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;10GbE&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Rare&lt;/td&gt;
&lt;td&gt;Sometimes&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;#1: Mini &lt;span class="caps"&gt;PC&lt;/span&gt; (Intel N100 /&amp;nbsp;N305)&lt;/h2&gt;
&lt;h3&gt;Why It Tops Our&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;The Intel N100 mini &lt;span class="caps"&gt;PC&lt;/span&gt; is the defining homelab hardware of 2025. It is silent, cheap, and powerful enough for 10–15 Docker containers or 3–5 Proxmox VMs. The N305 adds 4 more cores and dual 2.5GbE for heavier&amp;nbsp;workloads.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Intel N100&lt;/th&gt;
&lt;th&gt;Intel N305&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cores&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;4 (4 threads)&lt;/td&gt;
&lt;td&gt;8 (8 threads)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;TDP&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;6W&lt;/td&gt;
&lt;td&gt;15W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Up to 16 &lt;span class="caps"&gt;GB&lt;/span&gt; (single slot)&lt;/td&gt;
&lt;td&gt;Up to 32 &lt;span class="caps"&gt;GB&lt;/span&gt; (dual slot)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1–2 M.2 NVMe&lt;/td&gt;
&lt;td&gt;1–2 M.2 NVMe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;NIC&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1–2 GbE (Realtek/Intel)&lt;/td&gt;
&lt;td&gt;2 × 2.5GbE (Intel i226)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;QuickSync&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Price&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$150–200&lt;/td&gt;
&lt;td&gt;$200–300&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Extremely low power:&lt;/strong&gt; 6–15W idle. Under $15/year in&amp;nbsp;electricity.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Silent:&lt;/strong&gt; Fan noise under 25 dB. Ideal for&amp;nbsp;apartments.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;QuickSync:&lt;/strong&gt; Hardware transcoding for Jellyfin, Plex,&amp;nbsp;Immich.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cheap:&lt;/strong&gt; A complete N100 setup costs less than a used rack server&amp;#8217;s power&amp;nbsp;supply.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Limited &lt;span class="caps"&gt;RAM&lt;/span&gt;:&lt;/strong&gt; Single-slot models max at 16 &lt;span class="caps"&gt;GB&lt;/span&gt;. Dual-slot models needed for Proxmox with 4+&amp;nbsp;VMs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No PCIe expansion:&lt;/strong&gt; Cannot add 10GbE cards, HBAs, or&amp;nbsp;GPUs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Realtek NICs:&lt;/strong&gt; Some models have Realtek NICs that cause issues with Proxmox &lt;span class="caps"&gt;SR&lt;/span&gt;-&lt;span class="caps"&gt;IOV&lt;/span&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;First-time&amp;nbsp;homelabbers.&lt;/li&gt;
&lt;li&gt;Docker-only&amp;nbsp;users.&lt;/li&gt;
&lt;li&gt;Apartment dwellers who need&amp;nbsp;silence.&lt;/li&gt;
&lt;li&gt;Users who want QuickSync&amp;nbsp;transcoding.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Beelink &lt;span class="caps"&gt;EQ12&lt;/span&gt; (N100):&lt;/strong&gt;&amp;nbsp;~$150&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Minisforum &lt;span class="caps"&gt;UN100D&lt;/span&gt; (N100):&lt;/strong&gt;&amp;nbsp;~$170&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Minisforum &lt;span class="caps"&gt;UN305&lt;/span&gt; (N305):&lt;/strong&gt;&amp;nbsp;~$250&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;#2: Tower Server (Dell PowerEdge T340 / &lt;span class="caps"&gt;HP&lt;/span&gt; ProLiant &lt;span class="caps"&gt;ML350&lt;/span&gt;)&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;Tower servers offer the expandability of a rack server in a quiet, desktop-friendly form factor. They support &lt;span class="caps"&gt;ECC&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, multiple hard drives, and PCIe expansion while producing less noise than a 1U rack&amp;nbsp;unit.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Dell T340&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;HP&lt;/span&gt; &lt;span class="caps"&gt;ML350&lt;/span&gt; Gen10&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Intel Xeon E-2200&lt;/td&gt;
&lt;td&gt;Intel Xeon Scalable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Up to 64 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;ECC&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Up to 256 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;ECC&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Drives&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;8 × 3.5&amp;#8221; &lt;span class="caps"&gt;SATA&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;8 × 3.5&amp;#8221; &lt;span class="caps"&gt;SATA&lt;/span&gt;/&lt;span class="caps"&gt;SAS&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PCIe&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;4 slots&lt;/td&gt;
&lt;td&gt;4–6 slots&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;NIC&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2 × 1GbE&lt;/td&gt;
&lt;td&gt;2 × 1GbE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;IPMI&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;iDRAC 9&lt;/td&gt;
&lt;td&gt;iLO 5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Price (used)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$300–600&lt;/td&gt;
&lt;td&gt;$400–800&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;ECC&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; support:&lt;/strong&gt; Prevents data corruption for &lt;span class="caps"&gt;ZFS&lt;/span&gt; and&amp;nbsp;databases.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multiple drive bays:&lt;/strong&gt; 8–12 bays for a large &lt;span class="caps"&gt;NAS&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PCIe expansion:&lt;/strong&gt; Add HBAs, 10GbE cards, or&amp;nbsp;GPUs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;IPMI&lt;/span&gt;/iDRAC:&lt;/strong&gt; Remote management even if the &lt;span class="caps"&gt;OS&lt;/span&gt; is&amp;nbsp;down.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Power draw:&lt;/strong&gt; 40–80W idle. $50–100/year in&amp;nbsp;electricity.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Used hardware risk:&lt;/strong&gt; Hard drives and fans may need&amp;nbsp;replacement.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Size:&lt;/strong&gt; Larger than a mini &lt;span class="caps"&gt;PC&lt;/span&gt;. Requires dedicated&amp;nbsp;space.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Users who need 32+ &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;NAS&lt;/span&gt; builders who want 6+ hard&amp;nbsp;drives.&lt;/li&gt;
&lt;li&gt;Users who need remote management&amp;nbsp;(iDRAC/iLO).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Used Dell T340:&lt;/strong&gt;&amp;nbsp;$300–600&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Used &lt;span class="caps"&gt;HP&lt;/span&gt; &lt;span class="caps"&gt;ML350&lt;/span&gt; Gen10:&lt;/strong&gt;&amp;nbsp;$400–800&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;#3: Rack Server (Dell R720 / R730 / &lt;span class="caps"&gt;HP&lt;/span&gt; &lt;span class="caps"&gt;DL380&lt;/span&gt;&amp;nbsp;Gen9)&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;Rack servers are the most powerful homelab hardware. They support dual CPUs, 24+ &lt;span class="caps"&gt;DIMM&lt;/span&gt; slots, and enterprise features like redundant power supplies. However, they are loud, power-hungry, and oversized for most&amp;nbsp;homes.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Dell R720&lt;/th&gt;
&lt;th&gt;Dell R730&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;HP&lt;/span&gt; &lt;span class="caps"&gt;DL380&lt;/span&gt; Gen9&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2 × Xeon E5-2600 v2&lt;/td&gt;
&lt;td&gt;2 × Xeon E5-2600 v3/v4&lt;/td&gt;
&lt;td&gt;2 × Xeon E5-2600 v3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Up to 768 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Up to 768 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Up to 768 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Drives&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;8 × 2.5&amp;#8221; or 3.5&amp;#8221;&lt;/td&gt;
&lt;td&gt;8 × 2.5&amp;#8221; or 3.5&amp;#8221;&lt;/td&gt;
&lt;td&gt;8 × 2.5&amp;#8221; or 3.5&amp;#8221;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PCIe&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;7 slots&lt;/td&gt;
&lt;td&gt;7 slots&lt;/td&gt;
&lt;td&gt;6 slots&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;NIC&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;4 × 1GbE&lt;/td&gt;
&lt;td&gt;4 × 1GbE&lt;/td&gt;
&lt;td&gt;4 × 1GbE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;IPMI&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;iDRAC 7&lt;/td&gt;
&lt;td&gt;iDRAC 8&lt;/td&gt;
&lt;td&gt;iLO 4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Price (used)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$200–400&lt;/td&gt;
&lt;td&gt;$300–600&lt;/td&gt;
&lt;td&gt;$250–500&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Massive &lt;span class="caps"&gt;RAM&lt;/span&gt; capacity:&lt;/strong&gt; 512+ &lt;span class="caps"&gt;GB&lt;/span&gt; for large virtualization&amp;nbsp;labs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dual CPUs:&lt;/strong&gt; 24+ cores for heavy compute&amp;nbsp;workloads.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enterprise reliability:&lt;/strong&gt; Redundant power, &lt;span class="caps"&gt;ECC&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, &lt;span class="caps"&gt;IPMI&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cheap used:&lt;/strong&gt; $200–400 for a powerful&amp;nbsp;machine.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Extremely loud:&lt;/strong&gt; 50–60 dB at idle. Requires a closet or&amp;nbsp;basement.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;High power draw:&lt;/strong&gt; 100–200W idle. $150–300/year in&amp;nbsp;electricity.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Heavy:&lt;/strong&gt; 15–30 kg. Requires a rack or strong&amp;nbsp;shelf.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Old hardware:&lt;/strong&gt; R720s are from 2012–2013. Power efficiency is poor compared to modern&amp;nbsp;CPUs.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Users running 10+ VMs or large Kubernetes&amp;nbsp;clusters.&lt;/li&gt;
&lt;li&gt;Students studying for enterprise certifications (&lt;span class="caps"&gt;RHCE&lt;/span&gt;, VMware &lt;span class="caps"&gt;VCP&lt;/span&gt;).&lt;/li&gt;
&lt;li&gt;Users who need a large &lt;span class="caps"&gt;NAS&lt;/span&gt; with 8+&amp;nbsp;drives.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Used Dell R720:&lt;/strong&gt;&amp;nbsp;$200–400&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Used Dell R730:&lt;/strong&gt;&amp;nbsp;$300–600&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Used &lt;span class="caps"&gt;HP&lt;/span&gt; &lt;span class="caps"&gt;DL380&lt;/span&gt; Gen9:&lt;/strong&gt;&amp;nbsp;$250–500&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;#4: Custom Build (Mini-&lt;span class="caps"&gt;ITX&lt;/span&gt; / Micro-&lt;span class="caps"&gt;ATX&lt;/span&gt;)&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;A custom build gives you maximum flexibility. You choose the motherboard, &lt;span class="caps"&gt;CPU&lt;/span&gt;, case, and power supply. Mini-&lt;span class="caps"&gt;ITX&lt;/span&gt; builds with &lt;span class="caps"&gt;AMD&lt;/span&gt; Ryzen or Intel Core i3/i5 offer the performance of a tower server in a compact&amp;nbsp;case.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Mini-&lt;span class="caps"&gt;ITX&lt;/span&gt; Custom Build&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;AMD&lt;/span&gt; Ryzen 5 7600 / Intel i5-13400&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;32–64 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;DDR4&lt;/span&gt;/&lt;span class="caps"&gt;DDR5&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Drives&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;4–6 &lt;span class="caps"&gt;SATA&lt;/span&gt; + 2 M.2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PCIe&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1–2 slots&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;NIC&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1–2 GbE (onboard)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Power&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;30–50W idle&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Price&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$400–700&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Latest CPUs:&lt;/strong&gt; Modern power efficiency and&amp;nbsp;performance.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flexible:&lt;/strong&gt; Choose exactly the case, motherboard, and &lt;span class="caps"&gt;PSU&lt;/span&gt; you&amp;nbsp;want.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Quiet:&lt;/strong&gt; Can be built with Noctua fans and passive &lt;span class="caps"&gt;CPU&lt;/span&gt;&amp;nbsp;coolers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Expandable:&lt;/strong&gt; Add HBAs, 10GbE cards, or GPUs via&amp;nbsp;PCIe.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;More expensive than a mini &lt;span class="caps"&gt;PC&lt;/span&gt;.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Requires assembly and&amp;nbsp;troubleshooting.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No &lt;span class="caps"&gt;IPMI&lt;/span&gt;/iDRAC&lt;/strong&gt; unless you buy a server&amp;nbsp;motherboard.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Users who want the best of both worlds (mini &lt;span class="caps"&gt;PC&lt;/span&gt; size + tower&amp;nbsp;expandability).&lt;/li&gt;
&lt;li&gt;Users who need a specific feature (e.g., 10GbE, &lt;span class="caps"&gt;GPU&lt;/span&gt;&amp;nbsp;passthrough).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Budget build (i3-12100, 32 &lt;span class="caps"&gt;GB&lt;/span&gt;, 512 &lt;span class="caps"&gt;GB&lt;/span&gt; NVMe):&lt;/strong&gt;&amp;nbsp;~$400&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Performance build (Ryzen 7600, 64 &lt;span class="caps"&gt;GB&lt;/span&gt;, 1 &lt;span class="caps"&gt;TB&lt;/span&gt; NVMe):&lt;/strong&gt;&amp;nbsp;~$700&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Quick Comparison&amp;nbsp;Table&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Hardware&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;th&gt;Power&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Noise&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Mini &lt;span class="caps"&gt;PC&lt;/span&gt; (N100)&lt;/td&gt;
&lt;td&gt;$150–200&lt;/td&gt;
&lt;td&gt;6–15W&lt;/td&gt;
&lt;td&gt;16 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Silent&lt;/td&gt;
&lt;td&gt;Entry-level Docker&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mini &lt;span class="caps"&gt;PC&lt;/span&gt; (N305)&lt;/td&gt;
&lt;td&gt;$200–300&lt;/td&gt;
&lt;td&gt;15–25W&lt;/td&gt;
&lt;td&gt;32 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Silent&lt;/td&gt;
&lt;td&gt;Proxmox + 3–4 VMs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tower Server&lt;/td&gt;
&lt;td&gt;$300–800&lt;/td&gt;
&lt;td&gt;40–80W&lt;/td&gt;
&lt;td&gt;64–256 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Quiet&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;NAS&lt;/span&gt; + multiple VMs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rack Server&lt;/td&gt;
&lt;td&gt;$200–600&lt;/td&gt;
&lt;td&gt;100–200W&lt;/td&gt;
&lt;td&gt;256+ &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Loud&lt;/td&gt;
&lt;td&gt;10+ VMs, certification&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom Build&lt;/td&gt;
&lt;td&gt;$400–700&lt;/td&gt;
&lt;td&gt;30–50W&lt;/td&gt;
&lt;td&gt;32–64 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Quiet&lt;/td&gt;
&lt;td&gt;Flexibility, modern CPUs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Measure Your Power Before&amp;nbsp;Buying&lt;/h3&gt;
&lt;p&gt;Use a Kill-A-Watt meter to measure your current setup. If you are under 50W, a mini &lt;span class="caps"&gt;PC&lt;/span&gt; is perfect. If you are over 100W, consider a tower server or custom&amp;nbsp;build.&lt;/p&gt;
&lt;h3&gt;Tip 2: Prioritize QuickSync for Media&amp;nbsp;Servers&lt;/h3&gt;
&lt;p&gt;If you run Jellyfin, Plex, or Immich, Intel QuickSync is essential. &lt;span class="caps"&gt;AMD&lt;/span&gt; Ryzen does not have QuickSync. An Intel N100, N305, or i3-12100 is&amp;nbsp;ideal.&lt;/p&gt;
&lt;h3&gt;Tip 3: Buy Used Enterprise SSDs for&amp;nbsp;Boot&lt;/h3&gt;
&lt;p&gt;Used enterprise SSDs (Intel S4510, Samsung &lt;span class="caps"&gt;PM883&lt;/span&gt;) are cheap, reliable, and have high write endurance. A 240 &lt;span class="caps"&gt;GB&lt;/span&gt; enterprise &lt;span class="caps"&gt;SSD&lt;/span&gt; costs ~$20 used and outlasts a consumer &lt;span class="caps"&gt;SSD&lt;/span&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;For most homelabbers in 2025, a mini &lt;span class="caps"&gt;PC&lt;/span&gt; with an Intel N100 or N305 is the best choice. It is silent, cheap, and powerful enough for Docker, Proxmox, and media streaming. If you need 32+ &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, multiple hard drives, or &lt;span class="caps"&gt;IPMI&lt;/span&gt;, a tower server or custom build is the next step. Rack servers are only justified for certification labs or massive&amp;nbsp;virtualization.&lt;/p&gt;
&lt;h3&gt;Our&amp;nbsp;Recommendation&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;First homelab (Docker + 3–5 services):&lt;/strong&gt; Intel N100 mini &lt;span class="caps"&gt;PC&lt;/span&gt;&amp;nbsp;($150–200)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Proxmox + 4–6 VMs:&lt;/strong&gt; Intel N305 mini &lt;span class="caps"&gt;PC&lt;/span&gt; or custom i3 build&amp;nbsp;($250–400)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;NAS&lt;/span&gt; + 6+ drives + &lt;span class="caps"&gt;ECC&lt;/span&gt;:&lt;/strong&gt; Used tower server or custom build&amp;nbsp;($400–800)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Certification lab / 10+ VMs:&lt;/strong&gt; Used Dell R730&amp;nbsp;($300–600)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mini PCs:&lt;/strong&gt; Beelink, Minisforum,&amp;nbsp;GMKtec&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tower servers:&lt;/strong&gt; Dell, &lt;span class="caps"&gt;HP&lt;/span&gt; (refurbished&amp;nbsp;resellers)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rack servers:&lt;/strong&gt; eBay, ServerMonkey,&amp;nbsp;SaveMyServer&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Components:&lt;/strong&gt; Crucial &lt;span class="caps"&gt;RAM&lt;/span&gt;, Samsung SSDs, Noctua&amp;nbsp;fans&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;UPS&lt;/span&gt;:&lt;/strong&gt; &lt;span class="caps"&gt;APC&lt;/span&gt; Back-&lt;span class="caps"&gt;UPS&lt;/span&gt; Pro for protecting&amp;nbsp;hardware&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;why-this-matters&lt;/code&gt; → &lt;code&gt;mini-pc-home-server-2025&lt;/code&gt; — &amp;#8220;deep dive into mini &lt;span class="caps"&gt;PC&lt;/span&gt;&amp;nbsp;servers&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;item-1&lt;/code&gt; → &lt;code&gt;intel-n100-mini-pc-homelab&lt;/code&gt; — &amp;#8220;Intel N100 performance&amp;nbsp;review&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;item-2&lt;/code&gt; → &lt;code&gt;used-server-hardware-for-homelab&lt;/code&gt; — &amp;#8220;buying used servers&amp;nbsp;safely&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;proxmox-beginner-guide-2026&lt;/code&gt; — &amp;#8220;install Proxmox on your new&amp;nbsp;hardware&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;What hardware runs your homelab?&lt;/strong&gt; Share your specs and power draw in the&amp;nbsp;comments.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subscribe&lt;/strong&gt; for hardware reviews, power efficiency guides, and build&amp;nbsp;recommendations.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Guides"/><category term="homelab server hardware"/><category term="best server hardware"/><category term="self-hosted server"/><category term="mini pc"/><category term="rack server"/><category term="homelab build"/></entry><entry><title>Homelab Server Hardware 2026: The Complete Build Guide</title><link href="https://steadypub.com/2026/06/homelab-server-hardware-2026/" rel="alternate"/><published>2026-06-05T00:00:00+07:00</published><updated>2026-06-05T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/homelab-server-hardware-2026/</id><summary type="html">&lt;p&gt;A comprehensive guide to choosing homelab server hardware in 2026. Covers CPUs, &lt;span class="caps"&gt;RAM&lt;/span&gt;, storage, NICs, and form factors with real recommendations and budget&amp;nbsp;tiers.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~15 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Anyone planning a new homelab build or&amp;nbsp;upgrade&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is Homelab Server&amp;nbsp;Hardware?&lt;/h2&gt;
&lt;h3&gt;What Exactly Is&amp;nbsp;It?&lt;/h3&gt;
&lt;p&gt;Homelab server hardware is the physical infrastructure you use to run self-hosted services. It ranges from a $150 mini &lt;span class="caps"&gt;PC&lt;/span&gt; to a $2,000 rack server. Unlike a desktop &lt;span class="caps"&gt;PC&lt;/span&gt;, homelab hardware is chosen for 24/7 uptime, power efficiency, remote management, and virtualization support. The right hardware depends on your workload: a &lt;span class="caps"&gt;DNS&lt;/span&gt; server needs almost nothing, while a 4K Plex server with &lt;span class="caps"&gt;AI&lt;/span&gt; transcoding needs a modern &lt;span class="caps"&gt;GPU&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;A Brief&amp;nbsp;History&lt;/h3&gt;
&lt;p&gt;In 2015, a homelab was often an old desktop or a Dell OptiPlex. By 2020, the Intel &lt;span class="caps"&gt;NUC&lt;/span&gt; dominated small labs. In 2024–2026, the market exploded with Chinese mini PCs (Beelink, Minisforum), &lt;span class="caps"&gt;ARM&lt;/span&gt; servers (Raspberry Pi 5), and affordable used enterprise gear (Dell R730). The result is that you can build a capable lab for any&amp;nbsp;budget.&lt;/p&gt;
&lt;h3&gt;Why It Matters&amp;nbsp;Today&lt;/h3&gt;
&lt;p&gt;Choosing the wrong hardware leads to three problems:
1. &lt;strong&gt;Over-spending:&lt;/strong&gt; Buying a $1,500 rack server when a $300 mini &lt;span class="caps"&gt;PC&lt;/span&gt; would suffice.
2. &lt;strong&gt;Power bills:&lt;/strong&gt; An old R710 at 200W idle costs $200+/year in electricity.
3. &lt;strong&gt;Scalability walls:&lt;/strong&gt; A 4-core &lt;span class="caps"&gt;NUC&lt;/span&gt; with 16 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; cannot grow with your&amp;nbsp;needs.&lt;/p&gt;
&lt;p&gt;This guide helps you match hardware to your actual use&amp;nbsp;case.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why It&amp;nbsp;Matters&lt;/h2&gt;
&lt;h3&gt;Benefit 1: Total Cost of&amp;nbsp;Ownership&lt;/h3&gt;
&lt;p&gt;A cheap server that uses 200W costs more over 3 years than an efficient one. Consider upfront cost + electricity + cooling. A $300 mini &lt;span class="caps"&gt;PC&lt;/span&gt; at 15W is cheaper than a free R710 at&amp;nbsp;200W.&lt;/p&gt;
&lt;h3&gt;Benefit 2: Learning&amp;nbsp;Relevance&lt;/h3&gt;
&lt;p&gt;Enterprise hardware (iDRAC, &lt;span class="caps"&gt;RAID&lt;/span&gt;, &lt;span class="caps"&gt;IPMI&lt;/span&gt;) teaches you skills that transfer directly to sysadmin and DevOps roles. Consumer hardware teaches you less about remote&amp;nbsp;management.&lt;/p&gt;
&lt;h3&gt;Benefit 3:&amp;nbsp;Scalability&lt;/h3&gt;
&lt;p&gt;A 2U rack server with 24 &lt;span class="caps"&gt;RAM&lt;/span&gt; slots can scale from 16 &lt;span class="caps"&gt;GB&lt;/span&gt; to 768 &lt;span class="caps"&gt;GB&lt;/span&gt; without replacing the motherboard. A mini &lt;span class="caps"&gt;PC&lt;/span&gt; with 2 &lt;span class="caps"&gt;SODIMM&lt;/span&gt; slots maxes out at 64 &lt;span class="caps"&gt;GB&lt;/span&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Core&amp;nbsp;Principles&lt;/h2&gt;
&lt;h3&gt;Principle 1: &lt;span class="caps"&gt;CPU&lt;/span&gt;&amp;nbsp;Selection&lt;/h3&gt;
&lt;h4&gt;Explanation&lt;/h4&gt;
&lt;p&gt;The &lt;span class="caps"&gt;CPU&lt;/span&gt; is the heart of your homelab. For virtualization, you care about core count, thread count, and features like &lt;span class="caps"&gt;VT&lt;/span&gt;-x/&lt;span class="caps"&gt;AMD&lt;/span&gt;-V (virtualization), &lt;span class="caps"&gt;VT&lt;/span&gt;-d/&lt;span class="caps"&gt;AMD&lt;/span&gt;-Vi (&lt;span class="caps"&gt;PCI&lt;/span&gt; passthrough), and &lt;span class="caps"&gt;AES&lt;/span&gt;-&lt;span class="caps"&gt;NI&lt;/span&gt;&amp;nbsp;(encryption).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tiers for&amp;nbsp;2026:&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tier&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt; Example&lt;/th&gt;
&lt;th&gt;Cores/Threads&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;TDP&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Budget&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Intel N100 / N305&lt;/td&gt;
&lt;td&gt;4C/4T or 8C/8T&lt;/td&gt;
&lt;td&gt;6–15W&lt;/td&gt;
&lt;td&gt;2–4 VMs, &lt;span class="caps"&gt;LXC&lt;/span&gt; containers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mid-range&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;AMD&lt;/span&gt; Ryzen 5 5560U / 7 &lt;span class="caps"&gt;7735HS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;6C/12T or 8C/16T&lt;/td&gt;
&lt;td&gt;15–35W&lt;/td&gt;
&lt;td&gt;8–12 VMs, light transcoding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Performance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Intel Xeon E5-2680 v4&lt;/td&gt;
&lt;td&gt;14C/28T&lt;/td&gt;
&lt;td&gt;120W&lt;/td&gt;
&lt;td&gt;20+ VMs, heavy compute&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Enthusiast&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;AMD&lt;/span&gt; Ryzen 9 7950X / Threadripper&lt;/td&gt;
&lt;td&gt;16C/32T+&lt;/td&gt;
&lt;td&gt;65–170W&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;GPU&lt;/span&gt; passthrough, &lt;span class="caps"&gt;AI&lt;/span&gt;, massive VMs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4&gt;Example&lt;/h4&gt;
&lt;p&gt;A Proxmox host running Pi-hole, Nextcloud, and Jellyfin needs ~4 cores. A host running 10 Windows VMs for a test lab needs 16+&amp;nbsp;cores.&lt;/p&gt;
&lt;h3&gt;Principle 2: &lt;span class="caps"&gt;RAM&lt;/span&gt;&amp;nbsp;Selection&lt;/h3&gt;
&lt;h4&gt;Explanation&lt;/h4&gt;
&lt;p&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt; is the most common bottleneck in homelabs. Every &lt;span class="caps"&gt;VM&lt;/span&gt; consumes &lt;span class="caps"&gt;RAM&lt;/span&gt;. &lt;span class="caps"&gt;ZFS&lt;/span&gt; (a popular filesystem) uses &lt;span class="caps"&gt;RAM&lt;/span&gt; for &lt;span class="caps"&gt;ARC&lt;/span&gt; cache. A good rule of&amp;nbsp;thumb:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Base &lt;span class="caps"&gt;OS&lt;/span&gt;:&lt;/strong&gt; 2–4 &lt;span class="caps"&gt;GB&lt;/span&gt; for Proxmox or&amp;nbsp;TrueNAS.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Per &lt;span class="caps"&gt;VM&lt;/span&gt;:&lt;/strong&gt; 2–4 &lt;span class="caps"&gt;GB&lt;/span&gt; for Linux, 4–8 &lt;span class="caps"&gt;GB&lt;/span&gt; for&amp;nbsp;Windows.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;ZFS&lt;/span&gt; &lt;span class="caps"&gt;ARC&lt;/span&gt;:&lt;/strong&gt; 1 &lt;span class="caps"&gt;GB&lt;/span&gt; per &lt;span class="caps"&gt;TB&lt;/span&gt; of storage (or 50% of total &lt;span class="caps"&gt;RAM&lt;/span&gt;, whichever is&amp;nbsp;smaller).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt; types:&lt;/strong&gt;
- &lt;strong&gt;&lt;span class="caps"&gt;DDR3&lt;/span&gt; &lt;span class="caps"&gt;ECC&lt;/span&gt;:&lt;/strong&gt; Cheap, used in R720/R730. Good for budget builds.
- &lt;strong&gt;&lt;span class="caps"&gt;DDR4&lt;/span&gt; &lt;span class="caps"&gt;ECC&lt;/span&gt;:&lt;/strong&gt; Modern, used in R730/R740 and &lt;span class="caps"&gt;AMD&lt;/span&gt; &lt;span class="caps"&gt;EPYC&lt;/span&gt;. Best balance.
- &lt;strong&gt;&lt;span class="caps"&gt;DDR5&lt;/span&gt; &lt;span class="caps"&gt;ECC&lt;/span&gt;:&lt;/strong&gt; Cutting edge, expensive. Used in Ryzen 7000 and Intel Xeon W.
- &lt;strong&gt;Non-&lt;span class="caps"&gt;ECC&lt;/span&gt; &lt;span class="caps"&gt;SODIMM&lt;/span&gt;:&lt;/strong&gt; Used in mini PCs. Fine for small labs, but no error&amp;nbsp;correction.&lt;/p&gt;
&lt;h4&gt;Example&lt;/h4&gt;
&lt;p&gt;A mini &lt;span class="caps"&gt;PC&lt;/span&gt; with 32 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;DDR4&lt;/span&gt; can run 8–10 &lt;span class="caps"&gt;LXC&lt;/span&gt; containers. A rack server with 128 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;DDR4&lt;/span&gt; can run 20+ VMs with&amp;nbsp;headroom.&lt;/p&gt;
&lt;h3&gt;Principle 3: Storage&amp;nbsp;Strategy&lt;/h3&gt;
&lt;h4&gt;Explanation&lt;/h4&gt;
&lt;p&gt;Storage is about speed, capacity, and redundancy. Most homelabs use a tiered&amp;nbsp;approach:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tier&lt;/th&gt;
&lt;th&gt;Media&lt;/th&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;Speed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Boot&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;256–512 &lt;span class="caps"&gt;GB&lt;/span&gt; NVMe&lt;/td&gt;
&lt;td&gt;Proxmox &lt;span class="caps"&gt;OS&lt;/span&gt;, &lt;span class="caps"&gt;VM&lt;/span&gt; disks&lt;/td&gt;
&lt;td&gt;3,000+ &lt;span class="caps"&gt;MB&lt;/span&gt;/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;VM&lt;/span&gt; Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1–2 &lt;span class="caps"&gt;TB&lt;/span&gt; NVMe or &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Active &lt;span class="caps"&gt;VM&lt;/span&gt; disks, databases&lt;/td&gt;
&lt;td&gt;500–3,500 &lt;span class="caps"&gt;MB&lt;/span&gt;/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bulk Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;4–20 &lt;span class="caps"&gt;TB&lt;/span&gt; &lt;span class="caps"&gt;HDD&lt;/span&gt; (3.5&amp;#8221;)&lt;/td&gt;
&lt;td&gt;Media, backups, archives&lt;/td&gt;
&lt;td&gt;150–200 &lt;span class="caps"&gt;MB&lt;/span&gt;/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cold Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;External &lt;span class="caps"&gt;USB&lt;/span&gt; or offsite&lt;/td&gt;
&lt;td&gt;Long-term backups&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Redundancy options:&lt;/strong&gt;
- &lt;strong&gt;&lt;span class="caps"&gt;ZFS&lt;/span&gt;:&lt;/strong&gt; Software &lt;span class="caps"&gt;RAID&lt;/span&gt; with checksums, snapshots, and compression. Best for TrueNAS or Proxmox.
- &lt;strong&gt;Hardware &lt;span class="caps"&gt;RAID&lt;/span&gt;:&lt;/strong&gt; Dell &lt;span class="caps"&gt;PERC&lt;/span&gt;, &lt;span class="caps"&gt;HP&lt;/span&gt; Smart Array. Good for Windows VMs, but avoid for &lt;span class="caps"&gt;ZFS&lt;/span&gt;.
- &lt;strong&gt;Single disk + backups:&lt;/strong&gt; Acceptable for small labs with good 3-2-1&amp;nbsp;backups.&lt;/p&gt;
&lt;h4&gt;Example&lt;/h4&gt;
&lt;p&gt;A 4-drive &lt;span class="caps"&gt;ZFS&lt;/span&gt; pool of 4 &lt;span class="caps"&gt;TB&lt;/span&gt; HDDs in &lt;span class="caps"&gt;RAID&lt;/span&gt;-Z1 gives you 12 &lt;span class="caps"&gt;TB&lt;/span&gt; usable. Add an &lt;span class="caps"&gt;L2ARC&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt; for cache and a &lt;span class="caps"&gt;ZIL&lt;/span&gt; NVMe for sync&amp;nbsp;writes.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Applying This to Your&amp;nbsp;Homelab&lt;/h2&gt;
&lt;h3&gt;Homelab Setup&amp;nbsp;Example&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;The $400 Mini &lt;span class="caps"&gt;PC&lt;/span&gt; Lab:&lt;/strong&gt;
- &lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;:&lt;/strong&gt; Intel N100 (4 cores, 6W)
- &lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;:&lt;/strong&gt; 16 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;DDR4&lt;/span&gt; &lt;span class="caps"&gt;SODIMM&lt;/span&gt; (upgrade to 32 &lt;span class="caps"&gt;GB&lt;/span&gt; later)
- &lt;strong&gt;Boot:&lt;/strong&gt; 512 &lt;span class="caps"&gt;GB&lt;/span&gt; NVMe
- &lt;strong&gt;Storage:&lt;/strong&gt; 2 &lt;span class="caps"&gt;TB&lt;/span&gt; 2.5&amp;#8221; &lt;span class="caps"&gt;SSD&lt;/span&gt; (for VMs)
- &lt;strong&gt;Network:&lt;/strong&gt; 1x 1GbE (add a 2.5 GbE &lt;span class="caps"&gt;USB&lt;/span&gt; &lt;span class="caps"&gt;NIC&lt;/span&gt; if needed)
- &lt;strong&gt;&lt;span class="caps"&gt;OS&lt;/span&gt;:&lt;/strong&gt; Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;
- &lt;strong&gt;Services:&lt;/strong&gt; Pi-hole, Nextcloud, Jellyfin, Immich (light&amp;nbsp;use)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The $1,200 Rack Lab:&lt;/strong&gt;
- &lt;strong&gt;Server:&lt;/strong&gt; Dell R730 (2x E5-2680 v4, 128 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;DDR4&lt;/span&gt;)
- &lt;strong&gt;Boot:&lt;/strong&gt; 2x 480 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt; (&lt;span class="caps"&gt;RAID&lt;/span&gt;-1)
- &lt;strong&gt;Storage:&lt;/strong&gt; 6x 4 &lt;span class="caps"&gt;TB&lt;/span&gt; &lt;span class="caps"&gt;HDD&lt;/span&gt; (&lt;span class="caps"&gt;ZFS&lt;/span&gt; &lt;span class="caps"&gt;RAID&lt;/span&gt;-Z2) + 2x 1 &lt;span class="caps"&gt;TB&lt;/span&gt; NVMe (&lt;span class="caps"&gt;L2ARC&lt;/span&gt;/&lt;span class="caps"&gt;ZIL&lt;/span&gt;)
- &lt;strong&gt;Network:&lt;/strong&gt; 2x 10GbE &lt;span class="caps"&gt;SFP&lt;/span&gt;+ (Mellanox ConnectX-3)
- &lt;strong&gt;&lt;span class="caps"&gt;UPS&lt;/span&gt;:&lt;/strong&gt; &lt;span class="caps"&gt;APC&lt;/span&gt; Smart-&lt;span class="caps"&gt;UPS&lt;/span&gt; 1500 &lt;span class="caps"&gt;VA&lt;/span&gt;
- &lt;strong&gt;Switch:&lt;/strong&gt; 8-port 10GbE &lt;span class="caps"&gt;SFP&lt;/span&gt;+ managed switch
- &lt;strong&gt;Services:&lt;/strong&gt; 20+ VMs, Kubernetes, Plex (4K transcoding), &lt;span class="caps"&gt;ZFS&lt;/span&gt; &lt;span class="caps"&gt;NAS&lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;Practical&amp;nbsp;Steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;List your planned services&lt;/strong&gt; and estimate their &lt;span class="caps"&gt;RAM&lt;/span&gt;/&lt;span class="caps"&gt;CPU&lt;/span&gt;&amp;nbsp;needs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Choose a form factor:&lt;/strong&gt; Mini &lt;span class="caps"&gt;PC&lt;/span&gt; (silent), Tower (expandable), or Rack&amp;nbsp;(enterprise).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pick a &lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/strong&gt; with virtualization support and enough&amp;nbsp;cores.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Buy &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt; in matched pairs. For &lt;span class="caps"&gt;ZFS&lt;/span&gt;, allocate 1 &lt;span class="caps"&gt;GB&lt;/span&gt; per &lt;span class="caps"&gt;TB&lt;/span&gt; of&amp;nbsp;storage.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Design storage:&lt;/strong&gt; Use NVMe for speed, &lt;span class="caps"&gt;HDD&lt;/span&gt; for bulk, and &lt;span class="caps"&gt;ZFS&lt;/span&gt; for&amp;nbsp;integrity.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Plan networking:&lt;/strong&gt; 1GbE is fine for most. Add 2.5 GbE or 10GbE if you transfer large&amp;nbsp;files.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Buy a &lt;span class="caps"&gt;UPS&lt;/span&gt;&lt;/strong&gt; sized to your load (see our &lt;a href="https://steadypub.com/2026/06/ups-for-homelab/"&gt;&lt;span class="caps"&gt;UPS&lt;/span&gt; guide&lt;/a&gt;).&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Estimate your power draw&lt;/span&gt;
&lt;span class="c1"&gt;# Mini PC: 10-15W idle&lt;/span&gt;
&lt;span class="c1"&gt;# Rack server: 80-150W idle&lt;/span&gt;
&lt;span class="c1"&gt;# Per HDD: 5-8W&lt;/span&gt;
&lt;span class="c1"&gt;# Per NVMe: 3-5W&lt;/span&gt;
&lt;span class="c1"&gt;# Total = sum of all components&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Common Mistakes to&amp;nbsp;Avoid&lt;/h2&gt;
&lt;h3&gt;Mistake 1: Buying Old, Power-Hungry&amp;nbsp;Gear&lt;/h3&gt;
&lt;p&gt;A Dell R710 (2009) is free on Craigslist but uses 200W idle. Over 3 years, that costs $700 in electricity. A $300 mini &lt;span class="caps"&gt;PC&lt;/span&gt; at 15W costs $50. Do the&amp;nbsp;math.&lt;/p&gt;
&lt;h3&gt;Mistake 2: Ignoring &lt;span class="caps"&gt;ECC&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;For &lt;span class="caps"&gt;ZFS&lt;/span&gt; and TrueNAS, &lt;span class="caps"&gt;ECC&lt;/span&gt; is strongly recommended. It prevents silent corruption. If you use non-&lt;span class="caps"&gt;ECC&lt;/span&gt;, scrub your pools weekly and keep&amp;nbsp;backups.&lt;/p&gt;
&lt;h3&gt;Mistake 3: Using Consumer SSDs for 24/7 Write&amp;nbsp;Loads&lt;/h3&gt;
&lt;p&gt;&lt;span class="caps"&gt;QLC&lt;/span&gt; and &lt;span class="caps"&gt;TLC&lt;/span&gt; consumer SSDs wear out quickly under constant writes (databases, &lt;span class="caps"&gt;ZFS&lt;/span&gt; &lt;span class="caps"&gt;SLOG&lt;/span&gt;). Use datacenter SSDs (Intel D3, Samsung &lt;span class="caps"&gt;PM893&lt;/span&gt;) or dedicated NVMe for write-heavy&amp;nbsp;tasks.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Homelab hardware in 2026 is divided into three tiers:
- &lt;strong&gt;Mini &lt;span class="caps"&gt;PC&lt;/span&gt; ($150–400):&lt;/strong&gt; Perfect for beginners, silent, low power.
- &lt;strong&gt;Tower / Workstation ($400–800):&lt;/strong&gt; Good expandability, mid-range CPUs.
- &lt;strong&gt;Rack Server ($200–2,000):&lt;/strong&gt; Maximum power, remote management, but loud and&amp;nbsp;power-hungry.&lt;/p&gt;
&lt;p&gt;Match your hardware to your workload. A mini &lt;span class="caps"&gt;PC&lt;/span&gt; is enough for most personal labs. A rack server is only justified if you need 20+ VMs, heavy I/O, or enterprise&amp;nbsp;features.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;[internal_link] Ready to buy? See our &lt;a href="https://steadypub.com/2026/06/best-rack-server-for-homelab/"&gt;best rack server guide&lt;/a&gt; for used&amp;nbsp;deals.&lt;/li&gt;
&lt;li&gt;[internal_link] Want a mini &lt;span class="caps"&gt;PC&lt;/span&gt;? Read our &lt;a href="https://steadypub.com/2026/06/beelink-mini-pc-proxmox/"&gt;Beelink Proxmox guide&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;[internal_link] Need storage? Learn about &lt;a href="https://steadypub.com/2026/06/self-hosted-cloud-storage-nextcloud/"&gt;&lt;span class="caps"&gt;ZFS&lt;/span&gt; and TrueNAS&lt;/a&gt; for bulk&amp;nbsp;storage.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mini PCs&lt;/strong&gt;: Beelink, Minisforum, Intel &lt;span class="caps"&gt;NUC&lt;/span&gt; affiliate&amp;nbsp;links&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rack Servers&lt;/strong&gt;: eBay, ServerMonkey,&amp;nbsp;SaveMyServer&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;: Crucial, Kingston,&amp;nbsp;Samsung&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Storage&lt;/strong&gt;: Samsung 990 Pro, &lt;span class="caps"&gt;WD&lt;/span&gt; Red, Seagate&amp;nbsp;IronWolf&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Networking&lt;/strong&gt;: &lt;span class="caps"&gt;TP&lt;/span&gt;-Link, Ubiquiti,&amp;nbsp;MikroTik&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;UPS&lt;/span&gt;&lt;/strong&gt;: &lt;span class="caps"&gt;APC&lt;/span&gt;, CyberPower,&amp;nbsp;Eaton&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;what-is&lt;/code&gt; → &lt;code&gt;proxmox-beginner-guide-2026&lt;/code&gt; — &amp;#8220;start with Proxmox on your new&amp;nbsp;hardware&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;principle-1&lt;/code&gt; → &lt;code&gt;best-rack-server-for-homelab&lt;/code&gt; — &amp;#8220;rack server &lt;span class="caps"&gt;CPU&lt;/span&gt;&amp;nbsp;recommendations&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;principle-3&lt;/code&gt; → &lt;code&gt;ups-for-homelab&lt;/code&gt; — &amp;#8220;protect your hardware with a &lt;span class="caps"&gt;UPS&lt;/span&gt;&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;applying-it&lt;/code&gt; → &lt;code&gt;docker-compose-for-beginners&lt;/code&gt; — &amp;#8220;deploy apps on your new&amp;nbsp;server&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] What hardware are you running in your homelab? Share your specs and power&amp;nbsp;draw!&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for hardware deal alerts, build guides, and power efficiency&amp;nbsp;tips.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Concepts"/><category term="homelab server hardware"/><category term="2026"/><category term="build guide"/><category term="cpu"/><category term="ram"/><category term="storage"/><category term="mini pc"/><category term="rack"/></entry><entry><title>Immich vs Google Photos: The Ultimate Self-Hosted Photo Backup Comparison</title><link href="https://steadypub.com/2026/06/immich-vs-google-photos/" rel="alternate"/><published>2026-06-05T00:00:00+07:00</published><updated>2026-06-05T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/immich-vs-google-photos/</id><summary type="html">&lt;p&gt;Immich is the leading Google Photos alternative for self-hosters. Compare features, &lt;span class="caps"&gt;AI&lt;/span&gt; search, storage costs, privacy, and mobile apps to decide if you should&amp;nbsp;migrate.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~14 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Users considering leaving Google Photos for a self-hosted&amp;nbsp;alternative&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The Immich vs Google Photos&amp;nbsp;Dilemma&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Google Photos is the most popular photo backup service in the world. It offers unlimited storage (for compressed photos), powerful &lt;span class="caps"&gt;AI&lt;/span&gt; search, and seamless mobile apps. But it comes with a cost: your photos are mined for data, used to train &lt;span class="caps"&gt;AI&lt;/span&gt; models, and locked behind Google&amp;#8217;s account&amp;nbsp;system.&lt;/p&gt;
&lt;p&gt;Immich is the open-source answer. It offers automatic mobile backup, &lt;span class="caps"&gt;AI&lt;/span&gt;-powered facial recognition, timeline and map views, and album sharing — all on your own hardware. The question is: can Immich truly replace Google Photos for everyday&amp;nbsp;users?&lt;/p&gt;
&lt;h3&gt;Key Differences at a&amp;nbsp;Glance&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Google Photos&lt;/th&gt;
&lt;th&gt;Immich (Self-Hosted)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$0–$20/month (Google One)&lt;/td&gt;
&lt;td&gt;One-time hardware cost&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;AI&lt;/span&gt; face recognition&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Industry-leading&lt;/td&gt;
&lt;td&gt;✅ Good (local &lt;span class="caps"&gt;ML&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Object/scene search&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ &amp;#8220;dogs at beach&amp;#8221;&lt;/td&gt;
&lt;td&gt;✅ &amp;#8220;beach&amp;#8221; works; &amp;#8220;dogs at beach&amp;#8221; limited&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mobile auto-upload&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Instant&lt;/td&gt;
&lt;td&gt;✅ Background (iOS/Android)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Live photos&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Full support&lt;/td&gt;
&lt;td&gt;✅ Supported (iOS)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAW&lt;/span&gt;/&lt;span class="caps"&gt;DNG&lt;/span&gt; support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Video transcoding&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Automatic&lt;/td&gt;
&lt;td&gt;✅ Configurable (FFmpeg)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Album sharing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Easy links&lt;/td&gt;
&lt;td&gt;✅ Shared links + partner sharing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Privacy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Google scans photos&lt;/td&gt;
&lt;td&gt;✅ Your data stays local&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Offline access&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Requires internet&lt;/td&gt;
&lt;td&gt;✅ &lt;span class="caps"&gt;LAN&lt;/span&gt;-only works&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Export/migration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Google Takeout is messy&lt;/td&gt;
&lt;td&gt;✅ Files are just files on disk&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Option A: Google&amp;nbsp;Photos&lt;/h2&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Best-in-class &lt;span class="caps"&gt;AI&lt;/span&gt; search:&lt;/strong&gt; Type &amp;#8220;birthday cake 2023&amp;#8221; and find the exact photo. Google&amp;#8217;s &lt;span class="caps"&gt;AI&lt;/span&gt; is years ahead of open-source&amp;nbsp;alternatives.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Unlimited compressed storage:&lt;/strong&gt; The &amp;#8220;Storage Saver&amp;#8221; tier offers free unlimited backups at reduced&amp;nbsp;quality.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Seamless ecosystem:&lt;/strong&gt; Photos sync to Google Drive, appear in Google Docs, and integrate with&amp;nbsp;Android.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reliability:&lt;/strong&gt; Google&amp;#8217;s infrastructure is bulletproof. Your photos are replicated across&amp;nbsp;continents.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Editing tools:&lt;/strong&gt; Built-in cropping, filters, and auto-enhance are&amp;nbsp;polished.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Privacy nightmare:&lt;/strong&gt; Google scans your photos for objects, faces, locations, and text. This data feeds ad targeting and &lt;span class="caps"&gt;AI&lt;/span&gt;&amp;nbsp;training.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Account lock-in:&lt;/strong&gt; If your Google account is banned (false positive, payment issue), you lose&amp;nbsp;access.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Compression:&lt;/strong&gt; Storage Saver reduces quality. Original quality requires a paid&amp;nbsp;plan.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No true ownership:&lt;/strong&gt; You cannot directly access the raw files without Google Takeout, which is a zip-of-zips&amp;nbsp;mess.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Geofencing risks:&lt;/strong&gt; Google knows exactly where every photo was&amp;nbsp;taken.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Users who prioritize convenience and &lt;span class="caps"&gt;AI&lt;/span&gt; search over&amp;nbsp;privacy.&lt;/li&gt;
&lt;li&gt;Families who do not want to manage a&amp;nbsp;server.&lt;/li&gt;
&lt;li&gt;Users with thousands of photos who cannot afford a &lt;span class="caps"&gt;NAS&lt;/span&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plan&lt;/th&gt;
&lt;th&gt;Storage&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Google One Basic&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;100 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$1.99/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Google One Standard&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;200 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$2.99/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Google One Premium&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2 &lt;span class="caps"&gt;TB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$9.99/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage Saver&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Unlimited&lt;/td&gt;
&lt;td&gt;Free (compressed)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Option B:&amp;nbsp;Immich&lt;/h2&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;True privacy:&lt;/strong&gt; Your photos never leave your hardware. No &lt;span class="caps"&gt;AI&lt;/span&gt; training, no ad targeting, no geolocation&amp;nbsp;mining.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No subscription fees:&lt;/strong&gt; Buy a hard drive once. A 4 &lt;span class="caps"&gt;TB&lt;/span&gt; drive stores ~1 million photos and costs&amp;nbsp;~$80.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Full quality:&lt;/strong&gt; Every photo is stored at original resolution. No compression, no&amp;nbsp;re-encoding.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;AI&lt;/span&gt; features (local):&lt;/strong&gt; Facial recognition, duplicate detection, object detection, and smart search — all run on your server via machine learning&amp;nbsp;models.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Open source:&lt;/strong&gt; &lt;span class="caps"&gt;MIT&lt;/span&gt; license. You can audit the code, modify it, and self-host&amp;nbsp;indefinitely.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Partner sharing:&lt;/strong&gt; Share a library with a partner so both phones auto-upload to the same Immich&amp;nbsp;instance.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Map and timeline views:&lt;/strong&gt; Beautiful, fast, and functional — comparable to Google&amp;nbsp;Photos.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Server required:&lt;/strong&gt; You need a mini &lt;span class="caps"&gt;PC&lt;/span&gt;, &lt;span class="caps"&gt;NAS&lt;/span&gt;, or &lt;span class="caps"&gt;VPS&lt;/span&gt; running 24/7. This is a hardware and power&amp;nbsp;cost.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;AI&lt;/span&gt; search is weaker:&lt;/strong&gt; &amp;#8220;Show me photos of my dog at the park&amp;#8221; is harder than in Google Photos. Simple searches (&amp;#8220;beach&amp;#8221;, &amp;#8220;car&amp;#8221;, &amp;#8220;person&amp;#8221;) work&amp;nbsp;well.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Setup complexity:&lt;/strong&gt; You must install Docker, configure PostgreSQL, Redis, and machine learning&amp;nbsp;containers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mobile app limitations:&lt;/strong&gt; The iOS app is excellent but occasionally misses background uploads. Android is more&amp;nbsp;reliable.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No ecosystem:&lt;/strong&gt; Immich does not integrate with email, documents, or&amp;nbsp;calendars.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Privacy-conscious users who want full ownership of their&amp;nbsp;photos.&lt;/li&gt;
&lt;li&gt;Homelabbers who already run a&amp;nbsp;server.&lt;/li&gt;
&lt;li&gt;Photographers who want original-quality backups without cloud&amp;nbsp;subscriptions.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Cost (one-time)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mini &lt;span class="caps"&gt;PC&lt;/span&gt; / &lt;span class="caps"&gt;NAS&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$150–300&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;4 &lt;span class="caps"&gt;TB&lt;/span&gt; hard drive&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~$80&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Electricity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~$1–2/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Software&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Free (open source)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total 3-year cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~$230–380&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Compare to Google One 2 &lt;span class="caps"&gt;TB&lt;/span&gt;: $9.99 × 36 = &lt;strong&gt;$360&lt;/strong&gt;. Immich breaks even in ~3 years and then saves&amp;nbsp;money.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Option C: Other&amp;nbsp;Alternatives&lt;/h2&gt;
&lt;h3&gt;Nextcloud&amp;nbsp;Photos&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Integrated with Nextcloud file&amp;nbsp;sync.&lt;/li&gt;
&lt;li&gt;Basic timeline and facial recognition (via Recognize&amp;nbsp;app).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Users already running Nextcloud who want a simple photo&amp;nbsp;gallery.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;PhotoPrism&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="caps"&gt;AI&lt;/span&gt;-powered photo management with&amp;nbsp;TensorFlow.&lt;/li&gt;
&lt;li&gt;Excellent search, no mobile auto-upload (requires third-party&amp;nbsp;sync).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Users who want the best &lt;span class="caps"&gt;AI&lt;/span&gt; search without mobile&amp;nbsp;auto-backup.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Synology&amp;nbsp;Photos&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Built into Synology &lt;span class="caps"&gt;NAS&lt;/span&gt;&amp;nbsp;devices.&lt;/li&gt;
&lt;li&gt;Good mobile apps, facial recognition, and&amp;nbsp;sharing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Synology &lt;span class="caps"&gt;NAS&lt;/span&gt; owners who want a turnkey&amp;nbsp;solution.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Comparison&amp;nbsp;Matrix&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;Google Photos&lt;/th&gt;
&lt;th&gt;Immich&lt;/th&gt;
&lt;th&gt;Winner&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Privacy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Immich&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;AI&lt;/span&gt; search&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;⚠️ Good&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Google Photos&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cost (3 years)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$360+&lt;/td&gt;
&lt;td&gt;$230–380&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Immich&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ease of setup&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌ Requires Docker&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Google Photos&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mobile backup&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅ (iOS/Android)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Tie&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Family sharing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅ (partner sharing)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Tie&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAW&lt;/span&gt; support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Tie&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Offline access&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Immich&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Export freedom&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅ (just files)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Immich&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Which Should You&amp;nbsp;Choose?&lt;/h2&gt;
&lt;h3&gt;Scenario 1: &amp;#8220;I want the easiest photo backup with the best&amp;nbsp;search.&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose Google Photos.&lt;/strong&gt; The &lt;span class="caps"&gt;AI&lt;/span&gt; search is unmatched, and the mobile apps are frictionless. If privacy is not a top concern, Google Photos is the pragmatic&amp;nbsp;choice.&lt;/p&gt;
&lt;h3&gt;Scenario 2: &amp;#8220;I run a homelab and care about&amp;nbsp;privacy.&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose Immich.&lt;/strong&gt; It is the closest Google Photos replacement for self-hosters. The mobile app auto-uploads, the &lt;span class="caps"&gt;AI&lt;/span&gt; features are solid, and your data stays&amp;nbsp;local.&lt;/p&gt;
&lt;h3&gt;Scenario 3: &amp;#8220;I want &lt;span class="caps"&gt;AI&lt;/span&gt; search but not&amp;nbsp;Google.&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose PhotoPrism.&lt;/strong&gt; It has the best open-source &lt;span class="caps"&gt;AI&lt;/span&gt; search (via TensorFlow). Pair it with a sync app like Syncthing or Nextcloud for mobile&amp;nbsp;backup.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Migration&amp;nbsp;Path&lt;/h2&gt;
&lt;h3&gt;Step 1: Export from Google&amp;nbsp;Photos&lt;/h3&gt;
&lt;p&gt;Use Google Takeout:
1. Go to &lt;a href="https://takeout.google.com"&gt;Google Takeout&lt;/a&gt;.
2. Select &lt;strong&gt;Google Photos&lt;/strong&gt;.
3. Choose &lt;strong&gt;Export once&lt;/strong&gt; → &lt;strong&gt;Maximum 2 &lt;span class="caps"&gt;GB&lt;/span&gt; per file&lt;/strong&gt;.
4. Wait for the email (can take hours to days).
5. Download and extract the &lt;span class="caps"&gt;ZIP&lt;/span&gt;&amp;nbsp;files.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pro tip:&lt;/strong&gt; The metadata (&lt;span class="caps"&gt;EXIF&lt;/span&gt;, timestamps) is in &lt;span class="caps"&gt;JSON&lt;/span&gt; sidecar files. Immich will read these during&amp;nbsp;import.&lt;/p&gt;
&lt;h3&gt;Step 2: Prepare&amp;nbsp;Immich&lt;/h3&gt;
&lt;p&gt;Follow our &lt;a href="https://steadypub.com/2026/06/immich-photo-server/"&gt;Immich Docker Compose setup guide&lt;/a&gt;. Ensure:
- PostgreSQL and Redis are running.
-&amp;nbsp;The &lt;code&gt;upload&lt;/code&gt; directory has enough space (2–3× your photo library size).
- Machine learning is enabled for facial&amp;nbsp;recognition.&lt;/p&gt;
&lt;h3&gt;Step 3: Import&amp;nbsp;Photos&lt;/h3&gt;
&lt;p&gt;In the Immich web &lt;span class="caps"&gt;UI&lt;/span&gt;:
1. Go to &lt;strong&gt;Administration&lt;/strong&gt; → &lt;strong&gt;Jobs&lt;/strong&gt;.
2. Use the &lt;strong&gt;Import&lt;/strong&gt; feature or drag-and-drop into albums.
3. Wait for thumbnail generation and facial recognition (can take hours for large&amp;nbsp;libraries).&lt;/p&gt;
&lt;h3&gt;Step 4: Configure Mobile&amp;nbsp;Auto-Upload&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;iOS:&lt;/strong&gt; Enable background app refresh and location permissions. Immich uses geofencing to trigger&amp;nbsp;uploads.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Android:&lt;/strong&gt; Enable battery optimization exemption. The upload service runs reliably in the&amp;nbsp;background.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;The&amp;nbsp;Verdict&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Verdict&lt;/th&gt;
&lt;th&gt;Recommendation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for privacy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Immich&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for &lt;span class="caps"&gt;AI&lt;/span&gt; search&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Google Photos&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for non-technical users&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Google Photos&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for homelabbers&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Immich&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for photographers&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Immich (original quality)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best long-term cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Immich&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Google Photos is the convenient choice. Immich is the sovereign choice. For users who already run a homelab, Immich is a no-brainer: it delivers 90% of Google Photos&amp;#8217; functionality with 100% privacy and zero subscriptions. The &lt;span class="caps"&gt;AI&lt;/span&gt; gap is closing rapidly — by 2026, Immich&amp;#8217;s facial recognition and object detection are already good enough for daily&amp;nbsp;use.&lt;/p&gt;
&lt;h3&gt;Ready to Get&amp;nbsp;Started?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;New to self-hosting?&lt;/strong&gt; Read our &lt;a href="https://steadypub.com/2026/06/immich-photo-server/"&gt;Immich Docker Compose setup&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Need hardware?&lt;/strong&gt; See our &lt;a href="https://steadypub.com/2026/06/mini-pc-home-server-2025/"&gt;best mini &lt;span class="caps"&gt;PC&lt;/span&gt; for homelab&lt;/a&gt;&amp;nbsp;guide.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Want to compare more?&lt;/strong&gt; Check our &lt;a href="https://steadypub.com/2026/06/nextcloud-immich-comparison/"&gt;Nextcloud vs Immich comparison&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mini PCs:&lt;/strong&gt; Beelink, Minisforum for running&amp;nbsp;Immich.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hard drives:&lt;/strong&gt; &lt;span class="caps"&gt;WD&lt;/span&gt; Red, Seagate IronWolf, Samsung&amp;nbsp;SSDs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;NAS&lt;/span&gt;:&lt;/strong&gt; Synology, &lt;span class="caps"&gt;QNAP&lt;/span&gt;, TrueNAS &lt;span class="caps"&gt;SCALE&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;UPS&lt;/span&gt;:&lt;/strong&gt; &lt;span class="caps"&gt;APC&lt;/span&gt; Back-&lt;span class="caps"&gt;UPS&lt;/span&gt; for protecting your photo&amp;nbsp;server.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;intro-dilemma&lt;/code&gt; → &lt;code&gt;immich-photo-server&lt;/code&gt; — &amp;#8220;complete Immich setup&amp;nbsp;guide&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;migration-path&lt;/code&gt; → &lt;code&gt;immich-reverse-proxy&lt;/code&gt; — &amp;#8220;secure your Immich instance with &lt;span class="caps"&gt;HTTPS&lt;/span&gt;&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;best-self-hosted-apps-2026&lt;/code&gt; — &amp;#8220;other apps to run alongside&amp;nbsp;Immich&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Did you migrate from Google Photos to Immich?&lt;/strong&gt; Share your experience in the&amp;nbsp;comments.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subscribe&lt;/strong&gt; for photo backup guides, &lt;span class="caps"&gt;AI&lt;/span&gt; privacy news, and self-hosting&amp;nbsp;tutorials.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Comparisons"/><category term="immich vs google photos"/><category term="google photos alternative"/><category term="self-hosted photos"/><category term="photo backup"/><category term="homelab"/></entry><entry><title>Intel N100 Mini PC for Homelab: The Perfect Entry-Level Server</title><link href="https://steadypub.com/2026/06/intel-n100-mini-pc-homelab/" rel="alternate"/><published>2026-06-05T00:00:00+07:00</published><updated>2026-06-05T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/intel-n100-mini-pc-homelab/</id><summary type="html">&lt;p&gt;Why the Intel N100 mini &lt;span class="caps"&gt;PC&lt;/span&gt; is the best entry-level homelab server in 2026. Specs, power consumption, Proxmox setup, real-world performance, and what you can actually run on&amp;nbsp;it.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~12 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Beginners and budget-conscious&amp;nbsp;homelabbers&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is the Intel N100 Mini &lt;span class="caps"&gt;PC&lt;/span&gt;?&lt;/h2&gt;
&lt;h3&gt;What Exactly Is&amp;nbsp;It?&lt;/h3&gt;
&lt;p&gt;The Intel N100 is a quad-core, quad-thread Alder Lake-N processor launched in early 2023. It is part of Intel&amp;#8217;s &amp;#8220;Intel Processor&amp;#8221; branding (replacing Celeron/Pentium) and is designed for low-cost, low-power devices. Despite its humble positioning, the N100 has become a cult favorite in the homelab community for running 24/7&amp;nbsp;services.&lt;/p&gt;
&lt;h3&gt;A Brief&amp;nbsp;History&lt;/h3&gt;
&lt;p&gt;Before the N100, homelabbers on a budget relied on Raspberry Pi 4 (&lt;span class="caps"&gt;ARM&lt;/span&gt;, limited &lt;span class="caps"&gt;RAM&lt;/span&gt;) or expensive Intel NUCs. The N100 changed the game by delivering x86 compatibility, &lt;span class="caps"&gt;16GB&lt;/span&gt; &lt;span class="caps"&gt;DDR5&lt;/span&gt; support, and 2.5GbE networking in a $150–$200 package. By 2026, it has become the default recommendation for first-time homelab&amp;nbsp;builders.&lt;/p&gt;
&lt;h3&gt;Why It Matters&amp;nbsp;Today&lt;/h3&gt;
&lt;p&gt;The N100 offers a rare combination of:
- &lt;strong&gt;x86_64 architecture&lt;/strong&gt; (runs any Linux/Windows software)
- &lt;strong&gt;Low power&lt;/strong&gt; (6–8W idle)
- &lt;strong&gt;Modern connectivity&lt;/strong&gt; (2.5GbE, &lt;span class="caps"&gt;USB&lt;/span&gt; 3.2, NVMe)
- &lt;strong&gt;Adequate &lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/strong&gt; (4 cores, enough for 5–10 Docker containers)
- &lt;strong&gt;Low cost&lt;/strong&gt; ($150–$200 for a complete&amp;nbsp;system)&lt;/p&gt;
&lt;p&gt;For the price of a Raspberry Pi 5 kit with accessories, you get a fully capable x86 server with better&amp;nbsp;I/O.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why It&amp;nbsp;Matters&lt;/h2&gt;
&lt;h3&gt;Benefit 1: Unmatched Price-to-Performance for&amp;nbsp;Beginners&lt;/h3&gt;
&lt;p&gt;At $150–$200, the N100 mini &lt;span class="caps"&gt;PC&lt;/span&gt; delivers more computing power per dollar than any other homelab entry point. You get a full Debian/Proxmox host that can run Pi-hole, Nextcloud, Jellyfin, and Home Assistant&amp;nbsp;simultaneously.&lt;/p&gt;
&lt;h3&gt;Benefit 2: Silent 24/7&amp;nbsp;Operation&lt;/h3&gt;
&lt;p&gt;Most N100 mini PCs are fanless or use a tiny blower that is inaudible at 1 meter. This means you can run it in a bedroom, living room, or closet without noise complaints. A used rack server at 40 dB(A) is a non-starter in&amp;nbsp;apartments.&lt;/p&gt;
&lt;h3&gt;Benefit 3: Modern Networking and&amp;nbsp;Storage&lt;/h3&gt;
&lt;p&gt;Unlike older NUCs or Celeron J4125 systems, the N100 supports:
- 2.5GbE (2.5x faster than Gigabit on supported models)
- NVMe Gen3 x4 (up to 3,500 &lt;span class="caps"&gt;MB&lt;/span&gt;/s read)
- &lt;span class="caps"&gt;DDR5&lt;/span&gt;-4800 (faster memory bandwidth than &lt;span class="caps"&gt;DDR4&lt;/span&gt;)
- &lt;span class="caps"&gt;USB&lt;/span&gt; 3.2 Gen2 (10 Gbps for external&amp;nbsp;storage)&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;N100&lt;/th&gt;
&lt;th&gt;Raspberry Pi 5&lt;/th&gt;
&lt;th&gt;Celeron J4125&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;4C/4T Alder Lake-N&lt;/td&gt;
&lt;td&gt;4C/4T &lt;span class="caps"&gt;ARM&lt;/span&gt; Cortex-A76&lt;/td&gt;
&lt;td&gt;4C/4T Gemini Lake&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;16GB&lt;/span&gt; &lt;span class="caps"&gt;DDR5&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;8GB&lt;/span&gt; &lt;span class="caps"&gt;LPDDR4X&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;8GB&lt;/span&gt; &lt;span class="caps"&gt;DDR4&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1x NVMe + 1x &lt;span class="caps"&gt;SATA&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;microSD + NVMe (via &lt;span class="caps"&gt;HAT&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;1x &lt;span class="caps"&gt;SATA&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Network&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2.5GbE (some models)&lt;/td&gt;
&lt;td&gt;1GbE&lt;/td&gt;
&lt;td&gt;1GbE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Idle Power&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;6–8W&lt;/td&gt;
&lt;td&gt;5–7W&lt;/td&gt;
&lt;td&gt;10–12W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Price&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$150–$200&lt;/td&gt;
&lt;td&gt;$80–$120&lt;/td&gt;
&lt;td&gt;$120–$150&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Core&amp;nbsp;Principles&lt;/h2&gt;
&lt;h3&gt;Principle 1: Right-Sizing Your&amp;nbsp;Workload&lt;/h3&gt;
&lt;p&gt;The N100 is not a powerhouse. It has 4 cores and no hyperthreading. The key to happiness is running lightweight services in &lt;span class="caps"&gt;LXC&lt;/span&gt; containers or Docker, not heavy VMs. Stick to 1–2 VMs maximum, or use &lt;span class="caps"&gt;LXC&lt;/span&gt; for&amp;nbsp;everything.&lt;/p&gt;
&lt;h3&gt;Principle 2: &lt;span class="caps"&gt;RAM&lt;/span&gt; Is the&amp;nbsp;Bottleneck&lt;/h3&gt;
&lt;p&gt;Most N100 mini PCs have a single &lt;span class="caps"&gt;SODIMM&lt;/span&gt; slot, limiting you to &lt;span class="caps"&gt;16GB&lt;/span&gt; &lt;span class="caps"&gt;DDR5&lt;/span&gt;. Some models (like the Minisforum &lt;span class="caps"&gt;UN100D&lt;/span&gt;) have dual slots for &lt;span class="caps"&gt;32GB&lt;/span&gt;. Plan your services to fit within &lt;span class="caps"&gt;12GB&lt;/span&gt; usable &lt;span class="caps"&gt;RAM&lt;/span&gt; (reserve &lt;span class="caps"&gt;4GB&lt;/span&gt; for the&amp;nbsp;host).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Typical &lt;span class="caps"&gt;RAM&lt;/span&gt; budget:&lt;/strong&gt;
- Proxmox host: &lt;span class="caps"&gt;2GB&lt;/span&gt;
- Pi-hole &lt;span class="caps"&gt;LXC&lt;/span&gt;: 0.&lt;span class="caps"&gt;5GB&lt;/span&gt;
- AdGuard Home &lt;span class="caps"&gt;LXC&lt;/span&gt;: 0.&lt;span class="caps"&gt;5GB&lt;/span&gt;
- Nextcloud &lt;span class="caps"&gt;LXC&lt;/span&gt;: &lt;span class="caps"&gt;2GB&lt;/span&gt;
- Jellyfin &lt;span class="caps"&gt;LXC&lt;/span&gt;: &lt;span class="caps"&gt;1GB&lt;/span&gt;
- Home Assistant &lt;span class="caps"&gt;LXC&lt;/span&gt;: &lt;span class="caps"&gt;1GB&lt;/span&gt;
- WireGuard &lt;span class="caps"&gt;LXC&lt;/span&gt;: 0.&lt;span class="caps"&gt;5GB&lt;/span&gt;
- Reserve: &lt;span class="caps"&gt;2GB&lt;/span&gt;
- &lt;strong&gt;Total: ~9.&lt;span class="caps"&gt;5GB&lt;/span&gt;&lt;/strong&gt; — fits comfortably in &lt;span class="caps"&gt;16GB&lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;Principle 3: Storage Strategy&amp;nbsp;Matters&lt;/h3&gt;
&lt;p&gt;With only 1–2 drive slots, you must choose wisely:
- &lt;strong&gt;Option A:&lt;/strong&gt; Single &lt;span class="caps"&gt;1TB&lt;/span&gt; NVMe for everything (simple, fast)
- &lt;strong&gt;Option B:&lt;/strong&gt; &lt;span class="caps"&gt;256GB&lt;/span&gt; NVMe for &lt;span class="caps"&gt;OS&lt;/span&gt; + &lt;span class="caps"&gt;1TB&lt;/span&gt; &lt;span class="caps"&gt;SATA&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt; for data (separation, easy replacement)
- &lt;strong&gt;Option C:&lt;/strong&gt; External &lt;span class="caps"&gt;USB&lt;/span&gt; 3.2 2.5&amp;#8221; &lt;span class="caps"&gt;HDD&lt;/span&gt; for bulk media (cheap,&amp;nbsp;slow)&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Applying This to Your&amp;nbsp;Homelab&lt;/h2&gt;
&lt;h3&gt;Homelab Setup&amp;nbsp;Example&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;The &amp;#8220;Essential Services&amp;#8221; N100 Build:&lt;/strong&gt;
1. &lt;strong&gt;Hardware:&lt;/strong&gt; Beelink Mini S12 Pro (N100, &lt;span class="caps"&gt;16GB&lt;/span&gt; &lt;span class="caps"&gt;DDR5&lt;/span&gt;, &lt;span class="caps"&gt;500GB&lt;/span&gt; NVMe)
2. &lt;strong&gt;&lt;span class="caps"&gt;OS&lt;/span&gt;:&lt;/strong&gt; Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; 8.2
3. &lt;strong&gt;Services:&lt;/strong&gt;
   - &lt;span class="caps"&gt;LXC&lt;/span&gt; 101: Pi-hole (&lt;span class="caps"&gt;DNS&lt;/span&gt; + ad blocking)
   - &lt;span class="caps"&gt;LXC&lt;/span&gt; 102: AdGuard Home (backup &lt;span class="caps"&gt;DNS&lt;/span&gt;)
   - &lt;span class="caps"&gt;LXC&lt;/span&gt; 103: Nextcloud (files + calendar)
   - &lt;span class="caps"&gt;LXC&lt;/span&gt; 104: Jellyfin (media server)
   - &lt;span class="caps"&gt;LXC&lt;/span&gt; 105: Home Assistant (home automation)
   - &lt;span class="caps"&gt;LXC&lt;/span&gt; 106: WireGuard (&lt;span class="caps"&gt;VPN&lt;/span&gt;)
4. &lt;strong&gt;Power:&lt;/strong&gt; 6–8W idle, 15–20W under&amp;nbsp;load&lt;/p&gt;
&lt;h3&gt;Practical&amp;nbsp;Steps&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Step 1: Install Proxmox on the N100&lt;/span&gt;
&lt;span class="c1"&gt;# Download ISO, flash to USB, install&lt;/span&gt;
&lt;span class="c1"&gt;# Use ext4 (not ZFS) since single drive + low RAM&lt;/span&gt;

&lt;span class="c1"&gt;# Step 2: Create LXCs from Debian 12 templates&lt;/span&gt;
&lt;span class="c1"&gt;# Download template first&lt;/span&gt;
pveam&lt;span class="w"&gt; &lt;/span&gt;update
pveam&lt;span class="w"&gt; &lt;/span&gt;download&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;debian-12-standard_12.2-1_amd64.tar.zst

&lt;span class="c1"&gt;# Create Pi-hole LXC&lt;/span&gt;
pct&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;101&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;local:vztmpl/debian-12-standard_12.2-1_amd64.tar.zst&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--hostname&lt;span class="w"&gt; &lt;/span&gt;pihole&lt;span class="w"&gt; &lt;/span&gt;--cores&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--memory&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;512&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--swap&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;512&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--net0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;eth0,bridge&lt;span class="o"&gt;=&lt;/span&gt;vmbr0,ip&lt;span class="o"&gt;=&lt;/span&gt;dhcp&lt;span class="w"&gt; &lt;/span&gt;--storage&lt;span class="w"&gt; &lt;/span&gt;local-lvm&lt;span class="w"&gt; &lt;/span&gt;--rootfs&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;

&lt;span class="c1"&gt;# Step 3: Install Docker inside an LXC&lt;/span&gt;
pct&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;102&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;local:vztmpl/debian-12-standard_12.2-1_amd64.tar.zst&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--hostname&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;--cores&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--memory&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4096&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--swap&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4096&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--net0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;eth0,bridge&lt;span class="o"&gt;=&lt;/span&gt;vmbr0,ip&lt;span class="o"&gt;=&lt;/span&gt;dhcp&lt;span class="w"&gt; &lt;/span&gt;--storage&lt;span class="w"&gt; &lt;/span&gt;local-lvm&lt;span class="w"&gt; &lt;/span&gt;--rootfs&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;32&lt;/span&gt;

&lt;span class="c1"&gt;# In the LXC console:&lt;/span&gt;
apt&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;docker.io&lt;span class="w"&gt; &lt;/span&gt;docker-compose

&lt;span class="c1"&gt;# Step 4: Deploy services with docker-compose&lt;/span&gt;
mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;/opt/services&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/opt/services

&lt;span class="c1"&gt;# Example: Jellyfin&lt;/span&gt;
mkdir&lt;span class="w"&gt; &lt;/span&gt;jellyfin&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;jellyfin
cat&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&amp;lt; &amp;#39;EOF&amp;#39; &amp;gt; docker-compose.yml&lt;/span&gt;
&lt;span class="s"&gt;services:&lt;/span&gt;
&lt;span class="s"&gt;  jellyfin:&lt;/span&gt;
&lt;span class="s"&gt;    image: jellyfin/jellyfin:latest&lt;/span&gt;
&lt;span class="s"&gt;    container_name: jellyfin&lt;/span&gt;
&lt;span class="s"&gt;    network_mode: host&lt;/span&gt;
&lt;span class="s"&gt;    volumes:&lt;/span&gt;
&lt;span class="s"&gt;      - ./config:/config&lt;/span&gt;
&lt;span class="s"&gt;      - ./cache:/cache&lt;/span&gt;
&lt;span class="s"&gt;      - /mnt/media:/media:ro&lt;/span&gt;
&lt;span class="s"&gt;    restart: unless-stopped&lt;/span&gt;
&lt;span class="s"&gt;EOF&lt;/span&gt;

docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Common Mistakes to&amp;nbsp;Avoid&lt;/h2&gt;
&lt;h3&gt;Mistake 1: Buying a Single-Channel &lt;span class="caps"&gt;8GB&lt;/span&gt;&amp;nbsp;Model&lt;/h3&gt;
&lt;p&gt;Some N100 mini PCs ship with &lt;span class="caps"&gt;8GB&lt;/span&gt; single-channel &lt;span class="caps"&gt;RAM&lt;/span&gt;. This is fine for 2–3 services, but you&amp;#8217;ll run out of memory quickly. Always buy &lt;span class="caps"&gt;16GB&lt;/span&gt;, or verify the &lt;span class="caps"&gt;SODIMM&lt;/span&gt; slot&amp;nbsp;count.&lt;/p&gt;
&lt;h3&gt;Mistake 2: Enabling &lt;span class="caps"&gt;ZFS&lt;/span&gt; on a Single&amp;nbsp;Drive&lt;/h3&gt;
&lt;p&gt;&lt;span class="caps"&gt;ZFS&lt;/span&gt; is amazing, but on a single NVMe with &lt;span class="caps"&gt;16GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, it causes performance issues and consumes &lt;span class="caps"&gt;RAM&lt;/span&gt; for &lt;span class="caps"&gt;ARC&lt;/span&gt;. Use ext4 or xfs for the host, and pass directories to&amp;nbsp;containers.&lt;/p&gt;
&lt;h3&gt;Mistake 3: Running Windows&amp;nbsp;VMs&lt;/h3&gt;
&lt;p&gt;The N100 can run a Windows &lt;span class="caps"&gt;VM&lt;/span&gt;, but it will consume 2–4 cores and 4–&lt;span class="caps"&gt;8GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, leaving nothing for other services. If you need Windows, use a dedicated host or a cloud&amp;nbsp;instance.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;The Intel N100 mini &lt;span class="caps"&gt;PC&lt;/span&gt; is the best entry-level homelab server in 2026. It is cheap, silent, efficient, and capable of running 6–10 essential services in &lt;span class="caps"&gt;LXC&lt;/span&gt; containers. While it won&amp;#8217;t replace a rack server for heavy virtualization, it is the perfect starting point for 80% of new&amp;nbsp;homelabbers.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Read our &lt;a href="best-mini-pc-for-homelab"&gt;best mini &lt;span class="caps"&gt;PC&lt;/span&gt; for homelab guide&lt;/a&gt; for specific model&amp;nbsp;recommendations&lt;/li&gt;
&lt;li&gt;Read our &lt;a href="proxmox-beginner-guide-2026"&gt;Proxmox beginner guide&lt;/a&gt; for your first hypervisor&amp;nbsp;setup&lt;/li&gt;
&lt;li&gt;Read our &lt;a href="low-power-homelab-server-build"&gt;low-power homelab build guide&lt;/a&gt; for power tuning&amp;nbsp;tips&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Beelink Mini S12 Pro&lt;/strong&gt;: Amazon affiliate for entry-level&amp;nbsp;buyers&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Minisforum &lt;span class="caps"&gt;UN100D&lt;/span&gt;&lt;/strong&gt;: Official store affiliate for 2.5GbE&amp;nbsp;model&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Samsung 990 &lt;span class="caps"&gt;EVO&lt;/span&gt;&lt;/strong&gt;: NVMe &lt;span class="caps"&gt;SSD&lt;/span&gt;&amp;nbsp;recommendation&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Crucial &lt;span class="caps"&gt;16GB&lt;/span&gt; &lt;span class="caps"&gt;DDR5&lt;/span&gt; &lt;span class="caps"&gt;SODIMM&lt;/span&gt;&lt;/strong&gt;: &lt;span class="caps"&gt;RAM&lt;/span&gt; upgrade&amp;nbsp;link&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;what-is&lt;/code&gt; → &lt;code&gt;best-mini-pc-for-homelab&lt;/code&gt; for model&amp;nbsp;comparisons&lt;/li&gt;
&lt;li&gt;&lt;code&gt;principle-2&lt;/code&gt; → &lt;code&gt;low-power-homelab-server-build&lt;/code&gt; for &lt;span class="caps"&gt;RAM&lt;/span&gt;&amp;nbsp;optimization&lt;/li&gt;
&lt;li&gt;&lt;code&gt;practical-steps&lt;/code&gt; → &lt;code&gt;docker-compose-for-beginners&lt;/code&gt; for Docker&amp;nbsp;basics&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;proxmox-beginner-guide-2026&lt;/code&gt; for hypervisor&amp;nbsp;setup&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] Are you running an N100 homelab? Share your setup and power readings&amp;nbsp;below!&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for weekly mini &lt;span class="caps"&gt;PC&lt;/span&gt; reviews and homelab build&amp;nbsp;guides.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Guides"/><category term="intel n100"/><category term="mini pc"/><category term="homelab"/><category term="low power"/><category term="docker"/><category term="proxmox"/><category term="entry level server"/></entry><entry><title>Low-Power Homelab Server Build Guide 2026: Under 15W Idle</title><link href="https://steadypub.com/2026/06/low-power-homelab-server-build/" rel="alternate"/><published>2026-06-05T00:00:00+07:00</published><updated>2026-06-05T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/low-power-homelab-server-build/</id><summary type="html">&lt;p&gt;Build a power-efficient homelab server that idles under 15W. Step-by-step guide covering Intel N100/N305 hardware, Proxmox or Docker setup, power tuning, and real consumption&amp;nbsp;numbers.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~15 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelabbers wanting 24/7 operation without high electricity&amp;nbsp;bills&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is a Low-Power Homelab&amp;nbsp;Server?&lt;/h2&gt;
&lt;p&gt;A low-power homelab server is a virtualization or container host optimized for minimal electricity consumption. Unlike used rack servers that draw 100–200W, a low-power build targets &lt;strong&gt;6–15W idle&lt;/strong&gt; while still running multiple VMs, Docker containers, and&amp;nbsp;services.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why it matters:&lt;/strong&gt;
- &lt;strong&gt;Cost&lt;/strong&gt;: A 15W server costs ~$15/year in electricity vs. $130+/year for a 120W rack server
- &lt;strong&gt;Noise&lt;/strong&gt;: Fanless or near-silent operation
- &lt;strong&gt;Heat&lt;/strong&gt;: Minimal impact on room temperature
- &lt;strong&gt;24/7 viability&lt;/strong&gt;: Run without guilt or cost&amp;nbsp;anxiety&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Real-world power draw&amp;nbsp;comparison:&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Device&lt;/th&gt;
&lt;th&gt;Idle Power&lt;/th&gt;
&lt;th&gt;Load Power&lt;/th&gt;
&lt;th&gt;Annual Cost (at $0.12/kWh)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Intel N100 mini &lt;span class="caps"&gt;PC&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;6–8W&lt;/td&gt;
&lt;td&gt;15–20W&lt;/td&gt;
&lt;td&gt;~$8–$12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Intel N305 mini &lt;span class="caps"&gt;PC&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;10–12W&lt;/td&gt;
&lt;td&gt;25–30W&lt;/td&gt;
&lt;td&gt;~$13–$16&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dell R720 (dual Xeon)&lt;/td&gt;
&lt;td&gt;120–150W&lt;/td&gt;
&lt;td&gt;250–350W&lt;/td&gt;
&lt;td&gt;~$130–$160&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ryzen 5 desktop&lt;/td&gt;
&lt;td&gt;60–80W&lt;/td&gt;
&lt;td&gt;150–200W&lt;/td&gt;
&lt;td&gt;~$65–$85&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Raspberry Pi 5&lt;/td&gt;
&lt;td&gt;5–7W&lt;/td&gt;
&lt;td&gt;10–15W&lt;/td&gt;
&lt;td&gt;~$7–$10&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;h3&gt;Hardware&amp;nbsp;Requirements&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Minimum&lt;/th&gt;
&lt;th&gt;Recommended&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Intel N100 / &lt;span class="caps"&gt;AMD&lt;/span&gt; Ryzen Embedded&lt;/td&gt;
&lt;td&gt;Intel N305 / &lt;span class="caps"&gt;AMD&lt;/span&gt; Ryzen 5 7520U&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;8GB&lt;/span&gt; &lt;span class="caps"&gt;DDR4&lt;/span&gt;/&lt;span class="caps"&gt;DDR5&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;16GB&lt;/span&gt; &lt;span class="caps"&gt;DDR5&lt;/span&gt; (dual channel)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;128GB&lt;/span&gt; &lt;span class="caps"&gt;SATA&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;256GB&lt;/span&gt; NVMe &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Network&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1x 1GbE&lt;/td&gt;
&lt;td&gt;1x 2.5GbE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Power&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;19V/12V &lt;span class="caps"&gt;DC&lt;/span&gt; adapter&lt;/td&gt;
&lt;td&gt;65W &lt;span class="caps"&gt;PD&lt;/span&gt; or barrel adapter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;USB&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2x &lt;span class="caps"&gt;USB&lt;/span&gt; 3.0 (for installer/backup)&lt;/td&gt;
&lt;td&gt;3x &lt;span class="caps"&gt;USB&lt;/span&gt; (including &lt;span class="caps"&gt;USB&lt;/span&gt;-C)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Software&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; 8.x &lt;span class="caps"&gt;ISO&lt;/span&gt; or Debian 12 +&amp;nbsp;Docker&lt;/li&gt;
&lt;li&gt;BalenaEtcher or Rufus (for &lt;span class="caps"&gt;USB&lt;/span&gt;&amp;nbsp;installer)&lt;/li&gt;
&lt;li&gt;Kill-a-Watt meter or smart plug (to measure&amp;nbsp;power)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Knowledge&amp;nbsp;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Basic Linux command&amp;nbsp;line&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;BIOS&lt;/span&gt;/&lt;span class="caps"&gt;UEFI&lt;/span&gt;&amp;nbsp;navigation&lt;/li&gt;
&lt;li&gt;Docker or virtualization&amp;nbsp;concepts&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Choose and Configure Your&amp;nbsp;Hardware&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Select a mini &lt;span class="caps"&gt;PC&lt;/span&gt; platform with good power efficiency and virtualization&amp;nbsp;support.&lt;/p&gt;
&lt;h3&gt;Recommended Platforms for&amp;nbsp;2026&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;TDP&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Idle Power&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt; Max&lt;/th&gt;
&lt;th&gt;2.5GbE&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Beelink Mini S12 Pro&lt;/td&gt;
&lt;td&gt;N100&lt;/td&gt;
&lt;td&gt;6W&lt;/td&gt;
&lt;td&gt;6–7W&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;16GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;$150&lt;/td&gt;
&lt;td&gt;Entry Docker host&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Minisforum &lt;span class="caps"&gt;UN100D&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;N100&lt;/td&gt;
&lt;td&gt;6W&lt;/td&gt;
&lt;td&gt;6–8W&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;16GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;$180&lt;/td&gt;
&lt;td&gt;24/7 &lt;span class="caps"&gt;NAS&lt;/span&gt; + containers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GMKtec NucBox M5&lt;/td&gt;
&lt;td&gt;N305&lt;/td&gt;
&lt;td&gt;15W&lt;/td&gt;
&lt;td&gt;10–12W&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;32GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;$250&lt;/td&gt;
&lt;td&gt;5–10 VMs on Proxmox&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Minisforum &lt;span class="caps"&gt;MS&lt;/span&gt;-01&lt;/td&gt;
&lt;td&gt;i9-12900H&lt;/td&gt;
&lt;td&gt;45W&lt;/td&gt;
&lt;td&gt;20–25W&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;64GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;10GbE&lt;/td&gt;
&lt;td&gt;$600&lt;/td&gt;
&lt;td&gt;All-rounder with 10GbE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Beelink &lt;span class="caps"&gt;SER5&lt;/span&gt; Pro&lt;/td&gt;
&lt;td&gt;Ryzen 7 5800H&lt;/td&gt;
&lt;td&gt;45W&lt;/td&gt;
&lt;td&gt;15–18W&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;64GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;$350&lt;/td&gt;
&lt;td&gt;Higher &lt;span class="caps"&gt;CPU&lt;/span&gt; workloads&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Order the mini &lt;span class="caps"&gt;PC&lt;/span&gt;&lt;/strong&gt; with at least &lt;span class="caps"&gt;16GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; and NVMe&amp;nbsp;storage.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Verify virtualization support&lt;/strong&gt; in the product specs (Intel &lt;span class="caps"&gt;VT&lt;/span&gt;-x/&lt;span class="caps"&gt;VT&lt;/span&gt;-d or &lt;span class="caps"&gt;AMD&lt;/span&gt;-V/&lt;span class="caps"&gt;IOMMU&lt;/span&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Buy a smart plug&lt;/strong&gt; (&lt;span class="caps"&gt;TP&lt;/span&gt;-Link Kasa &lt;span class="caps"&gt;EP25&lt;/span&gt;, ~$15) to monitor power&amp;nbsp;consumption.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# After OS install, verify virtualization support&lt;/span&gt;
egrep&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;(vmx|svm)&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/proc/cpuinfo
&lt;span class="c1"&gt;# Output &amp;gt; 0 = supported&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 2: Install Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; (Lightweight&amp;nbsp;Virtualization)&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Install a Type-1 hypervisor for running multiple VMs and LXCs with minimal&amp;nbsp;overhead.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Download Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; 8.2 &lt;span class="caps"&gt;ISO&lt;/span&gt;&lt;/strong&gt; from&amp;nbsp;proxmox.com.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flash to &lt;span class="caps"&gt;USB&lt;/span&gt;&lt;/strong&gt; with&amp;nbsp;BalenaEtcher.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Boot the mini &lt;span class="caps"&gt;PC&lt;/span&gt; from &lt;span class="caps"&gt;USB&lt;/span&gt;&lt;/strong&gt; and install&amp;nbsp;Proxmox.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;During install,&amp;nbsp;choose:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Filesystem: &lt;code&gt;ext4&lt;/code&gt; (lower overhead than &lt;span class="caps"&gt;ZFS&lt;/span&gt; for single-drive&amp;nbsp;setups)&lt;/li&gt;
&lt;li&gt;Hostname: &lt;code&gt;pve-lowpower&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Network: static &lt;span class="caps"&gt;IP&lt;/span&gt;&amp;nbsp;(e.g., &lt;code&gt;192.168.1.10/24&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Post-install: disable high-availability services (not needed for single-node)&lt;/span&gt;
systemctl&lt;span class="w"&gt; &lt;/span&gt;disable&lt;span class="w"&gt; &lt;/span&gt;pve-ha-lrm&lt;span class="w"&gt; &lt;/span&gt;pve-ha-crm&lt;span class="w"&gt; &lt;/span&gt;corosync

&lt;span class="c1"&gt;# Disable enterprise repo (if no subscription)&lt;/span&gt;
sed&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;s/^deb/#deb/g&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/apt/sources.list.d/pve-enterprise.list

&lt;span class="c1"&gt;# Add no-subscription repo&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;deb http://download.proxmox.com/debian/pve bookworm pve-no-subscription&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/apt/sources.list.d/pve-no-subscription.list
apt&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;dist-upgrade&lt;span class="w"&gt; &lt;/span&gt;-y
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 3: &lt;span class="caps"&gt;CPU&lt;/span&gt; Power Management&amp;nbsp;Tuning&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Reduce idle power by enabling &lt;span class="caps"&gt;CPU&lt;/span&gt; power states and limiting peak&amp;nbsp;frequency.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Install powertop and cpupower&lt;/span&gt;
apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;linux-cpupower&lt;span class="w"&gt; &lt;/span&gt;powertop

&lt;span class="c1"&gt;# Check current CPU governor&lt;/span&gt;
cpupower&lt;span class="w"&gt; &lt;/span&gt;frequency-info

&lt;span class="c1"&gt;# Set powersave governor (Intel N100/N305)&lt;/span&gt;
cpupower&lt;span class="w"&gt; &lt;/span&gt;frequency-set&lt;span class="w"&gt; &lt;/span&gt;-g&lt;span class="w"&gt; &lt;/span&gt;powersave

&lt;span class="c1"&gt;# Make it persistent&lt;/span&gt;
cat&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&amp;lt; &amp;#39;EOF&amp;#39; &amp;gt; /etc/systemd/system/cpu-powersave.service&lt;/span&gt;
&lt;span class="s"&gt;[Unit]&lt;/span&gt;
&lt;span class="s"&gt;Description=Set CPU governor to powersave&lt;/span&gt;
&lt;span class="s"&gt;After=multi-user.target&lt;/span&gt;

&lt;span class="s"&gt;[Service]&lt;/span&gt;
&lt;span class="s"&gt;Type=oneshot&lt;/span&gt;
&lt;span class="s"&gt;ExecStart=/usr/bin/cpupower frequency-set -g powersave&lt;/span&gt;

&lt;span class="s"&gt;[Install]&lt;/span&gt;
&lt;span class="s"&gt;WantedBy=multi-user.target&lt;/span&gt;
&lt;span class="s"&gt;EOF&lt;/span&gt;

systemctl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--now&lt;span class="w"&gt; &lt;/span&gt;cpu-powersave.service

&lt;span class="c1"&gt;# Tune with powertop (run for 60 seconds, then apply)&lt;/span&gt;
powertop&lt;span class="w"&gt; &lt;/span&gt;--calibrate
powertop&lt;span class="w"&gt; &lt;/span&gt;--auto-tune

&lt;span class="c1"&gt;# Make powertop auto-tune persistent&lt;/span&gt;
cat&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&amp;lt; &amp;#39;EOF&amp;#39; &amp;gt; /etc/systemd/system/powertop.service&lt;/span&gt;
&lt;span class="s"&gt;[Unit]&lt;/span&gt;
&lt;span class="s"&gt;Description=Powertop auto-tune&lt;/span&gt;
&lt;span class="s"&gt;After=multi-user.target&lt;/span&gt;

&lt;span class="s"&gt;[Service]&lt;/span&gt;
&lt;span class="s"&gt;Type=oneshot&lt;/span&gt;
&lt;span class="s"&gt;ExecStart=/usr/sbin/powertop --auto-tune&lt;/span&gt;

&lt;span class="s"&gt;[Install]&lt;/span&gt;
&lt;span class="s"&gt;WantedBy=multi-user.target&lt;/span&gt;
&lt;span class="s"&gt;EOF&lt;/span&gt;

systemctl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--now&lt;span class="w"&gt; &lt;/span&gt;powertop.service
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; Idle power should drop 2–5W after&amp;nbsp;tuning.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 4: Enable Hardware-Accelerated Transcoding&amp;nbsp;(Optional)&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;If running Jellyfin or Plex, use Intel Quick Sync to reduce &lt;span class="caps"&gt;CPU&lt;/span&gt; load and power&amp;nbsp;draw.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Install Intel GPU drivers on Proxmox host&lt;/span&gt;
apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;intel-media-va-driver-non-free&lt;span class="w"&gt; &lt;/span&gt;vainfo

&lt;span class="c1"&gt;# Verify Quick Sync&lt;/span&gt;
vainfo&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;VAEntrypointVLD&amp;quot;&lt;/span&gt;

&lt;span class="c1"&gt;# In a Jellyfin LXC, mount the GPU&lt;/span&gt;
&lt;span class="c1"&gt;# Add to /etc/pve/lxc/XXX.conf:&lt;/span&gt;
&lt;span class="c1"&gt;# lxc.cgroup2.devices.allow: c 226:0 rwm&lt;/span&gt;
&lt;span class="c1"&gt;# lxc.cgroup2.devices.allow: c 226:128 rwm&lt;/span&gt;
&lt;span class="c1"&gt;# lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 5: Measure and Optimize Power&amp;nbsp;Consumption&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Establish a baseline and find remaining power&amp;nbsp;drains.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Install smartmontools to check disk power&lt;/span&gt;
apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;smartmontools

&lt;span class="c1"&gt;# Check disk power state&lt;/span&gt;
smartctl&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;/dev/nvme0

&lt;span class="c1"&gt;# Enable SATA link power management (if using SATA SSD)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;min_power&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/sys/class/scsi_host/host*/link_power_management_policy

&lt;span class="c1"&gt;# Disable HDMI output if headless (saves ~1W)&lt;/span&gt;
cat&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&amp;lt; &amp;#39;EOF&amp;#39; &amp;gt; /etc/modprobe.d/blacklist-hdmi.conf&lt;/span&gt;
&lt;span class="s"&gt;blacklist snd_hda_intel&lt;/span&gt;
&lt;span class="s"&gt;EOF&lt;/span&gt;

&lt;span class="c1"&gt;# Check power consumption with powerstat (if available)&lt;/span&gt;
apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;powerstat
powerstat&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-R&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;60&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Measurement checklist:&lt;/strong&gt;
- [ ] Kill-a-Watt or smart plug showing &amp;lt; 15W idle
- [ ] All VMs/LXCs running without &lt;span class="caps"&gt;CPU&lt;/span&gt; spikes
- [ ] Network responding (ping 192.168.1.10)
- [ ] Storage accessible (TrueNAS/Nextcloud&amp;nbsp;functional)&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Use &lt;span class="caps"&gt;LXC&lt;/span&gt; Over&amp;nbsp;VMs&lt;/h3&gt;
&lt;p&gt;&lt;span class="caps"&gt;LXC&lt;/span&gt; containers share the host kernel and use 10–20% less &lt;span class="caps"&gt;RAM&lt;/span&gt; and &lt;span class="caps"&gt;CPU&lt;/span&gt; than VMs. For Docker workloads, run a single &lt;span class="caps"&gt;LXC&lt;/span&gt; with Docker instead of multiple&amp;nbsp;VMs.&lt;/p&gt;
&lt;h3&gt;Tip 2: Disable Unnecessary&amp;nbsp;Services&lt;/h3&gt;
&lt;p&gt;On Proxmox single-node setups, disable:&amp;nbsp;- &lt;code&gt;pve-ha-lrm&lt;/code&gt;, &lt;code&gt;pve-ha-crm&lt;/code&gt;, &lt;code&gt;corosync&lt;/code&gt; (clustering)&amp;nbsp;- &lt;code&gt;pve-firewall&lt;/code&gt; (if using external firewall)&amp;nbsp;- &lt;code&gt;spiceproxy&lt;/code&gt; (if not using &lt;span class="caps"&gt;SPICE&lt;/span&gt;)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;disable&lt;span class="w"&gt; &lt;/span&gt;pve-ha-lrm&lt;span class="w"&gt; &lt;/span&gt;pve-ha-crm&lt;span class="w"&gt; &lt;/span&gt;corosync
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 3: Schedule Heavy&amp;nbsp;Tasks&lt;/h3&gt;
&lt;p&gt;Run backups, &lt;span class="caps"&gt;ZFS&lt;/span&gt; scrubs, and antivirus scans during off-peak hours when solar power is available or time-of-use rates are&amp;nbsp;cheaper.&lt;/p&gt;
&lt;h3&gt;Tip 4: Use a Single NVMe&amp;nbsp;Drive&lt;/h3&gt;
&lt;p&gt;A single NVMe &lt;span class="caps"&gt;SSD&lt;/span&gt; uses 3–7W. Adding &lt;span class="caps"&gt;SATA&lt;/span&gt; SSDs or HDDs increases power by 2–5W each. For ultra-low power, stick to one &lt;span class="caps"&gt;1TB&lt;/span&gt;&amp;nbsp;NVMe.&lt;/p&gt;
&lt;h3&gt;Tip 5: Consider &lt;span class="caps"&gt;ARM&lt;/span&gt; for Extreme Low&amp;nbsp;Power&lt;/h3&gt;
&lt;p&gt;If x86 compatibility isn&amp;#8217;t needed, the Raspberry Pi 5 (&lt;span class="caps"&gt;8GB&lt;/span&gt;) or Orange Pi 5 Plus can run Docker at 5–7W. The trade-off is weaker x86 app support and no&amp;nbsp;Proxmox.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Troubleshooting Common&amp;nbsp;Issues&lt;/h2&gt;
&lt;h3&gt;Problem 1: High Idle Power&amp;nbsp;(25W+)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Cause:&lt;/strong&gt; &lt;span class="caps"&gt;CPU&lt;/span&gt; governor set to performance, or &lt;span class="caps"&gt;GPU&lt;/span&gt; not&amp;nbsp;sleeping.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Verify governor&lt;/span&gt;
cat&lt;span class="w"&gt; &lt;/span&gt;/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
&lt;span class="c1"&gt;# Should say &amp;quot;powersave&amp;quot;&lt;/span&gt;

&lt;span class="c1"&gt;# Check GPU power state&lt;/span&gt;
cat&lt;span class="w"&gt; &lt;/span&gt;/sys/kernel/debug/dri/0/i915_frequency_info
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Problem 2: Proxmox &lt;span class="caps"&gt;VM&lt;/span&gt; Performance Is&amp;nbsp;Sluggish&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Cause:&lt;/strong&gt; N100 has only 4 cores/4 threads. Over-allocating vCPUs causes&amp;nbsp;contention.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Limit VMs to 1–2 vCPUs and use &lt;span class="caps"&gt;LXC&lt;/span&gt; for lightweight&amp;nbsp;services.&lt;/p&gt;
&lt;h3&gt;Problem 3: Network Drops After Power&amp;nbsp;Saving&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Cause:&lt;/strong&gt; Aggressive PCIe power&amp;nbsp;management.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;on&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/sys/class/net/eth0/device/power/control
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;A low-power homelab build around the Intel N100 or N305 can deliver real server capabilities at under 15W idle. With Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;, &lt;span class="caps"&gt;CPU&lt;/span&gt; power management tuning, and &lt;span class="caps"&gt;LXC&lt;/span&gt; containers, you can run 10–15 services for less than $15/year in&amp;nbsp;electricity.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Install your first &lt;span class="caps"&gt;LXC&lt;/span&gt; container (Nextcloud, Jellyfin, or&amp;nbsp;Pi-hole)&lt;/li&gt;
&lt;li&gt;Set up automated backups with Proxmox Backup&amp;nbsp;Server&lt;/li&gt;
&lt;li&gt;Monitor power with a smart plug and log trends in Home&amp;nbsp;Assistant&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Beelink Mini S12 Pro&lt;/strong&gt;: Amazon affiliate&amp;nbsp;link&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Minisforum &lt;span class="caps"&gt;UN100D&lt;/span&gt;&lt;/strong&gt;: Official store&amp;nbsp;affiliate&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;TP&lt;/span&gt;-Link Kasa &lt;span class="caps"&gt;EP25&lt;/span&gt;&lt;/strong&gt;: Smart plug for power&amp;nbsp;monitoring&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Samsung 990 &lt;span class="caps"&gt;EVO&lt;/span&gt;&lt;/strong&gt;: NVMe &lt;span class="caps"&gt;SSD&lt;/span&gt;&amp;nbsp;recommendation&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;prerequisites&lt;/code&gt; → &lt;code&gt;best-mini-pc-for-homelab&lt;/code&gt; for hardware&amp;nbsp;selection&lt;/li&gt;
&lt;li&gt;&lt;code&gt;step-2&lt;/code&gt; → &lt;code&gt;proxmox-beginner-guide-2026&lt;/code&gt; for Proxmox&amp;nbsp;basics&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tip-4&lt;/code&gt; → &lt;code&gt;docker-compose-for-beginners&lt;/code&gt; for container&amp;nbsp;setup&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;proxmox-backup-server&lt;/code&gt; for backup&amp;nbsp;setup&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] What&amp;#8217;s your homelab power draw? Share your kill-a-watt readings&amp;nbsp;below!&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for monthly power-efficient build guides and mini &lt;span class="caps"&gt;PC&lt;/span&gt;&amp;nbsp;reviews.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Tutorials"/><category term="low power homelab"/><category term="mini pc server"/><category term="intel n100"/><category term="power efficient"/><category term="docker"/><category term="proxmox"/><category term="green homelab"/></entry><entry><title>Mini PC Home Server 2025: The Ultimate Guide for Self-Hosters</title><link href="https://steadypub.com/2026/06/mini-pc-home-server-2025/" rel="alternate"/><published>2026-06-05T00:00:00+07:00</published><updated>2026-06-05T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/mini-pc-home-server-2025/</id><summary type="html">&lt;p&gt;Why mini PCs have become the dominant homelab server form factor in 2025. Covers Intel N100, N305, &lt;span class="caps"&gt;AMD&lt;/span&gt; options, &lt;span class="caps"&gt;RAM&lt;/span&gt; limits, power draw, and real-world Docker&amp;nbsp;performance.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~16 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Anyone building a homelab on a mini &lt;span class="caps"&gt;PC&lt;/span&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is a Mini &lt;span class="caps"&gt;PC&lt;/span&gt; Home&amp;nbsp;Server?&lt;/h2&gt;
&lt;h3&gt;What Exactly Is&amp;nbsp;It?&lt;/h3&gt;
&lt;p&gt;A mini &lt;span class="caps"&gt;PC&lt;/span&gt; home server is a compact, low-power x86 computer that runs 24/7 to host services like Docker containers, file storage, media streaming, and network services. Unlike traditional rack servers or full-size desktops, mini PCs are silent, draw under 15W at idle, and fit on a bookshelf. In 2025, they have become the default choice for new homelab&amp;nbsp;builds.&lt;/p&gt;
&lt;h3&gt;A Brief&amp;nbsp;History&lt;/h3&gt;
&lt;p&gt;Mini PCs evolved from Intel&amp;#8217;s &lt;span class="caps"&gt;NUC&lt;/span&gt; (Next Unit of Computing) line, introduced in 2013. Early NUCs were expensive and limited. In 2023–2024, Chinese manufacturers (Beelink, Minisforum, GMKtec) flooded the market with cheap, capable mini PCs based on Intel&amp;#8217;s Alder Lake-N and &lt;span class="caps"&gt;AMD&lt;/span&gt;&amp;#8217;s Ryzen U-series chips. The Intel N100 — a 6W quad-core processor — became the &amp;#8220;sweet spot&amp;#8221; for homelabbers, offering enough performance for 10–15 Docker containers at under&amp;nbsp;$150.&lt;/p&gt;
&lt;h3&gt;Why It Matters&amp;nbsp;Today&lt;/h3&gt;
&lt;p&gt;Electricity costs are rising. A full-size server drawing 100W+ costs $100–$200/year in power. A mini &lt;span class="caps"&gt;PC&lt;/span&gt; drawing 10W costs $15–$30/year. The performance gap has closed: modern mini PCs handle 4K transcoding, multiple VMs, and fast NVMe storage. For most homelabbers, a mini &lt;span class="caps"&gt;PC&lt;/span&gt; is the rational&amp;nbsp;choice.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why It&amp;nbsp;Matters&lt;/h2&gt;
&lt;h3&gt;Benefit 1: Extreme Power&amp;nbsp;Efficiency&lt;/h3&gt;
&lt;p&gt;A mini &lt;span class="caps"&gt;PC&lt;/span&gt; with an Intel N100 idles at 4–6W and peaks at 15–20W. Under full load (Proxmox + 5 VMs), it draws 25–35W. Compare this to a Dell R720 rack server: 80–150W idle, 300W+ under load. Over 3 years, the power savings alone pay for the mini &lt;span class="caps"&gt;PC&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;Benefit 2: Silent&amp;nbsp;Operation&lt;/h3&gt;
&lt;p&gt;Mini PCs are fan-cooled but use small, low-&lt;span class="caps"&gt;RPM&lt;/span&gt; fans. Most produce under 25 dB at idle — quieter than a refrigerator. This makes them ideal for living rooms, offices, or apartments where rack servers are&amp;nbsp;impossible.&lt;/p&gt;
&lt;h3&gt;Benefit 3: Low Cost of&amp;nbsp;Entry&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Mini &lt;span class="caps"&gt;PC&lt;/span&gt; Build&lt;/th&gt;
&lt;th&gt;Rack Server Build&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;/Motherboard&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Intel N100 (integrated)&lt;/td&gt;
&lt;td&gt;$200+ used Xeon&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;16 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;DDR4&lt;/span&gt; &lt;span class="caps"&gt;SODIMM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$100+ &lt;span class="caps"&gt;DDR4&lt;/span&gt; &lt;span class="caps"&gt;ECC&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;512 &lt;span class="caps"&gt;GB&lt;/span&gt; NVMe&lt;/td&gt;
&lt;td&gt;$100+ enterprise &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Case/&lt;span class="caps"&gt;PSU&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Integrated&lt;/td&gt;
&lt;td&gt;$200+ rack case + &lt;span class="caps"&gt;PSU&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$150–250&lt;/td&gt;
&lt;td&gt;$600–1,000+&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Core&amp;nbsp;Principles&lt;/h2&gt;
&lt;hr&gt;
&lt;h2&gt;Principle 1: &lt;span class="caps"&gt;CPU&lt;/span&gt; Selection Is&amp;nbsp;Critical&lt;/h2&gt;
&lt;h3&gt;Explanation&lt;/h3&gt;
&lt;p&gt;Not all mini &lt;span class="caps"&gt;PC&lt;/span&gt; CPUs are created equal. For homelab use, you need:
- &lt;strong&gt;Enough cores:&lt;/strong&gt; 4+ cores for Proxmox + Docker.
- &lt;strong&gt;QuickSync:&lt;/strong&gt; Intel&amp;#8217;s integrated &lt;span class="caps"&gt;GPU&lt;/span&gt; for hardware transcoding (Jellyfin, Immich).
- &lt;strong&gt;Low &lt;span class="caps"&gt;TDP&lt;/span&gt;:&lt;/strong&gt; Under 15W for 24/7 power efficiency.
- &lt;strong&gt;x86 architecture:&lt;/strong&gt; Avoid &lt;span class="caps"&gt;ARM&lt;/span&gt; mini PCs (e.g., Raspberry Pi) unless you enjoy compiling&amp;nbsp;containers.&lt;/p&gt;
&lt;h3&gt;Example&lt;/h3&gt;
&lt;p&gt;The Intel N100 has 4 cores, 6W &lt;span class="caps"&gt;TDP&lt;/span&gt;, and Intel &lt;span class="caps"&gt;UHD&lt;/span&gt; Graphics with QuickSync. It can transcode 4–5 1080p streams in Jellyfin simultaneously. The &lt;span class="caps"&gt;AMD&lt;/span&gt; Ryzen 7 &lt;span class="caps"&gt;7840HS&lt;/span&gt; has 8 cores, 35W &lt;span class="caps"&gt;TDP&lt;/span&gt;, and &lt;span class="caps"&gt;RDNA3&lt;/span&gt; graphics — overkill for most homelabs but excellent for &lt;span class="caps"&gt;GPU&lt;/span&gt;&amp;nbsp;passthrough.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Cores&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;TDP&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;QuickSync&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Intel N100&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;6W&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Entry-level Docker/Proxmox&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Intel N200&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;6W&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Slightly faster N100&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Intel N305&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;15W&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Proxmox with 4–5 VMs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Intel i3-N305&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;15W&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Same as N305, different branding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;AMD&lt;/span&gt; Ryzen 7 &lt;span class="caps"&gt;7840HS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;35W&lt;/td&gt;
&lt;td&gt;❌ (no QuickSync)&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;GPU&lt;/span&gt; passthrough, high &lt;span class="caps"&gt;CPU&lt;/span&gt; load&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;AMD&lt;/span&gt; Ryzen 9 &lt;span class="caps"&gt;7940HS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;35W&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Maximum performance mini &lt;span class="caps"&gt;PC&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Principle 2: &lt;span class="caps"&gt;RAM&lt;/span&gt; and Storage&amp;nbsp;Limits&lt;/h2&gt;
&lt;h3&gt;Explanation&lt;/h3&gt;
&lt;p&gt;Mini PCs use &lt;span class="caps"&gt;SODIMM&lt;/span&gt; (laptop) &lt;span class="caps"&gt;RAM&lt;/span&gt;, typically limited to 16–64 &lt;span class="caps"&gt;GB&lt;/span&gt; depending on the model. Most N100-based mini PCs have a single &lt;span class="caps"&gt;RAM&lt;/span&gt; slot, limiting you to 16–32 &lt;span class="caps"&gt;GB&lt;/span&gt;. The N305 models often have dual &lt;span class="caps"&gt;SODIMM&lt;/span&gt; slots, supporting up to 64 &lt;span class="caps"&gt;GB&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Storage is usually 1–2 M.2 NVMe slots plus 1–2 &lt;span class="caps"&gt;SATA&lt;/span&gt; ports. For a homelab:
- &lt;strong&gt;&lt;span class="caps"&gt;OS&lt;/span&gt;/Containers:&lt;/strong&gt; 512 &lt;span class="caps"&gt;GB&lt;/span&gt;–1 &lt;span class="caps"&gt;TB&lt;/span&gt; NVMe (fast, low latency)
- &lt;strong&gt;Media/Backups:&lt;/strong&gt; 2.5&amp;#8221; &lt;span class="caps"&gt;SATA&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt; or external &lt;span class="caps"&gt;USB&lt;/span&gt; drive (cheap,&amp;nbsp;large)&lt;/p&gt;
&lt;h3&gt;Example&lt;/h3&gt;
&lt;p&gt;A typical mini &lt;span class="caps"&gt;PC&lt;/span&gt; homelab setup:
- &lt;strong&gt;&lt;span class="caps"&gt;OS&lt;/span&gt;:&lt;/strong&gt; Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; on 256 &lt;span class="caps"&gt;GB&lt;/span&gt; NVMe
- &lt;strong&gt;&lt;span class="caps"&gt;VM&lt;/span&gt; storage:&lt;/strong&gt; 512 &lt;span class="caps"&gt;GB&lt;/span&gt; NVMe for &lt;span class="caps"&gt;VM&lt;/span&gt; disks
- &lt;strong&gt;Media:&lt;/strong&gt; 4 &lt;span class="caps"&gt;TB&lt;/span&gt; &lt;span class="caps"&gt;USB&lt;/span&gt; 3.0 external &lt;span class="caps"&gt;HDD&lt;/span&gt; for Jellyfin
- &lt;strong&gt;Backups:&lt;/strong&gt; 2 &lt;span class="caps"&gt;TB&lt;/span&gt; &lt;span class="caps"&gt;SATA&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt; for&amp;nbsp;restic/BorgBackup&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Principle 3: Networking and&amp;nbsp;Expandability&lt;/h2&gt;
&lt;h3&gt;Explanation&lt;/h3&gt;
&lt;p&gt;Mini PCs typically have 2–2.5 GbE ports (Realtek or Intel). The Intel i226-V is preferred for Proxmox (better driver support). Some models (Minisforum &lt;span class="caps"&gt;MS&lt;/span&gt;-01) have 10GbE &lt;span class="caps"&gt;SFP&lt;/span&gt;+ or dual 2.5 GbE ports, ideal for &lt;span class="caps"&gt;NAS&lt;/span&gt;&amp;nbsp;use.&lt;/p&gt;
&lt;p&gt;&lt;span class="caps"&gt;USB&lt;/span&gt; ports are plentiful (4–6 &lt;span class="caps"&gt;USB&lt;/span&gt; 3.0). You can add:
- &lt;strong&gt;&lt;span class="caps"&gt;USB&lt;/span&gt;-to-Ethernet adapters&lt;/strong&gt; for extra NICs (Proxmox bonding)
- &lt;strong&gt;&lt;span class="caps"&gt;USB&lt;/span&gt; storage&lt;/strong&gt; for cheap expansion
- &lt;strong&gt;&lt;span class="caps"&gt;USB&lt;/span&gt; serial adapters&lt;/strong&gt; for &lt;span class="caps"&gt;UPS&lt;/span&gt; or console&amp;nbsp;management&lt;/p&gt;
&lt;h3&gt;Example&lt;/h3&gt;
&lt;p&gt;The Minisforum &lt;span class="caps"&gt;MS&lt;/span&gt;-01 is a &amp;#8220;prosumer&amp;#8221; mini &lt;span class="caps"&gt;PC&lt;/span&gt; with:
- Intel i9-13900H (14 cores)
- 2 × 2.5 GbE (Intel i226)
- 2 × 10GbE &lt;span class="caps"&gt;SFP&lt;/span&gt;+
- 3 × M.2 NVMe slots
- 1 × U.2 NVMe&amp;nbsp;bay&lt;/p&gt;
&lt;p&gt;This is a mini &lt;span class="caps"&gt;PC&lt;/span&gt; that functions as a &lt;span class="caps"&gt;NAS&lt;/span&gt;, router, and virtualization host — all in 1.5&amp;nbsp;liters.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Applying This to Your&amp;nbsp;Homelab&lt;/h2&gt;
&lt;h3&gt;Homelab Setup&amp;nbsp;Example&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;The Budget Starter&amp;#8221; — Intel N100 + 16 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Services running:
- Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; (host)
- &lt;span class="caps"&gt;LXC&lt;/span&gt;: Pi-hole (&lt;span class="caps"&gt;DNS&lt;/span&gt; + ad blocking)
- &lt;span class="caps"&gt;LXC&lt;/span&gt;: Portainer (Docker management)
- &lt;span class="caps"&gt;VM&lt;/span&gt;: Docker host (Jellyfin, Nextcloud, Immich)
- &lt;span class="caps"&gt;LXC&lt;/span&gt;: WireGuard &lt;span class="caps"&gt;VPN&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Power draw: 8W idle, 18W under load. Monthly cost: ~$1.50 in&amp;nbsp;electricity.&lt;/p&gt;
&lt;h3&gt;Practical&amp;nbsp;Steps&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Step 1: Install Proxmox VE on the mini PC&lt;/span&gt;
&lt;span class="c1"&gt;# Download ISO from proxmox.com, flash to USB, install&lt;/span&gt;

&lt;span class="c1"&gt;# Step 2: Enable IOMMU for GPU passthrough (if needed)&lt;/span&gt;
nano&lt;span class="w"&gt; &lt;/span&gt;/etc/default/grub
&lt;span class="c1"&gt;# Add: GRUB_CMDLINE_LINUX_DEFAULT=&amp;quot;quiet intel_iommu=on iommu=pt&amp;quot;&lt;/span&gt;
update-grub
reboot

&lt;span class="c1"&gt;# Step 3: Update Proxmox&lt;/span&gt;
apt&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;dist-upgrade

&lt;span class="c1"&gt;# Step 4: Create an LXC container for Docker&lt;/span&gt;
pct&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;local:vztmpl/ubuntu-22.04-standard_22.04-1_amd64.tar.gz&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-rootfs&lt;span class="w"&gt; &lt;/span&gt;local-lvm:8&lt;span class="w"&gt; &lt;/span&gt;-memory&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4096&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-cores&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-net0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;eth0,bridge&lt;span class="o"&gt;=&lt;/span&gt;vmbr0,ip&lt;span class="o"&gt;=&lt;/span&gt;dhcp

&lt;span class="c1"&gt;# Step 5: Install Docker inside the LXC&lt;/span&gt;
pct&lt;span class="w"&gt; &lt;/span&gt;enter&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9000&lt;/span&gt;
apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;docker.io&lt;span class="w"&gt; &lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;-y
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Common Mistakes to&amp;nbsp;Avoid&lt;/h2&gt;
&lt;h3&gt;Mistake 1: Buying a Mini &lt;span class="caps"&gt;PC&lt;/span&gt; Without&amp;nbsp;QuickSync&lt;/h3&gt;
&lt;p&gt;If you plan to run Jellyfin, Immich, or Plex, you need Intel QuickSync for hardware transcoding. &lt;span class="caps"&gt;AMD&lt;/span&gt; mini PCs (Ryzen 5000/7000) do not have QuickSync. They can transcode via &lt;span class="caps"&gt;CPU&lt;/span&gt;, but it will peg your cores at 100% for 4K&amp;nbsp;content.&lt;/p&gt;
&lt;h3&gt;Mistake 2: Using a Single &lt;span class="caps"&gt;RAM&lt;/span&gt; Slot Model for&amp;nbsp;Proxmox&lt;/h3&gt;
&lt;p&gt;Some N100 mini PCs have only one &lt;span class="caps"&gt;SODIMM&lt;/span&gt; slot, limiting you to 16 &lt;span class="caps"&gt;GB&lt;/span&gt;. For Proxmox with 3+ VMs, 16 &lt;span class="caps"&gt;GB&lt;/span&gt; is tight. Buy a model with dual &lt;span class="caps"&gt;SODIMM&lt;/span&gt; slots (e.g., Minisforum &lt;span class="caps"&gt;UN100D&lt;/span&gt;, Beelink &lt;span class="caps"&gt;EQ12&lt;/span&gt;&amp;nbsp;Pro).&lt;/p&gt;
&lt;h3&gt;Mistake 3: Ignoring Realtek &lt;span class="caps"&gt;NIC&lt;/span&gt; Driver&amp;nbsp;Issues&lt;/h3&gt;
&lt;p&gt;Realtek NICs (&lt;span class="caps"&gt;RTL8111H&lt;/span&gt;) work fine on Linux but can have issues with Proxmox &lt;span class="caps"&gt;SR&lt;/span&gt;-&lt;span class="caps"&gt;IOV&lt;/span&gt; or PCIe passthrough. If you plan advanced networking, choose a mini &lt;span class="caps"&gt;PC&lt;/span&gt; with Intel i225/i226&amp;nbsp;NICs.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Mini PCs have democratized homelabbing. For $150–250, you get a silent, low-power server capable of running Proxmox, Docker, media servers, and VPNs. The Intel N100 is the entry point; the N305 and Minisforum &lt;span class="caps"&gt;MS&lt;/span&gt;-01 are the upgrade path. The only reason to buy a rack server in 2025 is if you need 64+ &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, multiple GPUs, or 10+ hard&amp;nbsp;drives.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Measure your power budget:&lt;/strong&gt; Use a Kill-A-Watt to see how much your current setup&amp;nbsp;draws.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pick a mini &lt;span class="caps"&gt;PC&lt;/span&gt;:&lt;/strong&gt; Start with an Intel N100 model (Beelink &lt;span class="caps"&gt;EQ12&lt;/span&gt;, Minisforum &lt;span class="caps"&gt;UN100D&lt;/span&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Install Proxmox:&lt;/strong&gt; Follow our Proxmox beginner&amp;nbsp;guide.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deploy your first 5 containers:&lt;/strong&gt; Pi-hole, Portainer, Jellyfin, Nextcloud,&amp;nbsp;Immich.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mini PCs:&lt;/strong&gt; Beelink &lt;span class="caps"&gt;EQ12&lt;/span&gt;, Minisforum &lt;span class="caps"&gt;UN100D&lt;/span&gt;, &lt;span class="caps"&gt;MS&lt;/span&gt;-01, GMKtec&amp;nbsp;N100&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;:&lt;/strong&gt; Crucial 16/32 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;DDR4&lt;/span&gt; &lt;span class="caps"&gt;SODIMM&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Storage:&lt;/strong&gt; Samsung 980/990 NVMe, &lt;span class="caps"&gt;WD&lt;/span&gt; Blue &lt;span class="caps"&gt;SATA&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;UPS&lt;/span&gt;:&lt;/strong&gt; &lt;span class="caps"&gt;APC&lt;/span&gt; Back-&lt;span class="caps"&gt;UPS&lt;/span&gt; Pro 1500 for power&amp;nbsp;protection&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Networking:&lt;/strong&gt; &lt;span class="caps"&gt;USB&lt;/span&gt;-to-2.5GbE adapters (Realtek &lt;span class="caps"&gt;RTL8156B&lt;/span&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;what-is&lt;/code&gt; → &lt;code&gt;proxmox-beginner-guide-2026&lt;/code&gt; — &amp;#8220;install Proxmox on your mini &lt;span class="caps"&gt;PC&lt;/span&gt;&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;principle-1&lt;/code&gt; → &lt;code&gt;intel-n100-mini-pc-homelab&lt;/code&gt; — &amp;#8220;deep dive into Intel N100&amp;nbsp;performance&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;principle-3&lt;/code&gt; → &lt;code&gt;minisforum-ms-01-review&lt;/code&gt; — &amp;#8220;the ultimate mini &lt;span class="caps"&gt;PC&lt;/span&gt; for&amp;nbsp;homelab&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;applying-it&lt;/code&gt; → &lt;code&gt;docker-compose-for-beginners&lt;/code&gt; — &amp;#8220;deploy your first&amp;nbsp;containers&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;best-self-hosted-apps-2026&lt;/code&gt; — &amp;#8220;what to run on your new mini &lt;span class="caps"&gt;PC&lt;/span&gt;&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;What mini &lt;span class="caps"&gt;PC&lt;/span&gt; runs your homelab?&lt;/strong&gt; Share your specs and power draw in the&amp;nbsp;comments.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subscribe&lt;/strong&gt; for mini &lt;span class="caps"&gt;PC&lt;/span&gt; reviews, Proxmox guides, and power efficiency&amp;nbsp;tips.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Guides"/><category term="mini pc home server"/><category term="best mini pc for homelab"/><category term="intel n100"/><category term="beelink"/><category term="minisforum"/><category term="low power server"/></entry><entry><title>Mini PC vs Rack Server for Homelab: Which One Should You Choose?</title><link href="https://steadypub.com/2026/06/mini-pc-vs-rack-server/" rel="alternate"/><published>2026-06-05T00:00:00+07:00</published><updated>2026-06-05T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/mini-pc-vs-rack-server/</id><summary type="html">&lt;p&gt;Compare mini PCs and rack servers for homelab use. Power, noise, price, performance, and expandability analyzed with real-world numbers and recommendations for every&amp;nbsp;budget.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~12 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelabbers deciding between compact and enterprise&amp;nbsp;hardware&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The Mini &lt;span class="caps"&gt;PC&lt;/span&gt; vs Rack Server&amp;nbsp;Dilemma&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;The first hardware decision every homelab builder faces is the form factor. Mini PCs (Intel N100, N305, Beelink, Minisforum) offer silence and efficiency. Rack servers (Dell R720, &lt;span class="caps"&gt;HP&lt;/span&gt; DL380p) offer raw power and enterprise features. The right choice depends on your use case, budget, and living&amp;nbsp;situation.&lt;/p&gt;
&lt;h3&gt;Key Differences at a&amp;nbsp;Glance&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Factor&lt;/th&gt;
&lt;th&gt;Mini &lt;span class="caps"&gt;PC&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Rack Server&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Idle power&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;6–15W&lt;/td&gt;
&lt;td&gt;100–200W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Noise&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Silent–near silent&lt;/td&gt;
&lt;td&gt;40–60 dB(A) (loud at boot)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Upfront cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$150–$400&lt;/td&gt;
&lt;td&gt;$150–$500 (used)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Max &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;16–64 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;192 &lt;span class="caps"&gt;GB&lt;/span&gt;–1.5 &lt;span class="caps"&gt;TB&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Drive bays&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1–3 (NVMe/&lt;span class="caps"&gt;SATA&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;8–24 hot-swap&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Remote management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;None or limited&lt;/td&gt;
&lt;td&gt;iDRAC/iLO/&lt;span class="caps"&gt;IPMI&lt;/span&gt; (full &lt;span class="caps"&gt;KVM&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PCIe expandability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0–1 slot&lt;/td&gt;
&lt;td&gt;3–7 full-height slots&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;ECC&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Size&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.5–2 L&lt;/td&gt;
&lt;td&gt;20–40 L&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Weight&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.5–1.5 kg&lt;/td&gt;
&lt;td&gt;20–35 kg&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Option A: Mini &lt;span class="caps"&gt;PC&lt;/span&gt; (Best for Beginners &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;Apartments)&lt;/h2&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Silent operation&lt;/strong&gt;: Fanless or low-&lt;span class="caps"&gt;RPM&lt;/span&gt; fans are&amp;nbsp;inaudible&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Low power&lt;/strong&gt;: 6–15W idle means $10–$20/year&amp;nbsp;electricity&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No rack needed&lt;/strong&gt;: Fits on a desk, shelf, or&amp;nbsp;closet&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modern connectivity&lt;/strong&gt;: 2.5GbE, Wi-Fi 6, &lt;span class="caps"&gt;USB&lt;/span&gt;-C, NVMe&amp;nbsp;Gen4&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Low heat&lt;/strong&gt;: Won&amp;#8217;t raise room&amp;nbsp;temperature&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Portable&lt;/strong&gt;: Easy to move or lend to&amp;nbsp;friends&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Limited &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;: &lt;span class="caps"&gt;16GB&lt;/span&gt; max on N100; &lt;span class="caps"&gt;64GB&lt;/span&gt; on high-end&amp;nbsp;models&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fewer drives&lt;/strong&gt;: 1–3 storage devices max (no &lt;span class="caps"&gt;RAID&lt;/span&gt;&amp;nbsp;hot-swap)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No &lt;span class="caps"&gt;ECC&lt;/span&gt;&lt;/strong&gt;: Risk of silent data corruption for &lt;span class="caps"&gt;ZFS&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No remote management&lt;/strong&gt;: If it crashes, you need physical&amp;nbsp;access&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No PCIe expansion&lt;/strong&gt;: Can&amp;#8217;t add 10GbE NICs, HBAs, or&amp;nbsp;GPUs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt; ceiling&lt;/strong&gt;: 4–8 cores; struggles with heavy transcoding or many&amp;nbsp;VMs&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Apartment dwellers with noise-sensitive&amp;nbsp;neighbors&lt;/li&gt;
&lt;li&gt;24/7 services (Pi-hole, AdGuard, Nextcloud,&amp;nbsp;Jellyfin)&lt;/li&gt;
&lt;li&gt;Docker/&lt;span class="caps"&gt;LXC&lt;/span&gt; container hosts (5–10&amp;nbsp;services)&lt;/li&gt;
&lt;li&gt;Beginners testing the waters before investing in a&amp;nbsp;rack&lt;/li&gt;
&lt;li&gt;Travelers who need a portable&amp;nbsp;lab&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Specs&lt;/th&gt;
&lt;th&gt;Price (2026)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Beelink Mini S12 Pro&lt;/td&gt;
&lt;td&gt;N100, &lt;span class="caps"&gt;16GB&lt;/span&gt;, &lt;span class="caps"&gt;500GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$150–$180&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Minisforum &lt;span class="caps"&gt;UN100D&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;N100, &lt;span class="caps"&gt;16GB&lt;/span&gt;, 2.5GbE&lt;/td&gt;
&lt;td&gt;$180–$220&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GMKtec NucBox M5&lt;/td&gt;
&lt;td&gt;N305, &lt;span class="caps"&gt;32GB&lt;/span&gt;, 2.5GbE&lt;/td&gt;
&lt;td&gt;$250–$300&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Minisforum &lt;span class="caps"&gt;MS&lt;/span&gt;-01&lt;/td&gt;
&lt;td&gt;i9-12900H, &lt;span class="caps"&gt;64GB&lt;/span&gt;, 10GbE&lt;/td&gt;
&lt;td&gt;$600–$700&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Option B: Rack Server (Best for Performance &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;Storage)&lt;/h2&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Massive &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;: &lt;span class="caps"&gt;192GB&lt;/span&gt;–1.&lt;span class="caps"&gt;5TB&lt;/span&gt; &lt;span class="caps"&gt;ECC&lt;/span&gt; for heavy&amp;nbsp;virtualization&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hot-swap storage&lt;/strong&gt;: 8–24 drives with hardware &lt;span class="caps"&gt;RAID&lt;/span&gt; or &lt;span class="caps"&gt;ZFS&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Remote management&lt;/strong&gt;: iDRAC/iLO lets you fix issues from&amp;nbsp;anywhere&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PCIe expansion&lt;/strong&gt;: Add 10GbE, Fibre Channel, HBAs, or&amp;nbsp;GPUs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;ECC&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;: Prevents bit-rot and data&amp;nbsp;corruption&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enterprise reliability&lt;/strong&gt;: Built for 24/7 over 5–10&amp;nbsp;years&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cheap used market&lt;/strong&gt;: $200 gets you a dual Xeon with &lt;span class="caps"&gt;64GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Loud&lt;/strong&gt;: 1U servers are jet engines at boot; 2U is manageable but still&amp;nbsp;audible&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Power hungry&lt;/strong&gt;: 100–200W idle means $100–$200/year&amp;nbsp;electricity&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Big and heavy&lt;/strong&gt;: Needs a rack or sturdy shelf; 20–35&amp;nbsp;kg&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hot&lt;/strong&gt;: Raises room temperature; needs&amp;nbsp;ventilation&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;DDR3&lt;/span&gt; aging&lt;/strong&gt;: Older models use &lt;span class="caps"&gt;DDR3&lt;/span&gt; (still fine for most&amp;nbsp;labs)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Overkill for many&lt;/strong&gt;: 80% of homelab services don&amp;#8217;t need 32&amp;nbsp;cores&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Proxmox/VMware clusters with 10+&amp;nbsp;VMs&lt;/li&gt;
&lt;li&gt;TrueNAS/FreeNAS with 8+ drive &lt;span class="caps"&gt;ZFS&lt;/span&gt;&amp;nbsp;pools&lt;/li&gt;
&lt;li&gt;Plex/Jellyfin with 4K &lt;span class="caps"&gt;HDR&lt;/span&gt; transcoding (add a &lt;span class="caps"&gt;GPU&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;Learning enterprise tools (iDRAC, &lt;span class="caps"&gt;RAID&lt;/span&gt;, &lt;span class="caps"&gt;IPMI&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;Users with a garage, basement, or dedicated server&amp;nbsp;room&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Specs&lt;/th&gt;
&lt;th&gt;Price (2026)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Dell R720 (used)&lt;/td&gt;
&lt;td&gt;Dual E5-2670, &lt;span class="caps"&gt;64GB&lt;/span&gt;, 8x &lt;span class="caps"&gt;LFF&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$200–$300&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;HP&lt;/span&gt; DL380p G8 (used)&lt;/td&gt;
&lt;td&gt;Dual E5-2680, &lt;span class="caps"&gt;64GB&lt;/span&gt;, 16x &lt;span class="caps"&gt;SFF&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$200–$280&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dell R730 (used)&lt;/td&gt;
&lt;td&gt;Dual E5-2680 v3, &lt;span class="caps"&gt;64GB&lt;/span&gt; &lt;span class="caps"&gt;DDR4&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$350–$500&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Supermicro 2U (used)&lt;/td&gt;
&lt;td&gt;Dual E5-2667 v2, &lt;span class="caps"&gt;128GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$300–$450&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Option C: Hybrid Approach (Best of Both&amp;nbsp;Worlds)&lt;/h2&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;p&gt;A hybrid setup uses a mini &lt;span class="caps"&gt;PC&lt;/span&gt; as the primary 24/7 host and a rack server for heavy workloads or storage. This gives you the silence of a mini &lt;span class="caps"&gt;PC&lt;/span&gt; for everyday services and the power of a rack server when&amp;nbsp;needed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example hybrid setup:&lt;/strong&gt;
- Mini &lt;span class="caps"&gt;PC&lt;/span&gt; (N100): Pi-hole, AdGuard, Home Assistant, &lt;span class="caps"&gt;VPN&lt;/span&gt; — 24/7 at 7W
- Rack server (R720): TrueNAS, Plex, Proxmox cluster node — on-demand or&amp;nbsp;scheduled&lt;/p&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Higher total cost&lt;/strong&gt;: Buying two&amp;nbsp;machines&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Complexity&lt;/strong&gt;: Two systems to manage, patch, and&amp;nbsp;backup&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Network dependency&lt;/strong&gt;: Services split across devices need reliable &lt;span class="caps"&gt;LAN&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Users who want silent always-on services but also need heavy&amp;nbsp;storage&lt;/li&gt;
&lt;li&gt;Homelabbers with time-of-use electricity rates (rack server off during&amp;nbsp;peak)&lt;/li&gt;
&lt;li&gt;Those experimenting with clustering and high&amp;nbsp;availability&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Comparison&amp;nbsp;Matrix&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;Mini &lt;span class="caps"&gt;PC&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Rack Server&lt;/th&gt;
&lt;th&gt;Hybrid&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Beginner homelab&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;★★☆☆☆&lt;/td&gt;
&lt;td&gt;★★★☆☆&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Docker containers (&amp;lt;10)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;★★★★☆&lt;/td&gt;
&lt;td&gt;★★★★☆&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;10+ VMs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;★☆☆☆☆&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;NAS&lt;/span&gt; with 8+ drives&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;★☆☆☆☆&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;4K transcoding&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;★★☆☆☆&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Noise-sensitive room&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;★☆☆☆☆&lt;/td&gt;
&lt;td&gt;★★★☆☆&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Low power / green&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;★★☆☆☆&lt;/td&gt;
&lt;td&gt;★★★★☆&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Budget under $200&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;★★★★☆&lt;/td&gt;
&lt;td&gt;★☆☆☆☆&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Learning enterprise tech&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;★★☆☆☆&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Remote management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;★☆☆☆☆&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Which Should You&amp;nbsp;Choose?&lt;/h2&gt;
&lt;h3&gt;Scenario 1: Apartment or Shared&amp;nbsp;Living&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose: Mini &lt;span class="caps"&gt;PC&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You need silence. A rack server will annoy roommates, partners, or neighbors. An Intel N100 or N305 mini &lt;span class="caps"&gt;PC&lt;/span&gt; can run all essential services at 7–12W without making a&amp;nbsp;sound.&lt;/p&gt;
&lt;h3&gt;Scenario 2: Garage or Basement with Power&amp;nbsp;Outlets&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose: Rack&amp;nbsp;Server&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You have space, power, and tolerance for noise. A used Dell R720 or &lt;span class="caps"&gt;HP&lt;/span&gt; DL380p gives you &lt;span class="caps"&gt;64GB&lt;/span&gt;+ &lt;span class="caps"&gt;RAM&lt;/span&gt;, 8+ drive bays, and enterprise remote management for&amp;nbsp;$200–$300.&lt;/p&gt;
&lt;h3&gt;Scenario 3: You Want to Learn VMware, Proxmox, or&amp;nbsp;TrueNAS&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose: Rack&amp;nbsp;Server&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Mini PCs lack the drive bays and &lt;span class="caps"&gt;RAM&lt;/span&gt; for serious &lt;span class="caps"&gt;ZFS&lt;/span&gt; or virtualization learning. You need a 2U server with 16+ &lt;span class="caps"&gt;SFF&lt;/span&gt; bays and &lt;span class="caps"&gt;128GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; to explore enterprise storage and&amp;nbsp;clustering.&lt;/p&gt;
&lt;h3&gt;Scenario 4: You Need 24/7 Services + Heavy&amp;nbsp;Storage&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose:&amp;nbsp;Hybrid&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Buy a mini &lt;span class="caps"&gt;PC&lt;/span&gt; ($180) for always-on services and a used rack server ($200) for TrueNAS. The mini &lt;span class="caps"&gt;PC&lt;/span&gt; sips power; the rack server sleeps when not needed or runs on a smart plug&amp;nbsp;schedule.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Migration&amp;nbsp;Path&lt;/h2&gt;
&lt;h3&gt;Step 1: Start with a Mini &lt;span class="caps"&gt;PC&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Buy a $150–$200 mini &lt;span class="caps"&gt;PC&lt;/span&gt; to learn Docker, Proxmox, and networking. Run Pi-hole, Nextcloud, and&amp;nbsp;Jellyfin.&lt;/p&gt;
&lt;h3&gt;Step 2: Add a Rack Server for&amp;nbsp;Storage&lt;/h3&gt;
&lt;p&gt;When you outgrow the mini &lt;span class="caps"&gt;PC&lt;/span&gt;&amp;#8217;s 2–3 drive slots, buy a used 2U server. Move TrueNAS and Plex to the server. Keep the mini &lt;span class="caps"&gt;PC&lt;/span&gt; for lightweight&amp;nbsp;services.&lt;/p&gt;
&lt;h3&gt;Step 3: Sell or Repurpose the Mini &lt;span class="caps"&gt;PC&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;If you move to a full rack environment, the mini &lt;span class="caps"&gt;PC&lt;/span&gt; becomes a portable travel lab, a backup &lt;span class="caps"&gt;DNS&lt;/span&gt; server, or a gift to a friend starting their homelab&amp;nbsp;journey.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The&amp;nbsp;Verdict&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Budget&lt;/th&gt;
&lt;th&gt;Recommendation&lt;/th&gt;
&lt;th&gt;Setup&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Under $200&lt;/td&gt;
&lt;td&gt;Mini &lt;span class="caps"&gt;PC&lt;/span&gt; (N100)&lt;/td&gt;
&lt;td&gt;Single device, Docker or Proxmox&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$200–$400&lt;/td&gt;
&lt;td&gt;Rack server (R720/DL380p)&lt;/td&gt;
&lt;td&gt;Used enterprise, max bang for buck&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$400–$600&lt;/td&gt;
&lt;td&gt;Hybrid&lt;/td&gt;
&lt;td&gt;Mini &lt;span class="caps"&gt;PC&lt;/span&gt; + rack server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$600+&lt;/td&gt;
&lt;td&gt;Rack server (R730)&lt;/td&gt;
&lt;td&gt;Modern &lt;span class="caps"&gt;DDR4&lt;/span&gt;, efficient, future-proof&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Mini PCs are the best starting point for 80% of homelabbers. They&amp;#8217;re silent, efficient, and capable. Rack servers are essential for storage-heavy, virtualization-heavy, or learning-heavy setups. The hybrid approach is the sweet spot for advanced users who want&amp;nbsp;both.&lt;/p&gt;
&lt;h3&gt;Ready to Get&amp;nbsp;Started?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Read our &lt;a href="best-mini-pc-for-homelab"&gt;best mini &lt;span class="caps"&gt;PC&lt;/span&gt; for homelab guide&lt;/a&gt; for specific&amp;nbsp;models&lt;/li&gt;
&lt;li&gt;Read our &lt;a href="used-server-hardware-for-homelab"&gt;used server hardware guide&lt;/a&gt; for eBay buying&amp;nbsp;tips&lt;/li&gt;
&lt;li&gt;Read our &lt;a href="proxmox-beginner-guide-2026"&gt;Proxmox beginner guide&lt;/a&gt; for your first hypervisor&amp;nbsp;setup&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Beelink Mini S12 Pro&lt;/strong&gt;: Amazon affiliate for mini &lt;span class="caps"&gt;PC&lt;/span&gt;&amp;nbsp;buyers&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dell R720 eBay listings&lt;/strong&gt;: Contextual link for rack server&amp;nbsp;buyers&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;StarTech rack shelves&lt;/strong&gt;: Shelf for rack servers in non-rack&amp;nbsp;setups&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;TP&lt;/span&gt;-Link Kasa smart plugs&lt;/strong&gt;: For measuring power and&amp;nbsp;scheduling&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;intro&lt;/code&gt; → &lt;code&gt;best-mini-pc-for-homelab&lt;/code&gt; for mini &lt;span class="caps"&gt;PC&lt;/span&gt;&amp;nbsp;recommendations&lt;/li&gt;
&lt;li&gt;&lt;code&gt;intro&lt;/code&gt; → &lt;code&gt;used-server-hardware-for-homelab&lt;/code&gt; for rack server buying&amp;nbsp;guide&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scenario-4&lt;/code&gt; → &lt;code&gt;low-power-homelab-server-build&lt;/code&gt; for power&amp;nbsp;tuning&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;proxmox-beginner-guide-2026&lt;/code&gt; for setup&amp;nbsp;steps&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] Are you team mini &lt;span class="caps"&gt;PC&lt;/span&gt; or team rack server? Vote in the comments and tell us&amp;nbsp;why!&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for weekly homelab hardware comparisons and deal&amp;nbsp;alerts.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Comparisons"/><category term="mini pc vs rack server"/><category term="homelab hardware"/><category term="low power server"/><category term="rack server"/><category term="homelab comparison"/></entry><entry><title>Pi-hole Docker Compose Setup: Complete Homelab Guide</title><link href="https://steadypub.com/2026/06/pihole-docker-compose/" rel="alternate"/><published>2026-06-05T00:00:00+07:00</published><updated>2026-06-05T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/pihole-docker-compose/</id><summary type="html">&lt;p&gt;Deploy Pi-hole with Docker Compose for network-wide ad blocking. Step-by-step guide with docker-compose.yml, router configuration, blocklists, and&amp;nbsp;troubleshooting.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~12 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelabbers wanting network-wide ad and tracker&amp;nbsp;blocking&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is&amp;nbsp;Pi-hole?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Pi-hole is a &lt;span class="caps"&gt;DNS&lt;/span&gt; sinkhole that blocks ads, trackers, and malicious domains at the network level. By acting as your &lt;span class="caps"&gt;LAN&lt;/span&gt;&amp;#8217;s &lt;span class="caps"&gt;DNS&lt;/span&gt; server, it intercepts queries to known ad domains and&amp;nbsp;returns &lt;code&gt;0.0.0.0&lt;/code&gt; — blocking ads on every device without installing browser extensions or&amp;nbsp;apps.&lt;/p&gt;
&lt;h3&gt;Key&amp;nbsp;Benefits&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Benefit&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Network-wide&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;One setup covers phones, TVs, IoT, and guests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Device-agnostic&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Works on devices that can&amp;#8217;t run ad blockers (smart TVs, consoles)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Low resource&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Runs on a Raspberry Pi or in a Docker container&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Privacy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Blocks trackers from Google, Facebook, Amazon, and analytics&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Malware blocking&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Filter lists include known malicious domains&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Custom filtering&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Add your own blacklists and whitelists&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Statistics&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;See exactly which domains are queried and blocked&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Pi-hole v6 (2025) changes:&lt;/strong&gt;
- Built-in web server (no Lighttpd dependency)
- &lt;span class="caps"&gt;FTL&lt;/span&gt; v6 &lt;span class="caps"&gt;DNS&lt;/span&gt; engine (replaces dnsmasq)
- &lt;span class="caps"&gt;TOML&lt;/span&gt; configuration format
- Improved &lt;span class="caps"&gt;REST&lt;/span&gt; &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;h3&gt;Hardware&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Any device running Docker (mini &lt;span class="caps"&gt;PC&lt;/span&gt;, Raspberry Pi, &lt;span class="caps"&gt;NAS&lt;/span&gt;, or &lt;span class="caps"&gt;VM&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;512MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; minimum (&lt;span class="caps"&gt;1GB&lt;/span&gt;&amp;nbsp;recommended)&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;2GB&lt;/span&gt; storage for logs and&amp;nbsp;databases&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Software&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Docker Engine 24.x+ and Docker Compose&amp;nbsp;v2+&lt;/li&gt;
&lt;li&gt;Linux host (Debian 12, Ubuntu 22.04/24.04, or Proxmox &lt;span class="caps"&gt;LXC&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;Router access to change &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;settings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Knowledge&amp;nbsp;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Basic Docker and Linux&amp;nbsp;commands&lt;/li&gt;
&lt;li&gt;Router admin panel&amp;nbsp;access&lt;/li&gt;
&lt;li&gt;Understanding of &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;basics&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Create the Docker Compose&amp;nbsp;File&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Set up a reproducible Pi-hole deployment with persistent storage and proper network&amp;nbsp;configuration.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Create a directory for&amp;nbsp;Pi-hole:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;~/docker/pihole&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/docker/pihole
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Create &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;pihole&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pihole&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pihole/pihole:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;53:53/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;53:53/udp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8080:80/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TZ=Asia/Singapore&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;WEBPASSWORD=ChangeMeStrong123!&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;FTLCONF_LOCAL_IPV4=192.168.1.10&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;PIHOLE_DNS_=1.1.1.1;1.0.0.1&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;FTLCONF_BLOCK_ICLOUD_PR=false&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./etc-pihole:/etc/pihole&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./etc-dnsmasq.d:/etc/dnsmasq.d&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;cap_add&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;NET_ADMIN&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pihole-net&lt;/span&gt;

&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;pihole-net&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;bridge&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Create data&amp;nbsp;directories:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;etc-pihole&lt;span class="w"&gt; &lt;/span&gt;etc-dnsmasq.d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Deploy:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Verify it&amp;#8217;s&amp;nbsp;running:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;logs&lt;span class="w"&gt; &lt;/span&gt;pihole&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;finished&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 2: Configure Your Router to Use&amp;nbsp;Pi-hole&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Point all devices on your network to Pi-hole for &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;resolution.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Option A: Router &lt;span class="caps"&gt;DHCP&lt;/span&gt; &lt;span class="caps"&gt;DNS&lt;/span&gt; (Recommended)&lt;/strong&gt;
1. Log into your router admin panel&amp;nbsp;(usually &lt;code&gt;192.168.1.1&lt;/code&gt; or &lt;code&gt;192.168.0.1&lt;/code&gt;)
2. Find &lt;strong&gt;&lt;span class="caps"&gt;DHCP&lt;/span&gt; Server&lt;/strong&gt; or &lt;strong&gt;&lt;span class="caps"&gt;LAN&lt;/span&gt; Settings&lt;/strong&gt;
3. Set &lt;strong&gt;Primary &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/strong&gt; to your Pi-hole &lt;span class="caps"&gt;IP&lt;/span&gt;&amp;nbsp;(e.g., &lt;code&gt;192.168.1.10&lt;/code&gt;)
4. Set &lt;strong&gt;Secondary &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/strong&gt; to a backup&amp;nbsp;(e.g., &lt;code&gt;1.1.1.1&lt;/code&gt;) or leave blank
5. Save and reboot the&amp;nbsp;router&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Option B: Pi-hole as &lt;span class="caps"&gt;DHCP&lt;/span&gt; Server&lt;/strong&gt;
If your router doesn&amp;#8217;t allow custom &lt;span class="caps"&gt;DNS&lt;/span&gt;, disable its &lt;span class="caps"&gt;DHCP&lt;/span&gt; and let Pi-hole handle it:
1. In Pi-hole admin (Settings → &lt;span class="caps"&gt;DHCP&lt;/span&gt;), enable &lt;span class="caps"&gt;DHCP&lt;/span&gt; server
2. Set&amp;nbsp;range: &lt;code&gt;192.168.1.100&lt;/code&gt; to &lt;code&gt;192.168.1.200&lt;/code&gt;
3. Set router (gateway)&amp;nbsp;to &lt;code&gt;192.168.1.1&lt;/code&gt;
4. Disable &lt;span class="caps"&gt;DHCP&lt;/span&gt; on your router
5. Renew leases on all devices (reconnect Wi-Fi or&amp;nbsp;reboot)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Option C: Manual Per-Device&lt;/strong&gt;
On each device, set &lt;span class="caps"&gt;DNS&lt;/span&gt; to Pi-hole&amp;#8217;s &lt;span class="caps"&gt;IP&lt;/span&gt;. Good for testing before network-wide&amp;nbsp;rollout.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 3: Add Blocklists and&amp;nbsp;Whitelists&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Tune blocking to balance ad blocking with website&amp;nbsp;functionality.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Log into Pi-hole admin&lt;/strong&gt;&amp;nbsp;at &lt;code&gt;http://192.168.1.10:8080/admin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Default blocklists (enabled&amp;nbsp;automatically):&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;StevenBlack&amp;#8217;s unified hosts&amp;nbsp;list&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;AdAway default&amp;nbsp;blocklist&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Add recommended blocklists (Group Management →&amp;nbsp;Adlists):&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts
https://adaway.org/hosts.txt
https://someonewhocares.org/hosts/zero/hosts
https://raw.githubusercontent.com/Spam404/lists/master/main-blacklist.txt
https://raw.githubusercontent.com/ShadowWhisperer/BlockLists/master/Lists/Tracking
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Update&amp;nbsp;gravity:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pihole&lt;span class="w"&gt; &lt;/span&gt;pihole&lt;span class="w"&gt; &lt;/span&gt;-g
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Common whitelist entries (to avoid breaking&amp;nbsp;sites):&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;clients4.google.com&lt;/code&gt; (Google&amp;nbsp;Play/Android)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;app-api.twitch.tv&lt;/code&gt; (Twitch&amp;nbsp;login)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;www.msftncsi.com&lt;/code&gt; (Windows connectivity&amp;nbsp;check)&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Step 4: Enable &lt;span class="caps"&gt;DNS&lt;/span&gt;-over-&lt;span class="caps"&gt;HTTPS&lt;/span&gt; (Optional but&amp;nbsp;Recommended)&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Encrypt &lt;span class="caps"&gt;DNS&lt;/span&gt; queries from Pi-hole to upstream resolvers for&amp;nbsp;privacy.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;p&gt;Use&amp;nbsp;Cloudflare&amp;#8217;s &lt;code&gt;cloudflared&lt;/code&gt; container as the&amp;nbsp;upstream:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;cloudflared&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;cloudflared&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;cloudflare/cloudflared:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;proxy-dns&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TUNNEL_DNS_UPSTREAM=https://1.1.1.1/dns-query,https://1.0.0.1/dns-query&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TUNNEL_DNS_PORT=5053&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TUNNEL_DNS_ADDRESS=0.0.0.0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pihole-net&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;pihole&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pihole&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pihole/pihole:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;53:53/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;53:53/udp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8080:80/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TZ=Asia/Singapore&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;WEBPASSWORD=ChangeMeStrong123!&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;PIHOLE_DNS_=cloudflared#5053&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./etc-pihole:/etc/pihole&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./etc-dnsmasq.d:/etc/dnsmasq.d&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;cap_add&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;NET_ADMIN&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pihole-net&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;cloudflared&lt;/span&gt;

&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;pihole-net&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;bridge&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Use a &lt;span class="caps"&gt;MAC&lt;/span&gt; Address&amp;nbsp;Reservation&lt;/h3&gt;
&lt;p&gt;Assign Pi-hole a static &lt;span class="caps"&gt;IP&lt;/span&gt; in your router&amp;#8217;s &lt;span class="caps"&gt;DHCP&lt;/span&gt; reservations. If the &lt;span class="caps"&gt;IP&lt;/span&gt; changes, your entire network loses &lt;span class="caps"&gt;DNS&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;Tip 2: Keep a Backup &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Set a secondary &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;(e.g., &lt;code&gt;1.1.1.1&lt;/code&gt;) on your router. If Pi-hole goes down, devices can still resolve. The trade-off is that some ads slip through during the&amp;nbsp;outage.&lt;/p&gt;
&lt;h3&gt;Tip 3: Schedule Gravity&amp;nbsp;Updates&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Add to crontab (docker host)&lt;/span&gt;
&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;*&lt;span class="w"&gt; &lt;/span&gt;*&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/docker/pihole&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pihole&lt;span class="w"&gt; &lt;/span&gt;pihole&lt;span class="w"&gt; &lt;/span&gt;-g
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 4: Monitor Block&amp;nbsp;Percentage&lt;/h3&gt;
&lt;p&gt;A healthy Pi-hole blocks 10–30% of queries. If it&amp;#8217;s under 5%, your blocklists are too conservative. If it&amp;#8217;s over 50%, you&amp;#8217;re probably breaking&amp;nbsp;websites.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Troubleshooting Common&amp;nbsp;Issues&lt;/h2&gt;
&lt;h3&gt;Problem 1: &amp;#8220;&lt;span class="caps"&gt;DNS&lt;/span&gt; Resolution Not&amp;nbsp;Working&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Cause:&lt;/strong&gt; Router not pointing to Pi-hole, or Pi-hole container not&amp;nbsp;running.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Check if Pi-hole is running&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;ps&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;pihole

&lt;span class="c1"&gt;# Test DNS directly&lt;/span&gt;
nslookup&lt;span class="w"&gt; &lt;/span&gt;google.com&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.1.10

&lt;span class="c1"&gt;# Check Pi-hole logs&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;logs&lt;span class="w"&gt; &lt;/span&gt;pihole
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Problem 2: &amp;#8220;Some Websites Won&amp;#8217;t&amp;nbsp;Load&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Cause:&lt;/strong&gt; Overly aggressive&amp;nbsp;blocklist.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;
1. Check Pi-hole Query Log for blocked domains
2. Whitelist the domain blocking the site
3. Use&amp;nbsp;the &lt;code&gt;pihole -t&lt;/code&gt; command to tail logs in real&amp;nbsp;time&lt;/p&gt;
&lt;h3&gt;Problem 3: &amp;#8220;Container Won&amp;#8217;t Start — Port 53 in&amp;nbsp;Use&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Cause:&lt;/strong&gt; systemd-resolved or another &lt;span class="caps"&gt;DNS&lt;/span&gt; service is using port&amp;nbsp;53.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# On Debian/Ubuntu, disable systemd-resolved&lt;/span&gt;
systemctl&lt;span class="w"&gt; &lt;/span&gt;stop&lt;span class="w"&gt; &lt;/span&gt;systemd-resolved
systemctl&lt;span class="w"&gt; &lt;/span&gt;disable&lt;span class="w"&gt; &lt;/span&gt;systemd-resolved
rm&lt;span class="w"&gt; &lt;/span&gt;/etc/resolv.conf
ln&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;/run/systemd/resolve/resolv.conf&lt;span class="w"&gt; &lt;/span&gt;/etc/resolv.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Pi-hole in Docker Compose is the easiest way to deploy network-wide ad blocking. With a&amp;nbsp;single &lt;code&gt;docker-compose.yml&lt;/code&gt; file, you can block ads on every device in your home, improve privacy, and reduce bandwidth&amp;nbsp;usage.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Add &lt;a href="pihole-unbound-dns"&gt;Unbound&lt;/a&gt; for recursive &lt;span class="caps"&gt;DNS&lt;/span&gt; without third-party&amp;nbsp;resolvers&lt;/li&gt;
&lt;li&gt;Set up &lt;a href="adguard-home-setup"&gt;AdGuard Home&lt;/a&gt; as a backup &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Monitor your network with &lt;a href="grafana-prometheus-setup"&gt;Grafana and&amp;nbsp;Prometheus&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Raspberry Pi 5&lt;/strong&gt;: Alternative hardware for&amp;nbsp;Pi-hole&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Beelink Mini S12 Pro&lt;/strong&gt;: Mini &lt;span class="caps"&gt;PC&lt;/span&gt; for running Pi-hole + other&amp;nbsp;services&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;TP&lt;/span&gt;-Link Omada router&lt;/strong&gt;: Router with good &lt;span class="caps"&gt;DNS&lt;/span&gt;/&lt;span class="caps"&gt;DHCP&lt;/span&gt;&amp;nbsp;control&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;intro&lt;/code&gt; → &lt;code&gt;pihole-vs-adguard-home&lt;/code&gt; for &lt;span class="caps"&gt;DNS&lt;/span&gt; blocker&amp;nbsp;comparison&lt;/li&gt;
&lt;li&gt;&lt;code&gt;step-4&lt;/code&gt; → &lt;code&gt;pihole-unbound-dns&lt;/code&gt; for recursive &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;setup&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;docker-compose-for-beginners&lt;/code&gt; for Docker&amp;nbsp;basics&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] What&amp;#8217;s your Pi-hole block percentage? Share your stats and favorite&amp;nbsp;blocklists!&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for weekly homelab Docker tutorials and privacy&amp;nbsp;guides.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Tutorials"/><category term="pihole"/><category term="docker compose"/><category term="dns"/><category term="ad blocker"/><category term="homelab"/><category term="network-wide"/></entry><entry><title>Portainer Docker Compose Stack: Build a Complete Homelab Management Platform</title><link href="https://steadypub.com/2026/06/portainer-docker-compose-stack/" rel="alternate"/><published>2026-06-05T00:00:00+07:00</published><updated>2026-06-05T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/portainer-docker-compose-stack/</id><summary type="html">&lt;p&gt;Deploy a complete Portainer-managed Docker Compose stack in your homelab. Includes Traefik reverse proxy, monitoring, databases, and production-ready security&amp;nbsp;practices.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~18 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelabbers who want a web &lt;span class="caps"&gt;UI&lt;/span&gt; to manage Docker&amp;nbsp;containers&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is&amp;nbsp;Portainer?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Portainer is a lightweight web &lt;span class="caps"&gt;UI&lt;/span&gt; for managing Docker, Docker Swarm, Kubernetes, and Nomad environments. It turns complex &lt;span class="caps"&gt;CLI&lt;/span&gt; commands&amp;nbsp;— &lt;code&gt;docker run&lt;/code&gt;, &lt;code&gt;docker network create&lt;/code&gt;, &lt;code&gt;docker volume inspect&lt;/code&gt; — into clickable buttons. For homelabbers, it is the fastest way to deploy, update, and monitor containers without memorizing&amp;nbsp;flags.&lt;/p&gt;
&lt;p&gt;Portainer &lt;span class="caps"&gt;CE&lt;/span&gt; (Community Edition) is free and open-source. It supports up to 5 nodes in the free version, which is more than enough for most&amp;nbsp;homelabs.&lt;/p&gt;
&lt;h3&gt;Key&amp;nbsp;Benefits&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Stack deployment:&lt;/strong&gt; Paste&amp;nbsp;a &lt;code&gt;docker-compose.yml&lt;/code&gt; into the &lt;span class="caps"&gt;UI&lt;/span&gt; and deploy it in one&amp;nbsp;click.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Container logs:&lt;/strong&gt; Stream logs in real-time from the&amp;nbsp;browser.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Image management:&lt;/strong&gt; Pull, inspect, and delete images without touching the &lt;span class="caps"&gt;CLI&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Volume browser:&lt;/strong&gt; Browse files inside named volumes — useful for debugging config&amp;nbsp;files.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;User management:&lt;/strong&gt; Create multiple users with role-based access control (&lt;span class="caps"&gt;RBAC&lt;/span&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;App templates:&lt;/strong&gt; One-click deploy popular apps (&lt;span class="caps"&gt;NGINX&lt;/span&gt;, MySQL, Redis,&amp;nbsp;WordPress).&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;h3&gt;Hardware&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;A Linux server (x86_64 or &lt;span class="caps"&gt;ARM64&lt;/span&gt;) with Docker&amp;nbsp;installed.&lt;/li&gt;
&lt;li&gt;Minimum 2 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; (4 &lt;span class="caps"&gt;GB&lt;/span&gt; recommended if running multiple&amp;nbsp;stacks).&lt;/li&gt;
&lt;li&gt;20 &lt;span class="caps"&gt;GB&lt;/span&gt; free storage for images and&amp;nbsp;volumes.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Software&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Docker Engine 20.10+ and Docker Compose&amp;nbsp;plugin.&lt;/li&gt;
&lt;li&gt;A user&amp;nbsp;with &lt;code&gt;docker&lt;/code&gt; group membership (or root&amp;nbsp;access).&lt;/li&gt;
&lt;li&gt;Optional: A domain name and &lt;span class="caps"&gt;DNS&lt;/span&gt; A record pointing to your&amp;nbsp;server.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Knowledge&amp;nbsp;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Basic familiarity with Docker concepts (images, containers, volumes,&amp;nbsp;networks).&lt;/li&gt;
&lt;li&gt;Comfortable editing &lt;span class="caps"&gt;YAML&lt;/span&gt;&amp;nbsp;files.&lt;/li&gt;
&lt;li&gt;Understanding of reverse proxies (Traefik or Nginx Proxy Manager) for &lt;span class="caps"&gt;HTTPS&lt;/span&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Minimum&lt;/th&gt;
&lt;th&gt;Recommended&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;2 cores&lt;/td&gt;
&lt;td&gt;4 cores&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;2 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;4 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;20 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;50 &lt;span class="caps"&gt;GB&lt;/span&gt;+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network&lt;/td&gt;
&lt;td&gt;1 GbE&lt;/td&gt;
&lt;td&gt;2.5 GbE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Install Docker and Docker&amp;nbsp;Compose&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Prepare the host with Docker Engine and the Compose plugin. Ensure the Docker daemon is running and the user has correct&amp;nbsp;permissions.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Update system&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;upgrade&lt;span class="w"&gt; &lt;/span&gt;-y

&lt;span class="c1"&gt;# Install prerequisites&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;ca-certificates&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;gnupg&lt;span class="w"&gt; &lt;/span&gt;lsb-release

&lt;span class="c1"&gt;# Add Docker&amp;#39;s official GPG key&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;/etc/apt/keyrings
curl&lt;span class="w"&gt; &lt;/span&gt;-fsSL&lt;span class="w"&gt; &lt;/span&gt;https://download.docker.com/linux/ubuntu/gpg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;gpg&lt;span class="w"&gt; &lt;/span&gt;--dearmor&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;/etc/apt/keyrings/docker.gpg

&lt;span class="c1"&gt;# Add the repository&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;deb [arch=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;dpkg&lt;span class="w"&gt; &lt;/span&gt;--print-architecture&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; signed-by=/etc/apt/keyrings/docker.gpg] \&lt;/span&gt;
&lt;span class="s2"&gt;  https://download.docker.com/linux/ubuntu &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;lsb_release&lt;span class="w"&gt; &lt;/span&gt;-cs&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; stable&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;tee&lt;span class="w"&gt; &lt;/span&gt;/etc/apt/sources.list.d/docker.list&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/dev/null

&lt;span class="c1"&gt;# Install Docker&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;update
sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;docker-ce&lt;span class="w"&gt; &lt;/span&gt;docker-ce-cli&lt;span class="w"&gt; &lt;/span&gt;containerd.io&lt;span class="w"&gt; &lt;/span&gt;docker-compose-plugin

&lt;span class="c1"&gt;# Add user to docker group&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;usermod&lt;span class="w"&gt; &lt;/span&gt;-aG&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$USER&lt;/span&gt;
newgrp&lt;span class="w"&gt; &lt;/span&gt;docker

&lt;span class="c1"&gt;# Verify&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;--version
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;version
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 2: Deploy Portainer &lt;span class="caps"&gt;CE&lt;/span&gt;&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Run Portainer as a Docker container with persistent data storage and restart&amp;nbsp;policies.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Create a volume for Portainer data&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;volume&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;portainer_data

&lt;span class="c1"&gt;# Run Portainer&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8000&lt;/span&gt;:8000&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9443&lt;/span&gt;:9443&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;portainer&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--restart&lt;span class="o"&gt;=&lt;/span&gt;always&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;/var/run/docker.sock:/var/run/docker.sock&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;portainer_data:/data&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;portainer/portainer-ce:latest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Access Portainer&amp;nbsp;at &lt;code&gt;https://your-server-ip:9443&lt;/code&gt;. Create the initial admin&amp;nbsp;account.&lt;/p&gt;
&lt;h3&gt;Optional: Docker Compose for&amp;nbsp;Portainer&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;portainer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;portainer/portainer-ce:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;portainer&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8000:8000&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;9443:9443&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/var/run/docker.sock:/var/run/docker.sock&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;portainer_data:/data&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;portainer_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Deploy:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 3: Deploy a Reverse Proxy&amp;nbsp;Stack&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Set up Traefik as a reverse proxy so all services get &lt;span class="caps"&gt;HTTPS&lt;/span&gt; certificates and domain-based&amp;nbsp;routing.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;p&gt;Create a project&amp;nbsp;directory:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;~/homelab/traefik&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/homelab/traefik
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Create &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;traefik&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;traefik:v3.0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;traefik&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--api.dashboard=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--providers.docker=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--providers.docker.exposedbydefault=false&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--entrypoints.web.address=:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--entrypoints.websecure.address=:443&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--certificatesresolvers.letsencrypt.acme.tlschallenge=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--certificatesresolvers.letsencrypt.acme.email=admin@yourdomain.com&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--entrypoints.web.http.redirections.entryPoint.to=websecure&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--entrypoints.web.http.redirections.entryPoint.scheme=https&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;80:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;443:443&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8080:8080&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/var/run/docker.sock:/var/run/docker.sock:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./letsencrypt:/letsencrypt&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;proxy&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;whoami&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;traefik/whoami&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;whoami&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.enable=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.whoami.rule=Host(`whoami.yourdomain.com`)&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.whoami.tls.certresolver=letsencrypt&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.services.whoami.loadbalancer.server.port=80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;proxy&lt;/span&gt;

&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;external&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Deploy via Portainer:
1. In Portainer, go to &lt;strong&gt;Stacks&lt;/strong&gt; → &lt;strong&gt;Add stack&lt;/strong&gt;.
2. Name&amp;nbsp;it &lt;code&gt;traefik&lt;/code&gt;.
3. Paste the Compose &lt;span class="caps"&gt;YAML&lt;/span&gt;.
4. Click &lt;strong&gt;Deploy the stack&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Verify:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-I&lt;span class="w"&gt; &lt;/span&gt;https://whoami.yourdomain.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 4: Deploy a Monitoring&amp;nbsp;Stack&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Add Prometheus, Grafana, and cAdvisor to monitor container metrics and system&amp;nbsp;performance.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;p&gt;Create a new stack in Portainer&amp;nbsp;named &lt;code&gt;monitoring&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;external&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;monitoring&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;bridge&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;prometheus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;prom/prometheus:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;prometheus&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./prometheus.yml:/etc/prometheus/prometheus.yml:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;prometheus_data:/prometheus&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--config.file=/etc/prometheus/prometheus.yml&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--storage.tsdb.path=/prometheus&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;monitoring&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;grafana&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;grafana/grafana:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;grafana&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3000:3000&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;grafana_data:/var/lib/grafana&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;GF_SECURITY_ADMIN_USER=admin&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;GF_SECURITY_ADMIN_PASSWORD=admin&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;monitoring&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;proxy&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.enable=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.grafana.rule=Host(`grafana.yourdomain.com`)&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.grafana.tls.certresolver=letsencrypt&amp;quot;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;cadvisor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;gcr.io/cadvisor/cadvisor:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;cadvisor&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/:/rootfs:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/var/run:/var/run:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/sys:/sys:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/var/lib/docker:/var/lib/docker:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/dev/disk:/dev/disk:ro&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;monitoring&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;prometheus_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;grafana_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Create &lt;code&gt;prometheus.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;global&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;scrape_interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;15s&lt;/span&gt;

&lt;span class="nt"&gt;scrape_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;prometheus&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;localhost:9090&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;cadvisor&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;cadvisor:8080&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Deploy the stack in Portainer. Access Grafana&amp;nbsp;at &lt;code&gt;https://grafana.yourdomain.com&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 5: Add a Database&amp;nbsp;Stack&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Deploy PostgreSQL and Redis as reusable backing services for apps like Nextcloud, Immich, and&amp;nbsp;Authelia.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;p&gt;Create&amp;nbsp;a &lt;code&gt;database&lt;/code&gt; stack in&amp;nbsp;Portainer:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;backend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;bridge&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;postgres&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;postgres:16-alpine&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;postgres&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;POSTGRES_USER=admin&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;POSTGRES_PASSWORD=changeme-strong-password&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;POSTGRES_DB=postgres&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;postgres_data:/var/lib/postgresql/data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;backend&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;5432:5432&amp;quot;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis:7-alpine&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;backend&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis_data:/data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;6379:6379&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;postgres_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;redis_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Security note:&lt;/strong&gt; Do not expose PostgreSQL and Redis to the internet. Use&amp;nbsp;the &lt;code&gt;backend&lt;/code&gt; network for internal communication only. If you must expose ports, restrict them with &lt;span class="caps"&gt;UFW&lt;/span&gt; or&amp;nbsp;iptables.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Use Portainer&amp;#8217;s Environment&amp;nbsp;Variables&lt;/h3&gt;
&lt;p&gt;Store secrets in Portainer&amp;#8217;s &lt;strong&gt;Environment Variables&lt;/strong&gt; section when creating a stack. This keeps passwords out of your Git&amp;nbsp;repository.&lt;/p&gt;
&lt;h3&gt;Tip 2: Enable Stack&amp;nbsp;GitOps&lt;/h3&gt;
&lt;p&gt;Portainer can poll a Git repository&amp;nbsp;for &lt;code&gt;docker-compose.yml&lt;/code&gt; changes and auto-deploy. This turns your homelab into a GitOps workflow:
1. Push a new Compose file to GitHub.
2. Portainer detects the change and&amp;nbsp;redeploys.&lt;/p&gt;
&lt;h3&gt;Tip 3: Use Agent Mode for Remote&amp;nbsp;Hosts&lt;/h3&gt;
&lt;p&gt;If you have multiple homelab servers, install the Portainer Agent on&amp;nbsp;each:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9001&lt;/span&gt;:9001&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;portainer_agent&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--restart&lt;span class="o"&gt;=&lt;/span&gt;always&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;/var/run/docker.sock:/var/run/docker.sock&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;/var/lib/docker/volumes:/var/lib/docker/volumes&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;portainer/agent:latest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then add the agent endpoint in your main Portainer &lt;span class="caps"&gt;UI&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;Tip 4: Backup Portainer&amp;nbsp;Data&lt;/h3&gt;
&lt;p&gt;Portainer&amp;#8217;s database is in its named volume. Back it up&amp;nbsp;with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;--rm&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;portainer_data:/data&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;:/backup&lt;span class="w"&gt; &lt;/span&gt;alpine&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;tar&lt;span class="w"&gt; &lt;/span&gt;czf&lt;span class="w"&gt; &lt;/span&gt;/backup/portainer-backup.tar.gz&lt;span class="w"&gt; &lt;/span&gt;-C&lt;span class="w"&gt; &lt;/span&gt;/data&lt;span class="w"&gt; &lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Troubleshooting Common&amp;nbsp;Issues&lt;/h2&gt;
&lt;h3&gt;Problem 1: Portainer Shows &amp;#8220;Unable to Retrieve&amp;nbsp;Containers&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Cause:&lt;/strong&gt; The Docker socket is not mounted or Portainer lacks permissions.
&lt;strong&gt;Fix:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;stop&lt;span class="w"&gt; &lt;/span&gt;portainer
docker&lt;span class="w"&gt; &lt;/span&gt;rm&lt;span class="w"&gt; &lt;/span&gt;portainer
docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;...&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;/var/run/docker.sock:/var/run/docker.sock&lt;span class="w"&gt; &lt;/span&gt;...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Problem 2: Traefik Not Generating&amp;nbsp;Certificates&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Cause:&lt;/strong&gt; Port 80 is not reachable from the internet, or the &lt;span class="caps"&gt;DNS&lt;/span&gt; record is wrong.
&lt;strong&gt;Fix:&lt;/strong&gt; Ensure your router forwards port 80 and 443 to the Docker host. Verify &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;with &lt;code&gt;dig yourdomain.com&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Problem 3: Stack Deploy Fails with &amp;#8220;Network Not&amp;nbsp;Found&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Cause:&lt;/strong&gt; The stack references an external network&amp;nbsp;(e.g., &lt;code&gt;proxy&lt;/code&gt;) that does not exist.
&lt;strong&gt;Fix:&lt;/strong&gt; Create the network&amp;nbsp;first:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;network&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;proxy
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Or&amp;nbsp;set &lt;code&gt;external: false&lt;/code&gt; in the Compose&amp;nbsp;file.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Portainer transforms Docker from a &lt;span class="caps"&gt;CLI&lt;/span&gt;-only tool into a visual platform. With a single &lt;span class="caps"&gt;UI&lt;/span&gt;, you can manage reverse proxies, monitoring, databases, and dozens of apps. The stack-based deployment model keeps your homelab organized, reproducible, and&amp;nbsp;version-controlled.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Add apps:&lt;/strong&gt; Deploy Nextcloud, Jellyfin, Immich, and Pi-hole as separate&amp;nbsp;stacks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Set up &lt;span class="caps"&gt;HTTPS&lt;/span&gt;:&lt;/strong&gt; Ensure every public service has a valid Let&amp;#8217;s Encrypt certificate via&amp;nbsp;Traefik.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Monitor:&lt;/strong&gt; Use the Grafana stack to track &lt;span class="caps"&gt;CPU&lt;/span&gt;, memory, and container&amp;nbsp;health.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automate:&lt;/strong&gt; Enable GitOps or Watchtower for automatic image&amp;nbsp;updates.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mini PCs:&lt;/strong&gt; Beelink, Minisforum for running the Docker&amp;nbsp;host.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Storage:&lt;/strong&gt; Samsung 990 Pro NVMe, &lt;span class="caps"&gt;WD&lt;/span&gt; Red &lt;span class="caps"&gt;SATA&lt;/span&gt;&amp;nbsp;SSDs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Networking:&lt;/strong&gt; &lt;span class="caps"&gt;TP&lt;/span&gt;-Link Omada or UniFi for managed&amp;nbsp;switches.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;UPS&lt;/span&gt;:&lt;/strong&gt; &lt;span class="caps"&gt;APC&lt;/span&gt; Back-&lt;span class="caps"&gt;UPS&lt;/span&gt; for protecting the Docker&amp;nbsp;host.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;prerequisites&lt;/code&gt; → &lt;code&gt;docker-compose-for-beginners&lt;/code&gt; — &amp;#8220;learn Docker Compose basics&amp;nbsp;first&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;step-3&lt;/code&gt; → &lt;code&gt;immich-reverse-proxy&lt;/code&gt; — &amp;#8220;configure Traefik for&amp;nbsp;Immich&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;step-4&lt;/code&gt; → &lt;code&gt;docker-monitoring-grafana-prometheus&lt;/code&gt; — &amp;#8220;deep dive into homelab&amp;nbsp;monitoring&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;step-5&lt;/code&gt; → &lt;code&gt;nextcloud-self-hosted&lt;/code&gt; — &amp;#8220;connect Nextcloud to&amp;nbsp;PostgreSQL&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;best-self-hosted-apps-2026&lt;/code&gt; — &amp;#8220;apps to deploy in your Portainer&amp;nbsp;stacks&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;What&amp;#8217;s in your Portainer stack?&lt;/strong&gt; Share your Compose templates in the&amp;nbsp;comments.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subscribe&lt;/strong&gt; for Docker Compose recipes, Portainer tips, and homelab automation&amp;nbsp;guides.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Tutorials"/><category term="portainer"/><category term="docker compose"/><category term="stack"/><category term="homelab"/><category term="container management"/><category term="docker"/></entry><entry><title>Portainer vs Cockpit: Which Container Manager Wins for Your Homelab?</title><link href="https://steadypub.com/2026/06/portainer-vs-cockpit/" rel="alternate"/><published>2026-06-05T00:00:00+07:00</published><updated>2026-06-05T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/portainer-vs-cockpit/</id><summary type="html">&lt;p&gt;Compare Portainer and Cockpit for managing Docker containers and Linux servers. Features, ease of use, resource usage, and which tool fits your homelab&amp;nbsp;workflow.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~12 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelabbers choosing a web &lt;span class="caps"&gt;UI&lt;/span&gt; for container and server&amp;nbsp;management&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The Portainer vs Cockpit&amp;nbsp;Dilemma&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Both Portainer and Cockpit provide web-based management for your homelab, but they serve different purposes. Portainer is a Docker-centric container management platform. Cockpit is a Linux server administration tool with Docker/Podman as one of many features. Understanding their strengths helps you pick the right tool — or use&amp;nbsp;both.&lt;/p&gt;
&lt;h3&gt;Key Differences at a&amp;nbsp;Glance&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Portainer&lt;/th&gt;
&lt;th&gt;Cockpit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary focus&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Docker/Podman containers&lt;/td&gt;
&lt;td&gt;Linux server administration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Container management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;★★★☆☆&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;VM&lt;/span&gt; management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Limited (&lt;span class="caps"&gt;LXD&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;Yes (&lt;span class="caps"&gt;KVM&lt;/span&gt;/&lt;span class="caps"&gt;QEMU&lt;/span&gt; via libvirt)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;System monitoring&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Basic (container stats)&lt;/td&gt;
&lt;td&gt;Advanced (&lt;span class="caps"&gt;CPU&lt;/span&gt;, memory, storage, network, logs)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;User management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;RBAC&lt;/span&gt;, teams, external auth&lt;/td&gt;
&lt;td&gt;Local users, sudo-based&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Multi-node / clustering&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes (Portainer Agent)&lt;/td&gt;
&lt;td&gt;Yes (Cockpit Client, limited)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;App templates&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes (150+ community templates)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Compose support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Full Docker Compose stack editor&lt;/td&gt;
&lt;td&gt;Basic (Podman Compose)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Resource overhead&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~&lt;span class="caps"&gt;50MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;~&lt;span class="caps"&gt;20MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Learning curve&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Docker-focused homelabs&lt;/td&gt;
&lt;td&gt;Full Linux server management&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Option A: Portainer (Best for Docker-First&amp;nbsp;Homelabs)&lt;/h2&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Purpose-built for containers&lt;/strong&gt;: Every feature is designed around Docker and&amp;nbsp;Kubernetes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stack editor&lt;/strong&gt;: Edit and deploy Docker Compose files directly in the &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;App templates&lt;/strong&gt;: One-click deploy of 150+ popular apps (Nextcloud, Jellyfin, Pi-hole,&amp;nbsp;etc.)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;RBAC&lt;/span&gt; and teams&lt;/strong&gt;: Multi-user support with role-based access&amp;nbsp;control&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multi-node&lt;/strong&gt;: Manage Docker hosts across multiple servers from one &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Registry integration&lt;/strong&gt;: Pull from Docker Hub, private registries, or GitHub Container&amp;nbsp;Registry&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Container console&lt;/strong&gt;: Web-based terminal into any&amp;nbsp;container&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Volume management&lt;/strong&gt;: Browse, inspect, and prune&amp;nbsp;volumes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Networks&lt;/strong&gt;: Visualize and manage Docker&amp;nbsp;networks&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Backup/restore&lt;/strong&gt;: Export and import container&amp;nbsp;configurations&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Narrow scope&lt;/strong&gt;: No system-level monitoring, user management, or service&amp;nbsp;control&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security surface&lt;/strong&gt;: Requires Docker socket access (risk if exposed&amp;nbsp;publicly)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Kubernetes focus&lt;/strong&gt;: Recent versions push Kubernetes; Docker Swarm is&amp;nbsp;deprecated&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No &lt;span class="caps"&gt;VM&lt;/span&gt; support&lt;/strong&gt;: Can&amp;#8217;t manage &lt;span class="caps"&gt;KVM&lt;/span&gt;/&lt;span class="caps"&gt;QEMU&lt;/span&gt; virtual&amp;nbsp;machines&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pro features&lt;/strong&gt;: Some features (&lt;span class="caps"&gt;RBAC&lt;/span&gt;, registry management) require Business Edition ($99/year for 5&amp;nbsp;nodes)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Docker-heavy homelabs (10+&amp;nbsp;containers)&lt;/li&gt;
&lt;li&gt;Users who prefer &lt;span class="caps"&gt;GUI&lt;/span&gt; over &lt;span class="caps"&gt;CLI&lt;/span&gt; for container&amp;nbsp;operations&lt;/li&gt;
&lt;li&gt;Teams or families sharing a homelab (multi-user &lt;span class="caps"&gt;RBAC&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;Multi-server Docker&amp;nbsp;deployments&lt;/li&gt;
&lt;li&gt;Beginners who want one-click app&amp;nbsp;deployments&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Edition&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;th&gt;Features&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Community&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Single node, basic &lt;span class="caps"&gt;RBAC&lt;/span&gt;, templates, Compose support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Business&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$99/year (5 nodes)&lt;/td&gt;
&lt;td&gt;Multi-node, advanced &lt;span class="caps"&gt;RBAC&lt;/span&gt;, registry management, support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Enterprise&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Custom&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;SSO&lt;/span&gt;, 25+ nodes, premium support&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Option B: Cockpit (Best for Full Linux Server&amp;nbsp;Management)&lt;/h2&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;System-wide view&lt;/strong&gt;: &lt;span class="caps"&gt;CPU&lt;/span&gt;, memory, disk I/O, network, processes, and logs in one&amp;nbsp;place&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;VM&lt;/span&gt; management&lt;/strong&gt;: Create and manage &lt;span class="caps"&gt;KVM&lt;/span&gt;/&lt;span class="caps"&gt;QEMU&lt;/span&gt; VMs via libvirt&amp;nbsp;integration&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Storage management&lt;/strong&gt;: Format, mount, &lt;span class="caps"&gt;RAID&lt;/span&gt;, and &lt;span class="caps"&gt;LVM&lt;/span&gt; management via web &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Network management&lt;/strong&gt;: Configure network interfaces, firewall zones, and&amp;nbsp;bridging&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;User management&lt;/strong&gt;: Create, edit, and manage Linux users and&amp;nbsp;groups&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Service control&lt;/strong&gt;: Start, stop, and enable systemd&amp;nbsp;services&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Terminal access&lt;/strong&gt;: Built-in web terminal with root&amp;nbsp;access&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Podman support&lt;/strong&gt;: Native Podman container management (rootless&amp;nbsp;containers)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SELinux troubleshooting&lt;/strong&gt;: Visual audit logs and policy&amp;nbsp;adjustments&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Low overhead&lt;/strong&gt;: Runs as a systemd service with minimal resource&amp;nbsp;usage&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pre-installed&lt;/strong&gt;: Included by default in Fedora, &lt;span class="caps"&gt;RHEL&lt;/span&gt;, CentOS Stream, and Ubuntu&amp;nbsp;Server&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Basic container management&lt;/strong&gt;: No Compose support, no app templates, no registry&amp;nbsp;browser&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No multi-node clustering&lt;/strong&gt;: Each server is managed&amp;nbsp;individually&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No &lt;span class="caps"&gt;RBAC&lt;/span&gt;&lt;/strong&gt;: Single-user or shared sudo access&amp;nbsp;only&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No backup tools&lt;/strong&gt;: No built-in container config&amp;nbsp;export/import&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Limited Docker support&lt;/strong&gt;: Primarily targets Podman; Docker support is&amp;nbsp;secondary&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No stack management&lt;/strong&gt;: Can&amp;#8217;t define and deploy multi-container apps&amp;nbsp;declaratively&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Full Linux server administration (not just&amp;nbsp;containers)&lt;/li&gt;
&lt;li&gt;Users running &lt;span class="caps"&gt;KVM&lt;/span&gt; VMs alongside&amp;nbsp;Docker&lt;/li&gt;
&lt;li&gt;Red Hat/Fedora/CentOS&amp;nbsp;ecosystems&lt;/li&gt;
&lt;li&gt;Users who prefer Podman over&amp;nbsp;Docker&lt;/li&gt;
&lt;li&gt;System administrators learning Linux&amp;nbsp;tools&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Edition&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;th&gt;Features&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cockpit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Free (included in most distros)&lt;/td&gt;
&lt;td&gt;Full feature set&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cockpit Client&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Connect to remote servers via &lt;span class="caps"&gt;SSH&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Option C: Use Both (Best for Advanced&amp;nbsp;Homelabs)&lt;/h2&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;p&gt;Portainer and Cockpit are complementary. Run Cockpit for system-level tasks (storage, networking, VMs, updates) and Portainer for container-level tasks (deploying apps, managing stacks, browsing&amp;nbsp;logs).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example workflow:&lt;/strong&gt;
1. &lt;strong&gt;Cockpit&lt;/strong&gt;: Create a new &lt;span class="caps"&gt;ZFS&lt;/span&gt; pool or format a disk
2. &lt;strong&gt;Portainer&lt;/strong&gt;: Deploy a Jellyfin container that mounts the new storage
3. &lt;strong&gt;Cockpit&lt;/strong&gt;: Check system resource usage after deployment
4. &lt;strong&gt;Portainer&lt;/strong&gt;: Update the container image when a new release&amp;nbsp;drops&lt;/p&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Two UIs to remember&lt;/strong&gt;: Slightly more cognitive&amp;nbsp;load&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Two ports to expose&lt;/strong&gt;: Portainer (9000/9443) and Cockpit&amp;nbsp;(9090)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Potential overlap&lt;/strong&gt;: Both show container stats; choose your source of&amp;nbsp;truth&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Advanced homelabs with both VMs and&amp;nbsp;containers&lt;/li&gt;
&lt;li&gt;Users who want the best tool for each&amp;nbsp;job&lt;/li&gt;
&lt;li&gt;Sysadmins who want system visibility + container&amp;nbsp;management&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Comparison&amp;nbsp;Matrix&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;Portainer&lt;/th&gt;
&lt;th&gt;Cockpit&lt;/th&gt;
&lt;th&gt;Winner&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Deploy Nextcloud via Docker Compose&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;★★☆☆☆&lt;/td&gt;
&lt;td&gt;Portainer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Manage &lt;span class="caps"&gt;KVM&lt;/span&gt; VMs&lt;/td&gt;
&lt;td&gt;★☆☆☆☆&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;Cockpit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;View system &lt;span class="caps"&gt;CPU&lt;/span&gt;/&lt;span class="caps"&gt;RAM&lt;/span&gt;/disk&lt;/td&gt;
&lt;td&gt;★★☆☆☆&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;Cockpit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Browse container logs&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;★★★☆☆&lt;/td&gt;
&lt;td&gt;Portainer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;One-click app install&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;★☆☆☆☆&lt;/td&gt;
&lt;td&gt;Portainer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Format and mount disks&lt;/td&gt;
&lt;td&gt;★☆☆☆☆&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;Cockpit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Manage firewall rules&lt;/td&gt;
&lt;td&gt;★☆☆☆☆&lt;/td&gt;
&lt;td&gt;★★★★☆&lt;/td&gt;
&lt;td&gt;Cockpit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Update container images&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;★★☆☆☆&lt;/td&gt;
&lt;td&gt;Portainer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-node management&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;★★☆☆☆&lt;/td&gt;
&lt;td&gt;Portainer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Manage systemd services&lt;/td&gt;
&lt;td&gt;★☆☆☆☆&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;Cockpit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rootless container security&lt;/td&gt;
&lt;td&gt;★★☆☆☆&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;td&gt;Cockpit&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Which Should You&amp;nbsp;Choose?&lt;/h2&gt;
&lt;h3&gt;Scenario 1: Docker-Only&amp;nbsp;Homelab&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose:&amp;nbsp;Portainer&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If your homelab is 100% containers (no VMs), Portainer is the obvious choice. It has the best Compose support, app templates, and container management&amp;nbsp;features.&lt;/p&gt;
&lt;h3&gt;Scenario 2: Mixed VMs and&amp;nbsp;Containers&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose: Cockpit +&amp;nbsp;Portainer&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Run both. Use Cockpit for Proxmox/&lt;span class="caps"&gt;KVM&lt;/span&gt; VMs and system administration. Use Portainer for Docker. They complement each other&amp;nbsp;perfectly.&lt;/p&gt;
&lt;h3&gt;Scenario 3: Minimalist / Low-Resource&amp;nbsp;Setup&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose:&amp;nbsp;Cockpit&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you run a single Raspberry Pi or N100 with &lt;span class="caps"&gt;8GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, Cockpit has lower overhead and covers both system and container basics without the&amp;nbsp;bloat.&lt;/p&gt;
&lt;h3&gt;Scenario 4: Learning Linux&amp;nbsp;Administration&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose:&amp;nbsp;Cockpit&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Cockpit teaches you real Linux concepts (systemd, &lt;span class="caps"&gt;LVM&lt;/span&gt;, NetworkManager, firewall zones) that transfer directly to &lt;span class="caps"&gt;CLI&lt;/span&gt; skills. Portainer abstracts these&amp;nbsp;away.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Migration&amp;nbsp;Path&lt;/h2&gt;
&lt;h3&gt;Step 1: Start with&amp;nbsp;Portainer&lt;/h3&gt;
&lt;p&gt;If you&amp;#8217;re new to Docker, install Portainer first. It makes learning containers much&amp;nbsp;easier.&lt;/p&gt;
&lt;h3&gt;Step 2: Add Cockpit for System&amp;nbsp;Tasks&lt;/h3&gt;
&lt;p&gt;When you need to manage storage, networking, or VMs, install Cockpit alongside&amp;nbsp;Portainer.&lt;/p&gt;
&lt;h3&gt;Step 3: Graduate to &lt;span class="caps"&gt;CLI&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Both tools are training wheels. As you learn, you&amp;#8217;ll naturally move&amp;nbsp;to &lt;code&gt;docker compose&lt;/code&gt;, &lt;code&gt;systemctl&lt;/code&gt;, &lt;code&gt;nmcli&lt;/code&gt;,&amp;nbsp;and &lt;code&gt;virsh&lt;/code&gt;. The UIs remain useful for quick checks and&amp;nbsp;visualizations.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The&amp;nbsp;Verdict&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;Recommendation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Docker-first homelab&lt;/td&gt;
&lt;td&gt;Portainer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mixed VMs + containers&lt;/td&gt;
&lt;td&gt;Cockpit + Portainer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Learning Linux admin&lt;/td&gt;
&lt;td&gt;Cockpit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Minimalist / low resource&lt;/td&gt;
&lt;td&gt;Cockpit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-node Docker clusters&lt;/td&gt;
&lt;td&gt;Portainer Business&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Red Hat / Fedora ecosystem&lt;/td&gt;
&lt;td&gt;Cockpit (native integration)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Portainer is the king of Docker management. Cockpit is the king of Linux server administration. Most advanced homelabs benefit from running both. Beginners should start with Portainer for containers; system administrators should start with Cockpit for the full&amp;nbsp;picture.&lt;/p&gt;
&lt;h3&gt;Ready to Get&amp;nbsp;Started?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Read our &lt;a href="portainer-setup-guide"&gt;Portainer setup guide&lt;/a&gt; for Docker&amp;nbsp;deployment&lt;/li&gt;
&lt;li&gt;Read our &lt;a href="proxmox-beginner-guide-2026"&gt;Proxmox beginner guide&lt;/a&gt; for &lt;span class="caps"&gt;VM&lt;/span&gt;&amp;nbsp;management&lt;/li&gt;
&lt;li&gt;Read our &lt;a href="docker-compose-for-beginners"&gt;Docker Compose for beginners&lt;/a&gt; for stack&amp;nbsp;management&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Beelink Mini S12 Pro&lt;/strong&gt;: Hardware for running both Portainer and&amp;nbsp;Cockpit&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;&lt;/strong&gt;: Free hypervisor for &lt;span class="caps"&gt;VM&lt;/span&gt;&amp;nbsp;management&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;intro&lt;/code&gt; → &lt;code&gt;portainer-setup-guide&lt;/code&gt; for Portainer&amp;nbsp;deployment&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scenario-2&lt;/code&gt; → &lt;code&gt;proxmox-beginner-guide-2026&lt;/code&gt; for &lt;span class="caps"&gt;VM&lt;/span&gt;&amp;nbsp;management&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;docker-compose-for-beginners&lt;/code&gt; for Compose&amp;nbsp;basics&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] Do you use Portainer, Cockpit, or both? Share your&amp;nbsp;workflow!&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for weekly homelab tool comparisons and setup&amp;nbsp;guides.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Comparisons"/><category term="portainer vs cockpit"/><category term="docker management"/><category term="container management"/><category term="homelab"/><category term="linux admin"/><category term="web ui"/></entry><entry><title>Prometheus Monitoring for Homelab: Metrics, Alerts, and Grafana</title><link href="https://steadypub.com/2026/06/prometheus-monitoring-homelab/" rel="alternate"/><published>2026-06-05T00:00:00+07:00</published><updated>2026-06-05T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/prometheus-monitoring-homelab/</id><summary type="html">&lt;p&gt;Set up Prometheus monitoring for your homelab with Docker Compose. Collect metrics from Proxmox, Docker, nodes, and services. Configure alerts and prepare for Grafana&amp;nbsp;dashboards.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~14 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelabbers wanting observability for their&amp;nbsp;infrastructure&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is&amp;nbsp;Prometheus?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Prometheus is an open-source monitoring and alerting toolkit designed for reliability and scalability. It collects metrics from configured targets at given intervals, stores them in a time-series database, and allows querying via PromQL. It is the de facto standard for cloud-native monitoring and works perfectly for homelab&amp;nbsp;observability.&lt;/p&gt;
&lt;h3&gt;Key&amp;nbsp;Benefits&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Benefit&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Pull-based&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Prometheus scrapes targets — no agent push needed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Time-series &lt;span class="caps"&gt;DB&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Efficient storage of numeric metrics over time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PromQL&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Powerful query language for alerts and dashboards&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Exporters&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hundreds of community exporters for hardware, apps, and services&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Alertmanager&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Route alerts to email, Slack, Telegram, or webhooks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Service discovery&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Auto-detect Docker containers, Kubernetes pods, or &lt;span class="caps"&gt;DNS&lt;/span&gt; entries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Native Grafana&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;First-class integration with Grafana dashboards&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;h3&gt;Hardware&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Any Docker host (mini &lt;span class="caps"&gt;PC&lt;/span&gt;, server, or &lt;span class="caps"&gt;VM&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;1GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; for Prometheus + Alertmanager + Node&amp;nbsp;Exporter&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;10GB&lt;/span&gt;+ storage for metrics retention (varies by scrape frequency and&amp;nbsp;targets)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Software&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Docker Engine 24.x+ and Docker Compose&amp;nbsp;v2+&lt;/li&gt;
&lt;li&gt;Linux host with persistent&amp;nbsp;storage&lt;/li&gt;
&lt;li&gt;Basic understanding of &lt;span class="caps"&gt;YAML&lt;/span&gt; and&amp;nbsp;networking&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Knowledge&amp;nbsp;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Docker Compose&amp;nbsp;basics&lt;/li&gt;
&lt;li&gt;Understanding of metrics and time-series&amp;nbsp;data&lt;/li&gt;
&lt;li&gt;Basic &lt;span class="caps"&gt;YAML&lt;/span&gt;&amp;nbsp;editing&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Deploy Prometheus Stack with Docker&amp;nbsp;Compose&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Run Prometheus, Node Exporter, and Alertmanager in Docker with persistent&amp;nbsp;storage.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Create the project&amp;nbsp;directory:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;~/docker/prometheus&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/docker/prometheus
mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;prometheus_data&lt;span class="w"&gt; &lt;/span&gt;alertmanager_data
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Create &lt;code&gt;prometheus.yml&lt;/code&gt; configuration:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;global&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;scrape_interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;15s&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;evaluation_interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;15s&lt;/span&gt;

&lt;span class="nt"&gt;alerting&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;alertmanagers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;alertmanager:9093&lt;/span&gt;

&lt;span class="nt"&gt;rule_files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/etc/prometheus/rules/*.yml&lt;/span&gt;

&lt;span class="nt"&gt;scrape_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;prometheus&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;localhost:9090&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;node-exporter&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;node-exporter:9100&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;cadvisor&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;cadvisor:8080&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;docker&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;docker-exporter:9323&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Create &lt;code&gt;alertmanager.yml&lt;/code&gt;:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;route&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;receiver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;default&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;group_wait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;30s&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;group_interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;5m&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;repeat_interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;4h&lt;/span&gt;

&lt;span class="nt"&gt;receivers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;default&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;email_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;your-email@example.com&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;alertmanager@homelab.local&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;smarthost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;smtp.gmail.com:587&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;auth_username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;your-email@example.com&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;auth_password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;your-app-password&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;require_tls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Create &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;prometheus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;prom/prometheus:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;prometheus&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;9090:9090&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./prometheus.yml:/etc/prometheus/prometheus.yml:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./rules:/etc/prometheus/rules:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./prometheus_data:/prometheus&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--config.file=/etc/prometheus/prometheus.yml&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--storage.tsdb.path=/prometheus&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--storage.tsdb.retention.time=30d&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--web.enable-lifecycle&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;monitoring&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;alertmanager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;prom/alertmanager:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;alertmanager&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;9093:9093&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./alertmanager_data:/alertmanager&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;monitoring&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;node-exporter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;prom/node-exporter:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;node-exporter&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/proc:/host/proc:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/sys:/host/sys:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/:/rootfs:ro&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--path.procfs=/host/proc&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--path.rootfs=/rootfs&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--path.sysfs=/host/sys&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;monitoring&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;cadvisor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;gcr.io/cadvisor/cadvisor:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;cadvisor&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;privileged&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/:/rootfs:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/var/run:/var/run:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/sys:/sys:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/var/lib/docker/:/var/lib/docker:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/dev/disk/:/dev/disk:ro&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;monitoring&lt;/span&gt;

&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;monitoring&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;bridge&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Create alert rules directory and&amp;nbsp;file:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;rules
cat&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&amp;lt; &amp;#39;EOF&amp;#39; &amp;gt; rules/homelab.yml&lt;/span&gt;
&lt;span class="s"&gt;groups:&lt;/span&gt;
&lt;span class="s"&gt;  - name: homelab&lt;/span&gt;
&lt;span class="s"&gt;    rules:&lt;/span&gt;
&lt;span class="s"&gt;      - alert: HighCPUUsage&lt;/span&gt;
&lt;span class="s"&gt;        expr: 100 - (avg by (instance) (irate(node_cpu_seconds_total{mode=&amp;quot;idle&amp;quot;}[5m])) * 100) &amp;gt; 80&lt;/span&gt;
&lt;span class="s"&gt;        for: 5m&lt;/span&gt;
&lt;span class="s"&gt;        labels:&lt;/span&gt;
&lt;span class="s"&gt;          severity: warning&lt;/span&gt;
&lt;span class="s"&gt;        annotations:&lt;/span&gt;
&lt;span class="s"&gt;          summary: &amp;quot;High CPU usage on {{ $labels.instance }}&amp;quot;&lt;/span&gt;
&lt;span class="s"&gt;          description: &amp;quot;CPU usage is above 80% for more than 5 minutes.&amp;quot;&lt;/span&gt;

&lt;span class="s"&gt;      - alert: LowDiskSpace&lt;/span&gt;
&lt;span class="s"&gt;        expr: (node_filesystem_avail_bytes / node_filesystem_size_bytes) &amp;lt; 0.1&lt;/span&gt;
&lt;span class="s"&gt;        for: 5m&lt;/span&gt;
&lt;span class="s"&gt;        labels:&lt;/span&gt;
&lt;span class="s"&gt;          severity: critical&lt;/span&gt;
&lt;span class="s"&gt;        annotations:&lt;/span&gt;
&lt;span class="s"&gt;          summary: &amp;quot;Low disk space on {{ $labels.instance }}&amp;quot;&lt;/span&gt;
&lt;span class="s"&gt;          description: &amp;quot;Disk space is below 10% on {{ $labels.mountpoint }}.&amp;quot;&lt;/span&gt;

&lt;span class="s"&gt;      - alert: HighMemoryUsage&lt;/span&gt;
&lt;span class="s"&gt;        expr: (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes &amp;gt; 0.85&lt;/span&gt;
&lt;span class="s"&gt;        for: 5m&lt;/span&gt;
&lt;span class="s"&gt;        labels:&lt;/span&gt;
&lt;span class="s"&gt;          severity: warning&lt;/span&gt;
&lt;span class="s"&gt;        annotations:&lt;/span&gt;
&lt;span class="s"&gt;          summary: &amp;quot;High memory usage on {{ $labels.instance }}&amp;quot;&lt;/span&gt;
&lt;span class="s"&gt;          description: &amp;quot;Memory usage is above 85% for more than 5 minutes.&amp;quot;&lt;/span&gt;
&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Deploy:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Verify:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Prometheus &lt;span class="caps"&gt;UI&lt;/span&gt;: &lt;code&gt;http://your-server-ip:9090&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Alertmanager: &lt;code&gt;http://your-server-ip:9093&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Targets: &lt;code&gt;http://your-server-ip:9090/targets&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Step 2: Add Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;&amp;nbsp;Exporter&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Monitor Proxmox host metrics including &lt;span class="caps"&gt;VM&lt;/span&gt;/&lt;span class="caps"&gt;LXC&lt;/span&gt; status, storage, and node&amp;nbsp;resources.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;On Proxmox host, create a monitoring&amp;nbsp;user:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pveum&lt;span class="w"&gt; &lt;/span&gt;user&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt; &lt;/span&gt;monitoring@pve&lt;span class="w"&gt; &lt;/span&gt;--password&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Change...3!&amp;quot;&lt;/span&gt;
pveum&lt;span class="w"&gt; &lt;/span&gt;aclmod&lt;span class="w"&gt; &lt;/span&gt;/&lt;span class="w"&gt; &lt;/span&gt;-user&lt;span class="w"&gt; &lt;/span&gt;monitoring@pve&lt;span class="w"&gt; &lt;/span&gt;-role&lt;span class="w"&gt; &lt;/span&gt;PVEAuditor
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Add&amp;nbsp;to &lt;code&gt;prometheus.yml&lt;/code&gt;:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;proxmox&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;proxmox.example.com:9221&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;metrics_path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/pve&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;module&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;default&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Deploy Proxmox exporter&amp;nbsp;container:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;proxmox-exporter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;prompve/prometheus-pve-exporter:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;proxmox-exporter&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;PVE_USER=monitoring@pve&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;PVE_PASSWORD=Change...3!&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;PVE_HOST=https://192.168.1.10:8006&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;9221:9221&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;monitoring&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 3: Configure Docker Daemon&amp;nbsp;Metrics&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Enable Docker&amp;#8217;s built-in metrics endpoint for&amp;nbsp;Prometheus.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Edit &lt;code&gt;/etc/docker/daemon.json&lt;/code&gt;:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;metrics-addr&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;0.0.0.0:9323&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;experimental&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Restart&amp;nbsp;Docker:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;restart&lt;span class="w"&gt; &lt;/span&gt;docker
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Prometheus already scrapes this target&lt;/strong&gt; via&amp;nbsp;the &lt;code&gt;docker&lt;/code&gt; job&amp;nbsp;in &lt;code&gt;prometheus.yml&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Use Recording Rules for Complex&amp;nbsp;Queries&lt;/h3&gt;
&lt;p&gt;Recording rules pre-compute expensive PromQL queries. Add them&amp;nbsp;to &lt;code&gt;rules/homelab.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;recording&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;record&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;instance:cpu_usage&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;100 - (avg by (instance) (irate(node_cpu_seconds_total{mode=&amp;quot;idle&amp;quot;}[5m])) * 100)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 2: Limit Retention for&amp;nbsp;Storage&lt;/h3&gt;
&lt;p&gt;The default 30-day retention is usually enough for homelab. If storage is tight, reduce to 15&amp;nbsp;days:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--storage.tsdb.retention.time=15d&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 3: Backup Prometheus&amp;nbsp;Data&lt;/h3&gt;
&lt;p&gt;Prometheus data is&amp;nbsp;in &lt;code&gt;./prometheus_data&lt;/code&gt;. Back it up&amp;nbsp;with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/docker/prometheus
tar&lt;span class="w"&gt; &lt;/span&gt;czvf&lt;span class="w"&gt; &lt;/span&gt;prometheus-backup-&lt;span class="k"&gt;$(&lt;/span&gt;date&lt;span class="w"&gt; &lt;/span&gt;+%F&lt;span class="k"&gt;)&lt;/span&gt;.tar.gz&lt;span class="w"&gt; &lt;/span&gt;prometheus_data
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 4: Use Grafana for&amp;nbsp;Visualization&lt;/h3&gt;
&lt;p&gt;Prometheus&amp;#8217;s built-in &lt;span class="caps"&gt;UI&lt;/span&gt; is for debugging. Install Grafana for dashboards. See our &lt;a href="grafana-docker-compose"&gt;Grafana Docker Compose guide&lt;/a&gt; for&amp;nbsp;setup.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Troubleshooting Common&amp;nbsp;Issues&lt;/h2&gt;
&lt;h3&gt;Problem 1: &amp;#8220;Targets Show as&amp;nbsp;Down&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Cause:&lt;/strong&gt; Network connectivity or container name resolution&amp;nbsp;issues.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Test connectivity from Prometheus container&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;prometheus&lt;span class="w"&gt; &lt;/span&gt;wget&lt;span class="w"&gt; &lt;/span&gt;-qO-&lt;span class="w"&gt; &lt;/span&gt;http://node-exporter:9100/metrics

&lt;span class="c1"&gt;# Check Prometheus logs&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;logs&lt;span class="w"&gt; &lt;/span&gt;prometheus
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Problem 2: &amp;#8220;No Data in&amp;nbsp;Queries&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Cause:&lt;/strong&gt; Scrape interval too long, or target not&amp;nbsp;configured.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;
-&amp;nbsp;Reduce &lt;code&gt;scrape_interval&lt;/code&gt; to 15s
- Verify targets&amp;nbsp;at &lt;code&gt;http://your-server-ip:9090/targets&lt;/code&gt;
- Check exporter is&amp;nbsp;running: &lt;code&gt;docker ps | grep exporter&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;Problem 3: &amp;#8220;Alertmanager Not Sending&amp;nbsp;Emails&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Cause:&lt;/strong&gt; &lt;span class="caps"&gt;SMTP&lt;/span&gt; settings or authentication&amp;nbsp;issues.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;
- Use an app-specific password (not your main password) for Gmail
- Test &lt;span class="caps"&gt;SMTP&lt;/span&gt;&amp;nbsp;with &lt;code&gt;swaks&lt;/code&gt; or &lt;code&gt;msmtp&lt;/code&gt;
- Check Alertmanager&amp;nbsp;logs: &lt;code&gt;docker logs alertmanager&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Prometheus gives you powerful observability over your homelab. With Node Exporter, cAdvisor, and the Proxmox exporter, you can monitor &lt;span class="caps"&gt;CPU&lt;/span&gt;, memory, disk, container, and &lt;span class="caps"&gt;VM&lt;/span&gt; metrics. Combined with Alertmanager, you&amp;#8217;ll know immediately when something&amp;nbsp;breaks.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Install &lt;a href="grafana-docker-compose"&gt;Grafana&lt;/a&gt; for beautiful&amp;nbsp;dashboards&lt;/li&gt;
&lt;li&gt;Add &lt;a href="grafana-loki-logs"&gt;Loki&lt;/a&gt; for log&amp;nbsp;aggregation&lt;/li&gt;
&lt;li&gt;Compare with &lt;a href="prometheus-vs-influxdb"&gt;InfluxDB&lt;/a&gt; for alternative&amp;nbsp;storage&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Samsung 990 &lt;span class="caps"&gt;EVO&lt;/span&gt;&lt;/strong&gt;: Fast NVMe for Prometheus&amp;nbsp;storage&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Beelink Mini S12 Pro&lt;/strong&gt;: Mini &lt;span class="caps"&gt;PC&lt;/span&gt; for monitoring&amp;nbsp;stack&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;intro&lt;/code&gt; → &lt;code&gt;grafana-docker-compose&lt;/code&gt; for dashboard&amp;nbsp;visualization&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tip-4&lt;/code&gt; → &lt;code&gt;grafana-prometheus-setup&lt;/code&gt; for integrated&amp;nbsp;setup&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;prometheus-vs-influxdb&lt;/code&gt; for storage&amp;nbsp;comparison&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] What&amp;#8217;s your homelab monitoring stack? Prometheus, InfluxDB, or something&amp;nbsp;else?&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for weekly observability and homelab monitoring&amp;nbsp;guides.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Tutorials"/><category term="prometheus"/><category term="monitoring"/><category term="homelab"/><category term="metrics"/><category term="alerting"/><category term="docker"/><category term="grafana"/></entry><entry><title>How to Create Your First VM on Proxmox: A Step-by-Step Tutorial</title><link href="https://steadypub.com/2026/06/proxmox-first-vm-tutorial/" rel="alternate"/><published>2026-06-05T00:00:00+07:00</published><updated>2026-06-05T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/proxmox-first-vm-tutorial/</id><summary type="html">&lt;p&gt;A beginner-friendly walkthrough for creating your first virtual machine on Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;. Covers Ubuntu Server, resource allocation, networking, and&amp;nbsp;cloud-init.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~12 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Proxmox beginners who have just installed the&amp;nbsp;hypervisor&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is a Proxmox &lt;span class="caps"&gt;VM&lt;/span&gt;?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;A Virtual Machine (&lt;span class="caps"&gt;VM&lt;/span&gt;) on Proxmox is a full computer emulated in software. It has its own virtual &lt;span class="caps"&gt;CPU&lt;/span&gt;, &lt;span class="caps"&gt;RAM&lt;/span&gt;, disk, and network card. Unlike a container (&lt;span class="caps"&gt;LXC&lt;/span&gt;), a &lt;span class="caps"&gt;VM&lt;/span&gt; runs its own kernel and can run any operating system—Windows, Linux, &lt;span class="caps"&gt;BSD&lt;/span&gt;, or even macOS (with hacks). This tutorial walks you through creating an Ubuntu Server 24.04 &lt;span class="caps"&gt;LTS&lt;/span&gt; &lt;span class="caps"&gt;VM&lt;/span&gt;, the standard starting point for most homelab&amp;nbsp;services.&lt;/p&gt;
&lt;h3&gt;Key&amp;nbsp;Benefits&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Isolation:&lt;/strong&gt; A crashed &lt;span class="caps"&gt;VM&lt;/span&gt; does not affect the host or other&amp;nbsp;VMs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Snapshots:&lt;/strong&gt; Freeze the entire &lt;span class="caps"&gt;VM&lt;/span&gt; state before updates. Roll back in&amp;nbsp;seconds.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hardware flexibility:&lt;/strong&gt; Add or remove &lt;span class="caps"&gt;RAM&lt;/span&gt;, &lt;span class="caps"&gt;CPU&lt;/span&gt; cores, and disks without opening a&amp;nbsp;case.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Migration:&lt;/strong&gt; Move a running &lt;span class="caps"&gt;VM&lt;/span&gt; to another Proxmox node (with shared&amp;nbsp;storage).&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;h3&gt;Hardware&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Proxmox host installed (bare metal or&amp;nbsp;nested)&lt;/li&gt;
&lt;li&gt;At least 4 &lt;span class="caps"&gt;GB&lt;/span&gt; free &lt;span class="caps"&gt;RAM&lt;/span&gt; on the&amp;nbsp;host&lt;/li&gt;
&lt;li&gt;At least 20 &lt;span class="caps"&gt;GB&lt;/span&gt; free storage (local-lvm, &lt;span class="caps"&gt;ZFS&lt;/span&gt;, or &lt;span class="caps"&gt;NFS&lt;/span&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Software&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Ubuntu Server 24.04 &lt;span class="caps"&gt;LTS&lt;/span&gt; &lt;span class="caps"&gt;ISO&lt;/span&gt; (download from &lt;a href="https://ubuntu.com/download/server"&gt;ubuntu.com&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Proxmox web &lt;span class="caps"&gt;UI&lt;/span&gt; access&amp;nbsp;(https://your-proxmox-ip:8006)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Knowledge&amp;nbsp;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Basic understanding of &lt;span class="caps"&gt;IP&lt;/span&gt; addresses and&amp;nbsp;subnetting&lt;/li&gt;
&lt;li&gt;Comfort with a Linux terminal (&lt;span class="caps"&gt;SSH&lt;/span&gt; or web&amp;nbsp;shell)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Upload the Ubuntu &lt;span class="caps"&gt;ISO&lt;/span&gt; to&amp;nbsp;Proxmox&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Before you can install a &lt;span class="caps"&gt;VM&lt;/span&gt;, Proxmox needs access to the installation media. You upload the &lt;span class="caps"&gt;ISO&lt;/span&gt; to the node&amp;#8217;s local&amp;nbsp;storage.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Log in to the Proxmox web &lt;span class="caps"&gt;UI&lt;/span&gt;&amp;nbsp;(&lt;code&gt;https://&amp;lt;proxmox-ip&amp;gt;:8006&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Select your node in the left sidebar&amp;nbsp;(e.g., &lt;code&gt;pve&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;local&lt;/strong&gt; under the node, then the &lt;strong&gt;&lt;span class="caps"&gt;ISO&lt;/span&gt; Images&lt;/strong&gt;&amp;nbsp;tab.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Upload&lt;/strong&gt; and select your Ubuntu Server 24.04 &lt;span class="caps"&gt;ISO&lt;/span&gt;&amp;nbsp;file.&lt;/li&gt;
&lt;li&gt;Wait for the upload to complete. The &lt;span class="caps"&gt;ISO&lt;/span&gt; will appear in the&amp;nbsp;list.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Alternative (&lt;span class="caps"&gt;CLI&lt;/span&gt;):&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# SSH into Proxmox&lt;/span&gt;
scp&lt;span class="w"&gt; &lt;/span&gt;ubuntu-24.04-live-server-amd64.iso&lt;span class="w"&gt; &lt;/span&gt;root@&amp;lt;proxmox-ip&amp;gt;:/var/lib/vz/template/iso/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 2: Create the &lt;span class="caps"&gt;VM&lt;/span&gt;&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Create a new &lt;span class="caps"&gt;VM&lt;/span&gt; with 2 &lt;span class="caps"&gt;CPU&lt;/span&gt; cores, 4 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, and a 32 &lt;span class="caps"&gt;GB&lt;/span&gt;&amp;nbsp;disk.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Click the &lt;strong&gt;Create &lt;span class="caps"&gt;VM&lt;/span&gt;&lt;/strong&gt; button in the top&amp;nbsp;right.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;General&amp;nbsp;Tab:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;VM&lt;/span&gt; &lt;span class="caps"&gt;ID&lt;/span&gt;:&lt;/strong&gt; 100 (or the next available &lt;span class="caps"&gt;ID&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Name:&lt;/strong&gt; &lt;code&gt;ubuntu-server-01&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Start at boot:&lt;/strong&gt; Unchecked (for&amp;nbsp;now)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;OS&lt;/span&gt;&amp;nbsp;Tab:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use &lt;span class="caps"&gt;CD&lt;/span&gt;/&lt;span class="caps"&gt;DVD&lt;/span&gt; disc image file:&lt;/strong&gt; Select the Ubuntu &lt;span class="caps"&gt;ISO&lt;/span&gt; you&amp;nbsp;uploaded.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Guest &lt;span class="caps"&gt;OS&lt;/span&gt; Type:&lt;/strong&gt;&amp;nbsp;Linux&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Version:&lt;/strong&gt; 6.x - 2.6 Kernel (or Ubuntu 24.04 if&amp;nbsp;available)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;System&amp;nbsp;Tab:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Machine:&lt;/strong&gt; q35 (modern, supports PCIe&amp;nbsp;passthrough)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;BIOS&lt;/span&gt;:&lt;/strong&gt; SeaBIOS (default) or &lt;span class="caps"&gt;OVMF&lt;/span&gt; for &lt;span class="caps"&gt;UEFI&lt;/span&gt;. For beginners, use&amp;nbsp;SeaBIOS.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Add &lt;span class="caps"&gt;EFI&lt;/span&gt; Disk:&lt;/strong&gt; Not needed for&amp;nbsp;SeaBIOS.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;QEMU&lt;/span&gt; Agent:&lt;/strong&gt; Check &lt;strong&gt;Use &lt;span class="caps"&gt;QEMU&lt;/span&gt; Agent&lt;/strong&gt; (enables guest reporting and shutdown from&amp;nbsp;host).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Disks&amp;nbsp;Tab:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bus/Device:&lt;/strong&gt; &lt;span class="caps"&gt;SCSI&lt;/span&gt;&amp;nbsp;(default)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Storage:&lt;/strong&gt; local-lvm (or your &lt;span class="caps"&gt;ZFS&lt;/span&gt;&amp;nbsp;pool)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Disk size:&lt;/strong&gt; 32 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cache:&lt;/strong&gt; Write back&amp;nbsp;(default)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Discard:&lt;/strong&gt; Check (helps with thin provisioning on&amp;nbsp;SSDs)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&amp;nbsp;Tab:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sockets:&lt;/strong&gt;&amp;nbsp;1&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cores:&lt;/strong&gt;&amp;nbsp;2&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Type:&lt;/strong&gt; host (passes host &lt;span class="caps"&gt;CPU&lt;/span&gt; features for best&amp;nbsp;performance)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Memory&amp;nbsp;Tab:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Memory:&lt;/strong&gt; 4096 &lt;span class="caps"&gt;MB&lt;/span&gt; (4 &lt;span class="caps"&gt;GB&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ballooning:&lt;/strong&gt; Unchecked (for beginners, keep it&amp;nbsp;simple)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Network&amp;nbsp;Tab:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bridge:&lt;/strong&gt; vmbr0 (default &lt;span class="caps"&gt;LAN&lt;/span&gt;&amp;nbsp;bridge)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;VLAN&lt;/span&gt; Tag:&lt;/strong&gt; Leave blank (or set if you use&amp;nbsp;VLANs)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Firewall:&lt;/strong&gt; Checked (Proxmox firewall rules will&amp;nbsp;apply)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Confirm Tab:&lt;/strong&gt; Review the summary. Click &lt;strong&gt;Finish&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The &lt;span class="caps"&gt;VM&lt;/span&gt; will appear in the left&amp;nbsp;sidebar.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 3: Install Ubuntu&amp;nbsp;Server&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Boot the &lt;span class="caps"&gt;VM&lt;/span&gt; from the &lt;span class="caps"&gt;ISO&lt;/span&gt; and install Ubuntu&amp;nbsp;Server.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Select the &lt;span class="caps"&gt;VM&lt;/span&gt;&amp;nbsp;(&lt;code&gt;ubuntu-server-01&lt;/code&gt;) and click &lt;strong&gt;Start&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Console&lt;/strong&gt; to open the &lt;span class="caps"&gt;VNC&lt;/span&gt;&amp;nbsp;window.&lt;/li&gt;
&lt;li&gt;The &lt;span class="caps"&gt;VM&lt;/span&gt; will boot from the &lt;span class="caps"&gt;ISO&lt;/span&gt;. Select &lt;strong&gt;Try or Install Ubuntu Server&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Language:&lt;/strong&gt;&amp;nbsp;English&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Keyboard layout:&lt;/strong&gt; &lt;span class="caps"&gt;US&lt;/span&gt; (or your&amp;nbsp;layout)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Network:&lt;/strong&gt; The &lt;span class="caps"&gt;VM&lt;/span&gt; will get an &lt;span class="caps"&gt;IP&lt;/span&gt; from your &lt;span class="caps"&gt;LAN&lt;/span&gt; &lt;span class="caps"&gt;DHCP&lt;/span&gt;&amp;nbsp;(e.g., &lt;code&gt;192.168.1.101&lt;/code&gt;). Note this &lt;span class="caps"&gt;IP&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Proxy:&lt;/strong&gt; Leave blank (unless you have a corporate&amp;nbsp;proxy)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mirror:&lt;/strong&gt; Default (Ubuntu&amp;nbsp;archive)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Storage:&lt;/strong&gt; Guided - use entire disk. Select the 32 &lt;span class="caps"&gt;GB&lt;/span&gt; virtual disk.&amp;nbsp;Confirm.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Profile:&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Your name:&lt;/strong&gt; Homelab&amp;nbsp;Admin&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Server name:&lt;/strong&gt;&amp;nbsp;ubuntu-01&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Username:&lt;/strong&gt;&amp;nbsp;admin&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Password:&lt;/strong&gt; Choose a strong password. Confirm&amp;nbsp;it.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;SSH&lt;/span&gt;:&lt;/strong&gt; Check &lt;strong&gt;Install OpenSSH server&lt;/strong&gt;. This is critical for remote&amp;nbsp;management.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Featured Server Snaps:&lt;/strong&gt; Skip for now (we will install Docker&amp;nbsp;later).&lt;/li&gt;
&lt;li&gt;The installer will partition, copy files, and install the kernel. This takes 5–10&amp;nbsp;minutes.&lt;/li&gt;
&lt;li&gt;When finished, select &lt;strong&gt;Reboot Now&lt;/strong&gt;. The &lt;span class="caps"&gt;VM&lt;/span&gt; will&amp;nbsp;restart.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; After the first reboot, the &lt;span class="caps"&gt;VM&lt;/span&gt; will try to boot from the &lt;span class="caps"&gt;ISO&lt;/span&gt; again. In the Proxmox web &lt;span class="caps"&gt;UI&lt;/span&gt;, go to &lt;strong&gt;Hardware → &lt;span class="caps"&gt;CD&lt;/span&gt;/&lt;span class="caps"&gt;DVD&lt;/span&gt; Drive&lt;/strong&gt; and click &lt;strong&gt;Remove&lt;/strong&gt; or change it to &lt;strong&gt;Do not use any media&lt;/strong&gt;. Then restart the &lt;span class="caps"&gt;VM&lt;/span&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 4: Configure the &lt;span class="caps"&gt;VM&lt;/span&gt; and Install &lt;span class="caps"&gt;QEMU&lt;/span&gt; Guest&amp;nbsp;Agent&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Ensure the &lt;span class="caps"&gt;VM&lt;/span&gt; reports its &lt;span class="caps"&gt;IP&lt;/span&gt; to Proxmox and can be shut down&amp;nbsp;gracefully.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;In the &lt;span class="caps"&gt;VM&lt;/span&gt; console, log in with the username and password you&amp;nbsp;created.&lt;/li&gt;
&lt;li&gt;Check the &lt;span class="caps"&gt;IP&lt;/span&gt;:
   &lt;code&gt;bash
   ip addr show&lt;/code&gt;
   Look&amp;nbsp;for &lt;code&gt;eth0&lt;/code&gt; or &lt;code&gt;ens18&lt;/code&gt; with an &lt;span class="caps"&gt;IP&lt;/span&gt;&amp;nbsp;like &lt;code&gt;192.168.1.101&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Install &lt;span class="caps"&gt;QEMU&lt;/span&gt; Guest&amp;nbsp;Agent:
   &lt;code&gt;bash
   sudo apt update &amp;amp;&amp;amp; sudo apt install qemu-guest-agent -y
   sudo systemctl enable qemu-guest-agent
   sudo systemctl start qemu-guest-agent&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;In the Proxmox web &lt;span class="caps"&gt;UI&lt;/span&gt;, the &lt;span class="caps"&gt;VM&lt;/span&gt;&amp;#8217;s &lt;strong&gt;Summary&lt;/strong&gt; tab should now show the &lt;span class="caps"&gt;IP&lt;/span&gt; address under&amp;nbsp;&amp;#8220;IPs.&amp;#8221;&lt;/li&gt;
&lt;li&gt;Test a graceful&amp;nbsp;shutdown:&lt;/li&gt;
&lt;li&gt;In Proxmox, right-click the &lt;span class="caps"&gt;VM&lt;/span&gt; → &lt;strong&gt;Shutdown&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;span class="caps"&gt;VM&lt;/span&gt; should power off cleanly within 10&amp;nbsp;seconds.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Step 5: Create a Cloud-Init Template (Advanced but&amp;nbsp;Recommended)&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Cloud-init lets you clone VMs with pre-configured hostnames, &lt;span class="caps"&gt;SSH&lt;/span&gt; keys, and IPs. This is how production Proxmox users deploy&amp;nbsp;VMs.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Download the cloud image&lt;/strong&gt; (instead of the &lt;span class="caps"&gt;ISO&lt;/span&gt;):
   &lt;code&gt;bash
   cd /var/lib/vz/template/iso/
   wget https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Create a new &lt;span class="caps"&gt;VM&lt;/span&gt;&lt;/strong&gt; (&lt;span class="caps"&gt;ID&lt;/span&gt; 9000,&amp;nbsp;name &lt;code&gt;ubuntu-cloud-template&lt;/code&gt;) with no&amp;nbsp;disk.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Import the image&lt;/strong&gt; as a&amp;nbsp;disk:
   &lt;code&gt;bash
   qm importdisk 9000 noble-server-cloudimg-amd64.img local-lvm&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;In the &lt;span class="caps"&gt;VM&lt;/span&gt; hardware, attach the imported disk as &lt;strong&gt;&lt;span class="caps"&gt;SCSI&lt;/span&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Add a &lt;strong&gt;CloudInit&lt;/strong&gt; drive (&lt;span class="caps"&gt;CD&lt;/span&gt;-&lt;span class="caps"&gt;ROM&lt;/span&gt;) in the hardware&amp;nbsp;list.&lt;/li&gt;
&lt;li&gt;In the &lt;strong&gt;Cloud-Init&lt;/strong&gt; tab of the &lt;span class="caps"&gt;VM&lt;/span&gt;:&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;User:&lt;/strong&gt; &lt;code&gt;admin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;Password:&lt;/strong&gt; (or better, add an &lt;span class="caps"&gt;SSH&lt;/span&gt; public&amp;nbsp;key)&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;&lt;span class="caps"&gt;IP&lt;/span&gt;&amp;nbsp;Config:&lt;/strong&gt; &lt;code&gt;ip=192.168.1.0/24,gw=192.168.1.1&lt;/code&gt; (use &lt;span class="caps"&gt;DHCP&lt;/span&gt; for&amp;nbsp;beginners)&lt;/li&gt;
&lt;li&gt;Convert the &lt;span class="caps"&gt;VM&lt;/span&gt; to a&amp;nbsp;template:
   &lt;code&gt;bash
   qm template 9000&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Clone the template&lt;/strong&gt; to create new VMs in&amp;nbsp;seconds:
   &lt;code&gt;bash
   qm clone 9000 101 --name ubuntu-web --full
   qm clone 9000 102 --name ubuntu-db --full&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Use Snapshots Before Major&amp;nbsp;Changes&lt;/h3&gt;
&lt;p&gt;Before you&amp;nbsp;run &lt;code&gt;apt upgrade&lt;/code&gt; or install a risky app, take a&amp;nbsp;snapshot:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In Proxmox, select the &lt;span class="caps"&gt;VM&lt;/span&gt; → &lt;strong&gt;Snapshots&lt;/strong&gt; → &lt;strong&gt;Take Snapshot&lt;/strong&gt;. Name it&amp;nbsp;&amp;#8220;pre-upgrade.&amp;#8221;&lt;/li&gt;
&lt;li&gt;If something breaks, right-click the snapshot → &lt;strong&gt;Rollback&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Tip 2: Reserve &lt;span class="caps"&gt;RAM&lt;/span&gt; for the&amp;nbsp;Host&lt;/h3&gt;
&lt;p&gt;Never allocate 100% of host &lt;span class="caps"&gt;RAM&lt;/span&gt; to VMs. Proxmox needs 2–4 &lt;span class="caps"&gt;GB&lt;/span&gt; for itself, &lt;span class="caps"&gt;ZFS&lt;/span&gt; &lt;span class="caps"&gt;ARC&lt;/span&gt;, and overhead. If your host has 32 &lt;span class="caps"&gt;GB&lt;/span&gt;, cap &lt;span class="caps"&gt;VM&lt;/span&gt; allocations at 28 &lt;span class="caps"&gt;GB&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;Tip 3: Enable Firewall&amp;nbsp;Rules&lt;/h3&gt;
&lt;p&gt;Go to &lt;strong&gt;Datacenter → Firewall&lt;/strong&gt; and enable the host firewall. Then, in each &lt;span class="caps"&gt;VM&lt;/span&gt;&amp;#8217;s &lt;strong&gt;Firewall&lt;/strong&gt; tab, add rules:
- Allow &lt;span class="caps"&gt;SSH&lt;/span&gt; (port 22) from your &lt;span class="caps"&gt;LAN&lt;/span&gt; subnet.
- Block everything else by&amp;nbsp;default.&lt;/p&gt;
&lt;p&gt;This adds a layer of protection even if the &lt;span class="caps"&gt;VM&lt;/span&gt;&amp;#8217;s &lt;span class="caps"&gt;OS&lt;/span&gt; firewall is&amp;nbsp;misconfigured.&lt;/p&gt;
&lt;h3&gt;Tip 4: Use Spice for Better Console&amp;nbsp;Performance&lt;/h3&gt;
&lt;p&gt;&lt;span class="caps"&gt;VNC&lt;/span&gt; is slow for video. If you need to interact with a desktop &lt;span class="caps"&gt;VM&lt;/span&gt;,&amp;nbsp;install &lt;code&gt;spice-vdagent&lt;/code&gt; and use the &lt;strong&gt;&lt;span class="caps"&gt;SPICE&lt;/span&gt;&lt;/strong&gt; console instead of &lt;span class="caps"&gt;VNC&lt;/span&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Troubleshooting Common&amp;nbsp;Issues&lt;/h2&gt;
&lt;h3&gt;Problem 1: &amp;#8220;No Boot Device&amp;nbsp;Found&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Cause:&lt;/strong&gt; The &lt;span class="caps"&gt;ISO&lt;/span&gt; is still mounted, or the disk boot order is&amp;nbsp;wrong.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;
- Go to &lt;strong&gt;Hardware → &lt;span class="caps"&gt;CD&lt;/span&gt;/&lt;span class="caps"&gt;DVD&lt;/span&gt; Drive&lt;/strong&gt; and remove the &lt;span class="caps"&gt;ISO&lt;/span&gt;.
- Go to &lt;strong&gt;Options → Boot Order&lt;/strong&gt; and ensure the disk is first.
- Restart the &lt;span class="caps"&gt;VM&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;Problem 2: &lt;span class="caps"&gt;VM&lt;/span&gt; Gets No &lt;span class="caps"&gt;IP&lt;/span&gt;&amp;nbsp;Address&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Cause:&lt;/strong&gt; The network&amp;nbsp;bridge &lt;code&gt;vmbr0&lt;/code&gt; is not connected to a &lt;span class="caps"&gt;LAN&lt;/span&gt; with &lt;span class="caps"&gt;DHCP&lt;/span&gt;, or the &lt;span class="caps"&gt;VM&lt;/span&gt;&amp;#8217;s &lt;span class="caps"&gt;NIC&lt;/span&gt; is&amp;nbsp;disconnected.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;
- Check&amp;nbsp;that &lt;code&gt;vmbr0&lt;/code&gt; on the Proxmox host has a valid &lt;span class="caps"&gt;IP&lt;/span&gt;.
- In the &lt;span class="caps"&gt;VM&lt;/span&gt; hardware, ensure the network adapter is connected (checkbox).
- Try setting a static &lt;span class="caps"&gt;IP&lt;/span&gt; in the &lt;span class="caps"&gt;VM&lt;/span&gt; if your &lt;span class="caps"&gt;LAN&lt;/span&gt; has no &lt;span class="caps"&gt;DHCP&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;Problem 3: &lt;span class="caps"&gt;QEMU&lt;/span&gt; Guest Agent Does Not Show &lt;span class="caps"&gt;IP&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Cause:&lt;/strong&gt; The agent is not installed, or the &lt;span class="caps"&gt;VM&lt;/span&gt; was created without &amp;#8220;&lt;span class="caps"&gt;QEMU&lt;/span&gt; Agent&amp;#8221;&amp;nbsp;checked.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;
-&amp;nbsp;Install &lt;code&gt;qemu-guest-agent&lt;/code&gt; inside the &lt;span class="caps"&gt;VM&lt;/span&gt;.
- Shut down the &lt;span class="caps"&gt;VM&lt;/span&gt;, go to &lt;strong&gt;Hardware → Options&lt;/strong&gt;, and ensure &lt;strong&gt;&lt;span class="caps"&gt;QEMU&lt;/span&gt; Agent&lt;/strong&gt; is enabled.
- Start the &lt;span class="caps"&gt;VM&lt;/span&gt; and wait 30&amp;nbsp;seconds.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;You have created your first &lt;span class="caps"&gt;VM&lt;/span&gt; on Proxmox, installed Ubuntu Server, and configured &lt;span class="caps"&gt;QEMU&lt;/span&gt; Guest Agent. This is the foundation of your homelab. From here, you can clone VMs, take snapshots, and deploy Docker inside the &lt;span class="caps"&gt;VM&lt;/span&gt; for application&amp;nbsp;hosting.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;[internal_link] Install Docker inside the &lt;span class="caps"&gt;VM&lt;/span&gt;: read our &lt;a href="https://steadypub.com/2026/06/docker-compose-for-beginners/"&gt;Docker Compose for beginners&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;[internal_link] Set up a reverse proxy: see our &lt;a href="https://steadypub.com/2026/06/portainer-setup-guide/"&gt;Portainer and &lt;span class="caps"&gt;NGINX&lt;/span&gt; Proxy Manager guide&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;[internal_link] Ready for more VMs? Learn about &lt;a href="https://steadypub.com/2026/06/proxmox-beginner-guide-2026/"&gt;cloud-init templates&lt;/a&gt; for instant&amp;nbsp;cloning.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Proxmox mini PCs&lt;/strong&gt;: Beelink, Minisforum, Intel &lt;span class="caps"&gt;NUC&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ubuntu Server&lt;/strong&gt;: Official Ubuntu Pro&amp;nbsp;subscriptions&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Courses&lt;/strong&gt;: Linux Foundation sysadmin&amp;nbsp;courses&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;what-is&lt;/code&gt; → &lt;code&gt;proxmox-beginner-guide-2026&lt;/code&gt; — &amp;#8220;learn Proxmox from&amp;nbsp;scratch&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prerequisites&lt;/code&gt; → &lt;code&gt;beelink-mini-pc-proxmox&lt;/code&gt; — &amp;#8220;hardware for your Proxmox&amp;nbsp;host&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;docker-compose-for-beginners&lt;/code&gt; — &amp;#8220;deploy apps inside your new &lt;span class="caps"&gt;VM&lt;/span&gt;&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] What &lt;span class="caps"&gt;OS&lt;/span&gt; did you install in your first Proxmox &lt;span class="caps"&gt;VM&lt;/span&gt;? Ubuntu, Debian, or something&amp;nbsp;else?&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for more Proxmox tutorials, &lt;span class="caps"&gt;VM&lt;/span&gt; templates, and homelab&amp;nbsp;automation.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Tutorials"/><category term="proxmox"/><category term="vm"/><category term="tutorial"/><category term="first vm"/><category term="homelab"/><category term="self-hosted"/></entry><entry><title>Proxmox vs VirtualBox for Beginners: Which One Wins for Your Homelab?</title><link href="https://steadypub.com/2026/06/proxmox-vs-virtualbox-for-beginners/" rel="alternate"/><published>2026-06-05T00:00:00+07:00</published><updated>2026-06-05T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/proxmox-vs-virtualbox-for-beginners/</id><summary type="html">&lt;p&gt;A head-to-head comparison of Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; and VirtualBox for homelab beginners. Learn which hypervisor fits your use case, hardware, and long-term&amp;nbsp;goals.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~11 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Beginners choosing their first homelab&amp;nbsp;hypervisor&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The Proxmox vs VirtualBox&amp;nbsp;Dilemma&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;VirtualBox is the familiar desktop hypervisor you probably used in school or work. Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; is a Linux-based, open-source enterprise hypervisor that runs headless on bare metal. If you want to turn an old &lt;span class="caps"&gt;PC&lt;/span&gt; into a 24/7 server, the choice between them defines your entire workflow: desktop convenience vs. server-grade&amp;nbsp;power.&lt;/p&gt;
&lt;h3&gt;Key Differences at a&amp;nbsp;Glance&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;VirtualBox&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Type&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Bare-metal (Type 1) hypervisor&lt;/td&gt;
&lt;td&gt;Hosted (Type 2) hypervisor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;OS&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Dedicated Debian-based appliance&lt;/td&gt;
&lt;td&gt;Runs on Windows, macOS, Linux&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;GUI&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Web-based (no monitor needed)&lt;/td&gt;
&lt;td&gt;Desktop &lt;span class="caps"&gt;GUI&lt;/span&gt; (needs monitor)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;VMs + Containers&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;KVM&lt;/span&gt; VMs + &lt;span class="caps"&gt;LXC&lt;/span&gt; containers&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;KVM&lt;/span&gt; VMs only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Clustering&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Native &lt;span class="caps"&gt;HA&lt;/span&gt; clustering&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Live Migration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes (shared storage)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Open Source&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fully open source (&lt;span class="caps"&gt;AGPL&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;Free for personal use (proprietary)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Learning Curve&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Steeper&lt;/td&gt;
&lt;td&gt;Gentle&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best For&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;24/7 servers, multi-&lt;span class="caps"&gt;VM&lt;/span&gt; labs&lt;/td&gt;
&lt;td&gt;Quick testing, desktop sandboxing&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Option A: Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;&lt;/h2&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Bare-metal performance:&lt;/strong&gt; Runs directly on hardware; no host &lt;span class="caps"&gt;OS&lt;/span&gt;&amp;nbsp;overhead.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Web &lt;span class="caps"&gt;UI&lt;/span&gt;:&lt;/strong&gt; Manage from any device on your network. No monitor, keyboard, or mouse needed after&amp;nbsp;install.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;LXC&lt;/span&gt; containers:&lt;/strong&gt; Run lightweight Linux containers alongside full VMs. A 512 &lt;span class="caps"&gt;MB&lt;/span&gt; container can host a whole web&amp;nbsp;stack.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;ZFS&lt;/span&gt; integration:&lt;/strong&gt; Built-in &lt;span class="caps"&gt;ZFS&lt;/span&gt; support with snapshots, compression, and &lt;span class="caps"&gt;RAID&lt;/span&gt;-Z.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Backup &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; restore:&lt;/strong&gt;&amp;nbsp;Native &lt;code&gt;vzdump&lt;/code&gt; backups, scheduled without third-party&amp;nbsp;tools.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Free forever:&lt;/strong&gt; No license fees for the community edition; enterprise support is&amp;nbsp;optional.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Installs to disk:&lt;/strong&gt; You must wipe the drive or dedicate a machine to&amp;nbsp;it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Command-line required:&lt;/strong&gt; Some advanced tasks (&lt;span class="caps"&gt;GPU&lt;/span&gt; passthrough, &lt;span class="caps"&gt;PCI&lt;/span&gt; binding) require&amp;nbsp;editing &lt;code&gt;/etc/pve&lt;/code&gt; or &lt;span class="caps"&gt;GRUB&lt;/span&gt;&amp;nbsp;configs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Networking complexity:&lt;/strong&gt; Linux bridges, VLANs, and bond configuration can overwhelm&amp;nbsp;beginners.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No desktop &lt;span class="caps"&gt;GUI&lt;/span&gt;:&lt;/strong&gt; You cannot run a local desktop on the Proxmox host (without nesting, which is&amp;nbsp;discouraged).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Users with a dedicated spare machine, mini &lt;span class="caps"&gt;PC&lt;/span&gt;, or rack&amp;nbsp;server.&lt;/li&gt;
&lt;li&gt;Anyone who wants to run services 24/7 (Plex, Nextcloud, Pi-hole,&amp;nbsp;etc.).&lt;/li&gt;
&lt;li&gt;Homelabbers who want to learn enterprise virtualization (&lt;span class="caps"&gt;KVM&lt;/span&gt;, clustering,&amp;nbsp;Ceph).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Free&lt;/strong&gt; (community edition, no&amp;nbsp;subscription).&lt;/li&gt;
&lt;li&gt;Enterprise subscription: ~$110/year per &lt;span class="caps"&gt;CPU&lt;/span&gt; socket (optional, adds support&amp;nbsp;repo).&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Option B:&amp;nbsp;VirtualBox&lt;/h2&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Instant setup:&lt;/strong&gt; Install like any desktop app. Create a &lt;span class="caps"&gt;VM&lt;/span&gt; in&amp;nbsp;minutes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Guest Additions:&lt;/strong&gt; Seamless mouse, shared clipboard, and dynamic resolution for desktop&amp;nbsp;VMs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Snapshot tree:&lt;/strong&gt; Visual snapshot branching (great for testing malware or risky&amp;nbsp;updates).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cross-platform:&lt;/strong&gt; Run Windows VMs on macOS or Linux VMs on&amp;nbsp;Windows.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;USB&lt;/span&gt; passthrough:&lt;/strong&gt; Simple, reliable &lt;span class="caps"&gt;USB&lt;/span&gt; device filtering for dongles or&amp;nbsp;peripherals.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Large community:&lt;/strong&gt; Every Linux distro tutorial assumes&amp;nbsp;VirtualBox.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Type 2 overhead:&lt;/strong&gt; Your host &lt;span class="caps"&gt;OS&lt;/span&gt; (Windows, macOS) consumes &lt;span class="caps"&gt;RAM&lt;/span&gt; and &lt;span class="caps"&gt;CPU&lt;/span&gt;&amp;nbsp;cycles.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Not for 24/7:&lt;/strong&gt; Running a &lt;span class="caps"&gt;VM&lt;/span&gt; while you sleep means your desktop stays on, wasting&amp;nbsp;power.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No containers:&lt;/strong&gt; You cannot run &lt;span class="caps"&gt;LXC&lt;/span&gt; or Docker natively inside VirtualBox without&amp;nbsp;nesting.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No remote management:&lt;/strong&gt; You need a monitor or &lt;span class="caps"&gt;RDP&lt;/span&gt; to the host to manage&amp;nbsp;VMs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Headless mode is&amp;nbsp;clunky:&lt;/strong&gt; &lt;code&gt;VBoxHeadless&lt;/code&gt; exists, but the experience is inferior to Proxmox&amp;#8217;s web &lt;span class="caps"&gt;UI&lt;/span&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Quick testing, &lt;span class="caps"&gt;OS&lt;/span&gt; evaluation, or software development&amp;nbsp;sandboxes.&lt;/li&gt;
&lt;li&gt;Users who only have one computer and cannot dedicate&amp;nbsp;hardware.&lt;/li&gt;
&lt;li&gt;Beginners who want to learn Linux without&amp;nbsp;repartitioning.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Free&lt;/strong&gt; for personal use (VirtualBox Extension Pack has a free personal-use&amp;nbsp;license).&lt;/li&gt;
&lt;li&gt;Commercial use requires a license from&amp;nbsp;Oracle.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Option C: The Hybrid Path (VirtualBox →&amp;nbsp;Proxmox)&lt;/h2&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Many users start with VirtualBox, then migrate to Proxmox once they have spare&amp;nbsp;hardware.&lt;/li&gt;
&lt;li&gt;VirtualBox &lt;code&gt;.ova&lt;/code&gt; files can be imported into Proxmox&amp;nbsp;with &lt;code&gt;qm importovf&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;This path lets you learn virtualization concepts with zero&amp;nbsp;risk.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Migration takes time (network reconfiguration, disk conversion, driver&amp;nbsp;updates).&lt;/li&gt;
&lt;li&gt;Some VirtualBox-specific settings (Guest Additions) do not&amp;nbsp;transfer.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Absolute beginners who want to test the waters before committing&amp;nbsp;hardware.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Free for both&amp;nbsp;stages.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Comparison&amp;nbsp;Matrix&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;Proxmox&lt;/th&gt;
&lt;th&gt;VirtualBox&lt;/th&gt;
&lt;th&gt;Winner&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;24/7 home server&lt;/td&gt;
&lt;td&gt;✅ Native&lt;/td&gt;
&lt;td&gt;❌ Host must stay on&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Proxmox&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Quick Windows test&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅ Easier&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;VirtualBox&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-&lt;span class="caps"&gt;VM&lt;/span&gt; lab (10+ VMs)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌ Host chokes&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Proxmox&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;LXC&lt;/span&gt; containers&lt;/td&gt;
&lt;td&gt;✅ Built-in&lt;/td&gt;
&lt;td&gt;❌ Not supported&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Proxmox&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;GPU&lt;/span&gt; passthrough&lt;/td&gt;
&lt;td&gt;✅ Advanced&lt;/td&gt;
&lt;td&gt;✅ Basic&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Proxmox&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Laptop user&lt;/td&gt;
&lt;td&gt;❌ Needs bare metal&lt;/td&gt;
&lt;td&gt;✅ Runs on host&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;VirtualBox&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Learning enterprise &lt;span class="caps"&gt;IT&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;✅ iDRAC-like experience&lt;/td&gt;
&lt;td&gt;❌ Desktop toy&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Proxmox&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Which Should You&amp;nbsp;Choose?&lt;/h2&gt;
&lt;h3&gt;Scenario 1: &amp;#8220;I have one laptop and want to learn&amp;nbsp;Linux.&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose VirtualBox.&lt;/strong&gt; Install Ubuntu, Debian, or Fedora in a &lt;span class="caps"&gt;VM&lt;/span&gt; without touching your main drive. You can snapshot before updates and roll back instantly. When you are ready, buy a $150 mini &lt;span class="caps"&gt;PC&lt;/span&gt; and switch to&amp;nbsp;Proxmox.&lt;/p&gt;
&lt;h3&gt;Scenario 2: &amp;#8220;I have an old desktop and want a 24/7 &lt;span class="caps"&gt;NAS&lt;/span&gt; and media&amp;nbsp;server.&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose Proxmox.&lt;/strong&gt; Install Proxmox on the bare metal. Create a &lt;span class="caps"&gt;VM&lt;/span&gt; for TrueNAS (or a container for Samba), another &lt;span class="caps"&gt;VM&lt;/span&gt; for Jellyfin, and a container for Pi-hole. You get enterprise-grade reliability, and you can manage it from your&amp;nbsp;phone.&lt;/p&gt;
&lt;h3&gt;Scenario 3: &amp;#8220;I want to build a career in &lt;span class="caps"&gt;IT&lt;/span&gt; /&amp;nbsp;DevOps.&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose Proxmox.&lt;/strong&gt; VirtualBox will not teach you clustering, live migration, Ceph storage, or network bridges. Proxmox is a free stand-in for VMware vSphere and is highly respected on&amp;nbsp;resumes.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Migration Path: VirtualBox to&amp;nbsp;Proxmox&lt;/h2&gt;
&lt;h3&gt;Step 1: Export Your VirtualBox &lt;span class="caps"&gt;VM&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;In VirtualBox, select the &lt;span class="caps"&gt;VM&lt;/span&gt; and choose &lt;strong&gt;File → Export Appliance&lt;/strong&gt;. Save as&amp;nbsp;an &lt;code&gt;.ova&lt;/code&gt; file.&lt;/p&gt;
&lt;h3&gt;Step 2: Upload to&amp;nbsp;Proxmox&lt;/h3&gt;
&lt;p&gt;Use &lt;span class="caps"&gt;SCP&lt;/span&gt; or the Proxmox web &lt;span class="caps"&gt;UI&lt;/span&gt; (Datacenter → Storage → Upload) to move&amp;nbsp;the &lt;code&gt;.ova&lt;/code&gt; to &lt;code&gt;/var/lib/vz/template/iso/&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Step 3: Import into&amp;nbsp;Proxmox&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# On Proxmox shell&lt;/span&gt;
qm&lt;span class="w"&gt; &lt;/span&gt;importovf&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/var/lib/vz/template/iso/myvm.ova&lt;span class="w"&gt; &lt;/span&gt;local-lvm
&lt;span class="c1"&gt;# Adjust VM ID (9000) and storage name as needed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Step 4: Fix&amp;nbsp;Networking&lt;/h3&gt;
&lt;p&gt;Proxmox uses Linux bridges&amp;nbsp;(&lt;code&gt;vmbr0&lt;/code&gt;). After import, change the &lt;span class="caps"&gt;VM&lt;/span&gt;&amp;#8217;s network adapter from the VirtualBox &amp;#8220;&lt;span class="caps"&gt;NAT&lt;/span&gt;&amp;#8221; style to a Proxmox bridge. You may need to reinstall guest drivers if the &lt;span class="caps"&gt;OS&lt;/span&gt; was&amp;nbsp;Windows.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The&amp;nbsp;Verdict&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Verdict&lt;/th&gt;
&lt;th&gt;Recommendation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for beginners&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;VirtualBox (zero commitment)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for homelab&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Proxmox (power, containers, remote)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best long-term&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Proxmox (scales from 1 node to 16)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;VirtualBox is the gateway drug of virtualization. It is perfect for learning, testing, and dabbling. Proxmox is the serious tool for a self-hosted infrastructure. If you have dedicated hardware and want to run services 24/7, Proxmox is the clear winner. If you are on a laptop and just curious, start with VirtualBox and migrate&amp;nbsp;later.&lt;/p&gt;
&lt;h3&gt;Ready to Get&amp;nbsp;Started?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;[internal_link] New to Proxmox? Read our &lt;a href="https://steadypub.com/2026/06/proxmox-beginner-guide-2026/"&gt;Proxmox beginner guide&lt;/a&gt; for a step-by-step&amp;nbsp;install.&lt;/li&gt;
&lt;li&gt;[internal_link] Need hardware? Check our &lt;a href="https://steadypub.com/2026/06/best-rack-server-for-homelab/"&gt;best rack server guide&lt;/a&gt; or &lt;a href="https://steadypub.com/2026/06/homelab-server-hardware-2026/"&gt;mini &lt;span class="caps"&gt;PC&lt;/span&gt; guide&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;[internal_link] Ready to deploy apps? See our &lt;a href="https://steadypub.com/2026/06/docker-compose-for-beginners/"&gt;Docker Compose for beginners&lt;/a&gt;&amp;nbsp;guide.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Proxmox hardware&lt;/strong&gt;: Mini &lt;span class="caps"&gt;PC&lt;/span&gt; affiliate links (Beelink,&amp;nbsp;Minisforum)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;VirtualBox&lt;/strong&gt;: Cross-promote to laptop&amp;nbsp;users&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;When-to-choose&lt;/strong&gt;: &lt;span class="caps"&gt;VPS&lt;/span&gt; providers for users who cannot run a home&amp;nbsp;server&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;intro-dilemma&lt;/code&gt; → &lt;code&gt;proxmox-beginner-guide-2026&lt;/code&gt; — &amp;#8220;our comprehensive Proxmox setup&amp;nbsp;guide&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;migration-path&lt;/code&gt; → &lt;code&gt;migrate-from-esxi-to-proxmox&lt;/code&gt; — &amp;#8220;see how to migrate VMs into&amp;nbsp;Proxmox&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;docker-compose-for-beginners&lt;/code&gt; — &amp;#8220;deploy apps inside Proxmox&amp;nbsp;containers&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] Which hypervisor did you start with? VirtualBox or Proxmox? Share your story&amp;nbsp;below!&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for more homelab comparisons, setup guides, and hardware&amp;nbsp;reviews.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Comparisons"/><category term="proxmox"/><category term="virtualbox"/><category term="homelab"/><category term="beginners"/><category term="virtualization"/><category term="comparison"/></entry><entry><title>TP-Link Omada vs UniFi: Which Network Ecosystem Wins for Your Homelab?</title><link href="https://steadypub.com/2026/06/tp-link-omada-vs-unifi/" rel="alternate"/><published>2026-06-05T00:00:00+07:00</published><updated>2026-06-05T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/tp-link-omada-vs-unifi/</id><summary type="html">&lt;p&gt;A head-to-head comparison of &lt;span class="caps"&gt;TP&lt;/span&gt;-Link Omada and Ubiquiti UniFi for homelab networking. Compare cost, features, controller software, and hardware to decide which ecosystem fits your&amp;nbsp;setup.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~14 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab builders choosing between &lt;span class="caps"&gt;TP&lt;/span&gt;-Link Omada and Ubiquiti&amp;nbsp;UniFi&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The Omada vs UniFi&amp;nbsp;Dilemma&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Ubiquiti UniFi has been the dominant name in prosumer networking for over a decade. &lt;span class="caps"&gt;TP&lt;/span&gt;-Link Omada is the underdog that has quietly built a compelling alternative at a lower price point. Both ecosystems offer centralized controller software, managed switches, Wi-Fi access points, and gateways. The choice between them shapes your entire network&amp;nbsp;experience.&lt;/p&gt;
&lt;h3&gt;Key Differences at a&amp;nbsp;Glance&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;TP&lt;/span&gt;-Link Omada&lt;/th&gt;
&lt;th&gt;Ubiquiti UniFi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Controller cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Free (no licensing)&lt;/td&gt;
&lt;td&gt;Free (no licensing)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hardware cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;20–40% cheaper&lt;/td&gt;
&lt;td&gt;Premium pricing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cloud hosting&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Optional (free)&lt;/td&gt;
&lt;td&gt;Optional (free)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Self-hosted controller&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes (Docker available)&lt;/td&gt;
&lt;td&gt;Yes (Docker available)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;AP&lt;/span&gt; Wi-Fi 6E&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Available (&lt;span class="caps"&gt;EAP670&lt;/span&gt;, &lt;span class="caps"&gt;EAP680&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;Available (U6-Enterprise)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;2.5 GbE switches&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Available (&lt;span class="caps"&gt;SG3210XHP&lt;/span&gt;-M2)&lt;/td&gt;
&lt;td&gt;Available (&lt;span class="caps"&gt;USW&lt;/span&gt;-Enterprise-8)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;10 GbE&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Limited (&lt;span class="caps"&gt;SG3428X&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;More options (&lt;span class="caps"&gt;XG&lt;/span&gt; line)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PoE budget&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Generous per-port&lt;/td&gt;
&lt;td&gt;Good, but varies by model&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Community size&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Growing (r/TPLinkOmada)&lt;/td&gt;
&lt;td&gt;Massive (r/Ubiquiti)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Software maturity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Newer, improving rapidly&lt;/td&gt;
&lt;td&gt;Mature, but buggy updates&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Option A: &lt;span class="caps"&gt;TP&lt;/span&gt;-Link&amp;nbsp;Omada&lt;/h2&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Significantly cheaper:&lt;/strong&gt; An Omada &lt;span class="caps"&gt;AP&lt;/span&gt; costs 30–50% less than an equivalent UniFi &lt;span class="caps"&gt;AP&lt;/span&gt;. For a 3-&lt;span class="caps"&gt;AP&lt;/span&gt; + switch setup, Omada can save&amp;nbsp;$200–400.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No forced ecosystem lock-in:&lt;/strong&gt; Omada hardware works without a cloud account. You can run the controller locally, self-hosted, or not at&amp;nbsp;all.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Free controller software:&lt;/strong&gt; The Omada Software Controller (v5+) runs on Windows, Linux, and in Docker containers. No licensing&amp;nbsp;fees.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Better PoE switch value:&lt;/strong&gt; The &lt;span class="caps"&gt;SG2008P&lt;/span&gt; (8-port, 4 PoE) and &lt;span class="caps"&gt;SG2210P&lt;/span&gt; (10-port, 8 PoE) are priced aggressively for homelab&amp;nbsp;use.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Simpler &lt;span class="caps"&gt;UI&lt;/span&gt;:&lt;/strong&gt; The Omada interface is less cluttered than UniFi. Settings are easier to find for&amp;nbsp;beginners.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No forced firmware updates:&lt;/strong&gt; UniFi has a history of pushing updates that break features. Omada updates are more&amp;nbsp;conservative.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Smaller community:&lt;/strong&gt; Fewer YouTube tutorials, fewer Reddit threads, and less third-party&amp;nbsp;documentation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fewer advanced features:&lt;/strong&gt; No WiFiman-like &lt;span class="caps"&gt;RF&lt;/span&gt; scanning app, no built-in speed test server, and no advanced traffic&amp;nbsp;analytics.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Less enterprise polish:&lt;/strong&gt; &lt;span class="caps"&gt;VLAN&lt;/span&gt; configuration works but is less intuitive. L3 switch features are limited compared to&amp;nbsp;UniFi.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cloud reliability:&lt;/strong&gt; Omada Cloud (for remote management) has had more downtime than UniFi&amp;nbsp;Cloud.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No native Protect/ cameras:&lt;/strong&gt; UniFi has Protect for cameras. Omada has no equivalent &lt;span class="caps"&gt;NVR&lt;/span&gt;&amp;nbsp;ecosystem.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Budget-conscious homelabbers who want managed Wi-Fi and switching without the UniFi&amp;nbsp;tax.&lt;/li&gt;
&lt;li&gt;Users who want to self-host the controller in Docker without cloud&amp;nbsp;dependencies.&lt;/li&gt;
&lt;li&gt;Small offices and home labs with under 50&amp;nbsp;devices.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Omada Model&lt;/th&gt;
&lt;th&gt;Price (approx)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Wi-Fi 6 &lt;span class="caps"&gt;AP&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;EAP610&lt;/span&gt; (&lt;span class="caps"&gt;AX1800&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;~$80&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wi-Fi 6E &lt;span class="caps"&gt;AP&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;EAP670&lt;/span&gt; (&lt;span class="caps"&gt;AX5400&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;~$180&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8-port PoE switch&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;SG2008P&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;~$70&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;24-port PoE switch&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;SG3428MP&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;~$350&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gateway / router&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;ER7206&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;~$150&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Controller&lt;/td&gt;
&lt;td&gt;Self-hosted (free)&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Option B: Ubiquiti&amp;nbsp;UniFi&lt;/h2&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Massive ecosystem:&lt;/strong&gt; Access points, switches, cameras, doorbells, sensors, and phones — all managed from one &lt;span class="caps"&gt;UI&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UniFi Protect:&lt;/strong&gt; The best integrated &lt;span class="caps"&gt;NVR&lt;/span&gt; for homelabbers. G4 cameras, &lt;span class="caps"&gt;AI&lt;/span&gt; detection, and local&amp;nbsp;storage.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Advanced &lt;span class="caps"&gt;RF&lt;/span&gt; features:&lt;/strong&gt; WiFiman app, &lt;span class="caps"&gt;RF&lt;/span&gt; environment scanning, and&amp;nbsp;auto-optimization.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Larger community:&lt;/strong&gt; Thousands of tutorials, custom firmware projects, and third-party&amp;nbsp;tools.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enterprise features:&lt;/strong&gt; Advanced traffic rules, dynamic VLANs, and deep packet inspection (on Dream Machine&amp;nbsp;Pro).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Regular updates:&lt;/strong&gt; Frequent firmware and feature releases (though quality&amp;nbsp;varies).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Premium pricing:&lt;/strong&gt; A UniFi Wi-Fi 6 &lt;span class="caps"&gt;AP&lt;/span&gt; costs 30–50% more than an equivalent Omada &lt;span class="caps"&gt;AP&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Update instability:&lt;/strong&gt; UniFi has a reputation for releasing firmware that breaks PoE, &lt;span class="caps"&gt;RADIUS&lt;/span&gt;, or &lt;span class="caps"&gt;VLAN&lt;/span&gt;&amp;nbsp;tagging.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cloud pressure:&lt;/strong&gt; Ubiquiti pushes cloud accounts and mobile app usage. Local-only management is increasingly&amp;nbsp;hidden.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hardware scarcity:&lt;/strong&gt; Popular items (Dream Machine Pro, U6-Pro) are often out of&amp;nbsp;stock.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No 2.5 GbE on budget switches:&lt;/strong&gt; UniFi&amp;#8217;s entry-level switches lack 2.5 GbE ports, forcing you to buy expensive Enterprise&amp;nbsp;models.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Users who want an all-in-one ecosystem with cameras, networking, and&amp;nbsp;IoT.&lt;/li&gt;
&lt;li&gt;Homelabbers who value community support and third-party&amp;nbsp;tools.&lt;/li&gt;
&lt;li&gt;Users who need advanced traffic analytics and &lt;span class="caps"&gt;RF&lt;/span&gt;&amp;nbsp;optimization.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;UniFi Model&lt;/th&gt;
&lt;th&gt;Price (approx)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Wi-Fi 6 &lt;span class="caps"&gt;AP&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;U6-Lite (&lt;span class="caps"&gt;AX1500&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;~$100&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wi-Fi 6E &lt;span class="caps"&gt;AP&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;U6-Enterprise (&lt;span class="caps"&gt;AX5400&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;~$300&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8-port PoE switch&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;USW&lt;/span&gt;-Lite-8-PoE&lt;/td&gt;
&lt;td&gt;~$110&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;24-port PoE switch&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;USW&lt;/span&gt;-24-PoE&lt;/td&gt;
&lt;td&gt;~$400&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gateway / router&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;UDM&lt;/span&gt; Pro&lt;/td&gt;
&lt;td&gt;~$380&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Controller&lt;/td&gt;
&lt;td&gt;Self-hosted (free) or Cloud Key&lt;/td&gt;
&lt;td&gt;$0–$200&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Option C: Hybrid or&amp;nbsp;Third-Party&lt;/h2&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Some homelabbers run Omada APs with a UniFi switch, or vice versa. Both support standard 802.3af/at&amp;nbsp;PoE.&lt;/li&gt;
&lt;li&gt;Third-party controllers like OpenWrt or standalone APs (MikroTik, Aruba Instant On) offer even more&amp;nbsp;flexibility.&lt;/li&gt;
&lt;li&gt;MikroTik provides enterprise-grade routing at lower prices than&amp;nbsp;both.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Mixed ecosystems lose the centralized management benefit. You manage two&amp;nbsp;UIs.&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;VLAN&lt;/span&gt; configuration can be tricky when trunking between different&amp;nbsp;vendors.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Comparison&amp;nbsp;Matrix&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;TP&lt;/span&gt;-Link Omada&lt;/th&gt;
&lt;th&gt;Ubiquiti UniFi&lt;/th&gt;
&lt;th&gt;Winner&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Budget homelab (under $500)&lt;/td&gt;
&lt;td&gt;✅ Aggressive pricing&lt;/td&gt;
&lt;td&gt;❌ Premium&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Omada&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;All-in-one (cameras + network)&lt;/td&gt;
&lt;td&gt;❌ No cameras&lt;/td&gt;
&lt;td&gt;✅ Protect&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;UniFi&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wi-Fi 6E coverage&lt;/td&gt;
&lt;td&gt;✅ &lt;span class="caps"&gt;EAP670&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;✅ U6-Enterprise&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Tie&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2.5 GbE switching&lt;/td&gt;
&lt;td&gt;✅ &lt;span class="caps"&gt;SG3210XHP&lt;/span&gt;-M2&lt;/td&gt;
&lt;td&gt;✅ &lt;span class="caps"&gt;USW&lt;/span&gt;-Enterprise&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Omada&lt;/strong&gt; (cheaper)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10 GbE / &lt;span class="caps"&gt;SFP&lt;/span&gt;+&lt;/td&gt;
&lt;td&gt;❌ Limited&lt;/td&gt;
&lt;td&gt;✅ &lt;span class="caps"&gt;XG&lt;/span&gt; line&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;UniFi&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Self-hosted controller&lt;/td&gt;
&lt;td&gt;✅ Docker&lt;/td&gt;
&lt;td&gt;✅ Docker&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Tie&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Community support&lt;/td&gt;
&lt;td&gt;❌ Smaller&lt;/td&gt;
&lt;td&gt;✅ Massive&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;UniFi&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Software stability&lt;/td&gt;
&lt;td&gt;✅ Conservative&lt;/td&gt;
&lt;td&gt;❌ Buggy updates&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Omada&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PoE budget per port&lt;/td&gt;
&lt;td&gt;✅ Higher&lt;/td&gt;
&lt;td&gt;⚠️ Varies&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Omada&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Which Should You&amp;nbsp;Choose?&lt;/h2&gt;
&lt;h3&gt;Scenario 1: &amp;#8220;I want the cheapest reliable Wi-Fi and switching&amp;nbsp;setup.&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose &lt;span class="caps"&gt;TP&lt;/span&gt;-Link Omada.&lt;/strong&gt; An &lt;span class="caps"&gt;EAP610&lt;/span&gt; + &lt;span class="caps"&gt;SG2008P&lt;/span&gt; + self-hosted controller costs under $200 and covers most apartments or small homes. The performance is nearly identical to UniFi for day-to-day&amp;nbsp;use.&lt;/p&gt;
&lt;h3&gt;Scenario 2: &amp;#8220;I want cameras, doorbells, and sensors integrated with my&amp;nbsp;network.&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose Ubiquiti UniFi.&lt;/strong&gt; UniFi Protect is the only integrated &lt;span class="caps"&gt;NVR&lt;/span&gt; in this comparison. The G4 Bullet and G4 Instant are excellent cameras, and the &lt;span class="caps"&gt;AI&lt;/span&gt; detection works&amp;nbsp;locally.&lt;/p&gt;
&lt;h3&gt;Scenario 3: &amp;#8220;I need 10 GbE and &lt;span class="caps"&gt;SFP&lt;/span&gt;+ for my &lt;span class="caps"&gt;NAS&lt;/span&gt; and&amp;nbsp;server.&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose UniFi (or MikroTik).&lt;/strong&gt; UniFi&amp;#8217;s &lt;span class="caps"&gt;XG&lt;/span&gt; line (&lt;span class="caps"&gt;USW&lt;/span&gt;-Aggregation, &lt;span class="caps"&gt;USW&lt;/span&gt;-Pro-Aggregation) has more 10 GbE options. However, MikroTik &lt;span class="caps"&gt;CRS&lt;/span&gt; switches are cheaper if you don&amp;#8217;t need centralized&amp;nbsp;management.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Migration&amp;nbsp;Path&lt;/h2&gt;
&lt;h3&gt;Step 1: Inventory Existing&amp;nbsp;Hardware&lt;/h3&gt;
&lt;p&gt;List your current APs, switches, and gateway. Check if they support standard 802.3af/at PoE. If they do, you can mix vendors during&amp;nbsp;migration.&lt;/p&gt;
&lt;h3&gt;Step 2: Deploy the&amp;nbsp;Controller&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Omada:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Docker Compose for Omada Controller&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;omada-controller&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8088&lt;/span&gt;:8088&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8043&lt;/span&gt;:8043&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;omada-data:/opt/tplink/EAPController/data&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;mbentley/omada-controller:latest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;UniFi:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Docker Compose for UniFi Network Server&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;unifi-controller&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8443&lt;/span&gt;:8443&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8080&lt;/span&gt;:8080&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;unifi-data:/unifi&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;jacobalberty/unifi:latest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Step 3: Adopt&amp;nbsp;Devices&lt;/h3&gt;
&lt;p&gt;In both controllers, go to &lt;strong&gt;Devices&lt;/strong&gt; → &lt;strong&gt;Adopt&lt;/strong&gt; and follow the adoption process. Reset devices to factory default if they were previously managed by another&amp;nbsp;controller.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The&amp;nbsp;Verdict&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Verdict&lt;/th&gt;
&lt;th&gt;Recommendation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for pure networking on a budget&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;TP&lt;/span&gt;-Link Omada&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for all-in-one ecosystem&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Ubiquiti UniFi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for stability and conservative updates&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;TP&lt;/span&gt;-Link Omada&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for community and third-party tools&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Ubiquiti UniFi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for 10 GbE / &lt;span class="caps"&gt;SFP&lt;/span&gt;+&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Ubiquiti UniFi (or MikroTik)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;&lt;span class="caps"&gt;TP&lt;/span&gt;-Link Omada is the value champion for homelab networking. It delivers 90% of UniFi&amp;#8217;s functionality at 60% of the cost. Ubiquiti UniFi wins if you want an integrated ecosystem with cameras, advanced analytics, and the largest&amp;nbsp;community.&lt;/p&gt;
&lt;h3&gt;Ready to Get&amp;nbsp;Started?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Omada:&lt;/strong&gt; Start with an &lt;span class="caps"&gt;EAP610&lt;/span&gt; and the free software&amp;nbsp;controller.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UniFi:&lt;/strong&gt; Start with a U6-Lite and a self-hosted Network&amp;nbsp;Server.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Omada hardware:&lt;/strong&gt; Amazon affiliate links for &lt;span class="caps"&gt;EAP610&lt;/span&gt;, &lt;span class="caps"&gt;SG2008P&lt;/span&gt;, &lt;span class="caps"&gt;ER7206&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UniFi hardware:&lt;/strong&gt; Amazon or B&amp;amp;H affiliate links for U6-Lite, &lt;span class="caps"&gt;USW&lt;/span&gt;-Lite-8-PoE, &lt;span class="caps"&gt;UDM&lt;/span&gt;&amp;nbsp;Pro&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MikroTik:&lt;/strong&gt; For users who want 10 GbE on a&amp;nbsp;budget&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;UPS&lt;/span&gt;:&lt;/strong&gt; &lt;span class="caps"&gt;APC&lt;/span&gt; or CyberPower for protecting network&amp;nbsp;hardware&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;intro-dilemma&lt;/code&gt; → &lt;code&gt;homelab-networking-basics&lt;/code&gt; — &amp;#8220;fundamentals of homelab&amp;nbsp;networking&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;option-a&lt;/code&gt; → &lt;code&gt;ubiquiti-homelab-setup&lt;/code&gt; — &amp;#8220;deep dive into UniFi&amp;nbsp;setup&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;option-b&lt;/code&gt; → &lt;code&gt;tp-link-omada-setup-guide&lt;/code&gt; — &amp;#8220;Omada controller setup&amp;nbsp;guide&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;migration-path&lt;/code&gt; → &lt;code&gt;docker-compose-for-beginners&lt;/code&gt; — &amp;#8220;how to deploy controllers with&amp;nbsp;Docker&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;best-mini-pc-for-homelab&lt;/code&gt; — &amp;#8220;hardware to run your&amp;nbsp;controller&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Which ecosystem runs your network?&lt;/strong&gt; Omada, UniFi, or something else? Share in the&amp;nbsp;comments.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subscribe&lt;/strong&gt; for weekly homelab networking guides, hardware reviews, and setup&amp;nbsp;tutorials.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Comparisons"/><category term="tp-link omada vs unifi"/><category term="homelab networking"/><category term="unifi alternative"/><category term="omada controller"/><category term="self-hosted network"/></entry><entry><title>Best UPS for Homelab in 2026: A Curated Guide</title><link href="https://steadypub.com/2026/06/ups-for-homelab/" rel="alternate"/><published>2026-06-05T00:00:00+07:00</published><updated>2026-06-05T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/ups-for-homelab/</id><summary type="html">&lt;p&gt;A curated ranking of the best &lt;span class="caps"&gt;UPS&lt;/span&gt; units for homelab builds in 2026. Includes real runtime calculations, sizing math, and &lt;span class="caps"&gt;USB&lt;/span&gt;/&lt;span class="caps"&gt;NMC&lt;/span&gt; shutdown&amp;nbsp;integration.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~12 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab builders who want clean power and graceful&amp;nbsp;shutdowns&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why a &lt;span class="caps"&gt;UPS&lt;/span&gt; for Your&amp;nbsp;Homelab?&lt;/h2&gt;
&lt;p&gt;A &lt;span class="caps"&gt;UPS&lt;/span&gt; (Uninterruptible Power Supply) does two things: it filters dirty power (surges, brownouts) and keeps your servers running during outages long enough to shut down gracefully. A hard shutdown can corrupt &lt;span class="caps"&gt;ZFS&lt;/span&gt; pools, corrupt databases, and damage spinning disks. A &lt;span class="caps"&gt;UPS&lt;/span&gt; is not a luxury; it is the cheapest insurance you can buy for your&amp;nbsp;data.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Evaluation&amp;nbsp;Criteria&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Criteria&lt;/th&gt;
&lt;th&gt;Why It Matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;VA&lt;/span&gt; / Watt Rating&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;VA&lt;/span&gt; is apparent power; Watts is real power. Modern PSUs have &lt;span class="caps"&gt;PFC&lt;/span&gt;, so you need a &lt;span class="caps"&gt;UPS&lt;/span&gt; that matches the wattage, not just the &lt;span class="caps"&gt;VA&lt;/span&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Runtime&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;How long the &lt;span class="caps"&gt;UPS&lt;/span&gt; can power your load. At 50% load, most units give 5–15 minutes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Topology&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Line-interactive (common, good for homelab) vs. Online double-conversion (best, expensive).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Outlets&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Ensure enough &lt;span class="caps"&gt;NEMA&lt;/span&gt; 5-15R outlets for your server, switch, router, and modem.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;USB&lt;/span&gt; / Network Management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A &lt;span class="caps"&gt;USB&lt;/span&gt; or &lt;span class="caps"&gt;SNMP&lt;/span&gt; card lets the &lt;span class="caps"&gt;UPS&lt;/span&gt; signal the &lt;span class="caps"&gt;OS&lt;/span&gt; to shut down before battery depletion.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Expandability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Some &lt;span class="caps"&gt;APC&lt;/span&gt; units accept external battery packs (&lt;span class="caps"&gt;EBM&lt;/span&gt;) to extend runtime.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Noise&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Tower &lt;span class="caps"&gt;UPS&lt;/span&gt; units are quieter than rackmount units. For apartments, choose a tower.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;#1: &lt;span class="caps"&gt;APC&lt;/span&gt; Back-&lt;span class="caps"&gt;UPS&lt;/span&gt; Pro &lt;span class="caps"&gt;BR1500G&lt;/span&gt;&lt;/h2&gt;
&lt;h3&gt;Why It Tops Our&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;The &lt;span class="caps"&gt;BR1500G&lt;/span&gt; is the &amp;#8220;standard&amp;#8221; homelab &lt;span class="caps"&gt;UPS&lt;/span&gt;. It offers 1500 &lt;span class="caps"&gt;VA&lt;/span&gt; / 865 W, 10 outlets (5 battery + 5 surge), a &lt;span class="caps"&gt;USB&lt;/span&gt; management port, and &lt;span class="caps"&gt;APC&lt;/span&gt;&amp;#8217;s PowerChute software. It is reliable, widely available, and has a huge community of users who have integrated it with Proxmox, TrueNAS, and &lt;span class="caps"&gt;NUT&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;VA&lt;/span&gt; / Watt&lt;/td&gt;
&lt;td&gt;1500 &lt;span class="caps"&gt;VA&lt;/span&gt; / 865 W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Outlets&lt;/td&gt;
&lt;td&gt;10 (5 battery + 5 surge)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Topology&lt;/td&gt;
&lt;td&gt;Line-interactive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Form&lt;/td&gt;
&lt;td&gt;Tower&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;USB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Yes (&lt;span class="caps"&gt;USB&lt;/span&gt;-B)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network card&lt;/td&gt;
&lt;td&gt;Optional (&lt;span class="caps"&gt;AP9640&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Display&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;LCD&lt;/span&gt; (load, runtime, battery health)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runtime @ 50%&lt;/td&gt;
&lt;td&gt;~12 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Warranty&lt;/td&gt;
&lt;td&gt;3 years (includes battery)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="caps"&gt;LCD&lt;/span&gt; shows exact load percentage and estimated&amp;nbsp;runtime.&lt;/li&gt;
&lt;li&gt;PowerChute software works on Windows, macOS, and Linux (via &lt;span class="caps"&gt;NUT&lt;/span&gt;).&lt;/li&gt;
&lt;li&gt;5 battery-backed outlets are enough for a mini &lt;span class="caps"&gt;PC&lt;/span&gt; + switch + router +&amp;nbsp;modem.&lt;/li&gt;
&lt;li&gt;Hot-swappable battery (&lt;span class="caps"&gt;RBC123&lt;/span&gt;) is easy to&amp;nbsp;find.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;865 W may not be enough for a dual-socket rack server + &lt;span class="caps"&gt;GPU&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;No native rackmount form&amp;nbsp;factor.&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;APC&lt;/span&gt;&amp;#8217;s proprietary network card is&amp;nbsp;expensive.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Small-to-medium homelabs (mini &lt;span class="caps"&gt;PC&lt;/span&gt;, tower server, &lt;span class="caps"&gt;NAS&lt;/span&gt;) with a total load under 500&amp;nbsp;W.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;New:&lt;/strong&gt; $180–$220 &lt;span class="caps"&gt;USD&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Replacement battery (&lt;span class="caps"&gt;RBC123&lt;/span&gt;):&lt;/strong&gt;&amp;nbsp;$40–$60&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;#2: CyberPower &lt;span class="caps"&gt;CP1500PFCLCD&lt;/span&gt;&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;The &lt;span class="caps"&gt;CP1500PFCLCD&lt;/span&gt; is CyberPower&amp;#8217;s answer to the &lt;span class="caps"&gt;APC&lt;/span&gt; &lt;span class="caps"&gt;BR1500G&lt;/span&gt;. It uses a &lt;strong&gt;pure sine wave&lt;/strong&gt; inverter, which is critical for Active &lt;span class="caps"&gt;PFC&lt;/span&gt; power supplies (common in modern servers and high-end desktops). It also has a slightly higher wattage (900 W) and a &lt;span class="caps"&gt;USB&lt;/span&gt; charging port on the&amp;nbsp;front.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;VA&lt;/span&gt; / Watt&lt;/td&gt;
&lt;td&gt;1500 &lt;span class="caps"&gt;VA&lt;/span&gt; / 900 W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Outlets&lt;/td&gt;
&lt;td&gt;12 (6 battery + 6 surge)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Topology&lt;/td&gt;
&lt;td&gt;Line-interactive (pure sine wave)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Form&lt;/td&gt;
&lt;td&gt;Tower&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;USB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Yes (&lt;span class="caps"&gt;USB&lt;/span&gt;-B)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network card&lt;/td&gt;
&lt;td&gt;Optional (&lt;span class="caps"&gt;RMCARD205&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Display&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;LCD&lt;/span&gt; (color, with load bar)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runtime @ 50%&lt;/td&gt;
&lt;td&gt;~10 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Warranty&lt;/td&gt;
&lt;td&gt;3 years&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Pure sine wave ensures compatibility with Active &lt;span class="caps"&gt;PFC&lt;/span&gt; PSUs (no shutdowns on&amp;nbsp;battery).&lt;/li&gt;
&lt;li&gt;12 outlets mean you can plug in monitors, &lt;span class="caps"&gt;USB&lt;/span&gt; hubs, and chargers without a power&amp;nbsp;strip.&lt;/li&gt;
&lt;li&gt;CyberPower&amp;#8217;s software is Linux-friendly and supports &lt;span class="caps"&gt;NUT&lt;/span&gt; out of the&amp;nbsp;box.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Runtime is slightly shorter than the &lt;span class="caps"&gt;APC&lt;/span&gt; &lt;span class="caps"&gt;BR1500G&lt;/span&gt; at the same&amp;nbsp;load.&lt;/li&gt;
&lt;li&gt;Network card is less common than &lt;span class="caps"&gt;APC&lt;/span&gt;&amp;#8217;s in the used&amp;nbsp;market.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Users with Active &lt;span class="caps"&gt;PFC&lt;/span&gt; power supplies (most modern rack servers and gaming&amp;nbsp;PCs).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;New:&lt;/strong&gt; $170–$210 &lt;span class="caps"&gt;USD&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Replacement battery:&lt;/strong&gt;&amp;nbsp;$45–$65&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;#3: Tripp Lite &lt;span class="caps"&gt;SMART1500LCD&lt;/span&gt;&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;Tripp Lite (now Eaton) makes bulletproof &lt;span class="caps"&gt;UPS&lt;/span&gt; units. The &lt;span class="caps"&gt;SMART1500LCD&lt;/span&gt; is a line-interactive tower with 1500 &lt;span class="caps"&gt;VA&lt;/span&gt; / 900 W and a robust metal chassis. It is slightly less &amp;#8220;smart home&amp;#8221; friendly than &lt;span class="caps"&gt;APC&lt;/span&gt; or CyberPower, but it is a&amp;nbsp;workhorse.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;VA&lt;/span&gt; / Watt&lt;/td&gt;
&lt;td&gt;1500 &lt;span class="caps"&gt;VA&lt;/span&gt; / 900 W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Outlets&lt;/td&gt;
&lt;td&gt;8 (4 battery + 4 surge)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Topology&lt;/td&gt;
&lt;td&gt;Line-interactive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Form&lt;/td&gt;
&lt;td&gt;Tower&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;USB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Yes (&lt;span class="caps"&gt;USB&lt;/span&gt;-B)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network card&lt;/td&gt;
&lt;td&gt;Optional (&lt;span class="caps"&gt;SNMPWEBCARD&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Display&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;LCD&lt;/span&gt; (basic)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runtime @ 50%&lt;/td&gt;
&lt;td&gt;~11 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Warranty&lt;/td&gt;
&lt;td&gt;2 years&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Metal chassis and high-quality battery&amp;nbsp;connectors.&lt;/li&gt;
&lt;li&gt;Excellent voltage regulation (&lt;span class="caps"&gt;AVR&lt;/span&gt;) without switching to&amp;nbsp;battery.&lt;/li&gt;
&lt;li&gt;Works flawlessly with &lt;span class="caps"&gt;NUT&lt;/span&gt; (Network &lt;span class="caps"&gt;UPS&lt;/span&gt; Tools) on&amp;nbsp;Linux.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Fewer outlets than&amp;nbsp;competitors.&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;LCD&lt;/span&gt; is basic (no runtime estimate in&amp;nbsp;minutes).&lt;/li&gt;
&lt;li&gt;Warranty is&amp;nbsp;shorter.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Users who want a simple, reliable &lt;span class="caps"&gt;UPS&lt;/span&gt; with no&amp;nbsp;frills.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;New:&lt;/strong&gt; $160–$200 &lt;span class="caps"&gt;USD&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Replacement battery:&lt;/strong&gt;&amp;nbsp;$40–$55&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;#4: &lt;span class="caps"&gt;APC&lt;/span&gt; Smart-&lt;span class="caps"&gt;UPS&lt;/span&gt; &lt;span class="caps"&gt;SMT1500RM2U&lt;/span&gt;&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;If you have a rack and need a &lt;strong&gt;rackmount&lt;/strong&gt; &lt;span class="caps"&gt;UPS&lt;/span&gt;, the &lt;span class="caps"&gt;APC&lt;/span&gt; Smart-&lt;span class="caps"&gt;UPS&lt;/span&gt; &lt;span class="caps"&gt;SMT1500RM2U&lt;/span&gt; is the industry standard. It is a 2U online/line-interactive unit with a 1500 &lt;span class="caps"&gt;VA&lt;/span&gt; / 1000 W rating and an optional network management card. It is overkill for a mini &lt;span class="caps"&gt;PC&lt;/span&gt;, but essential for a rack&amp;nbsp;server.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;VA&lt;/span&gt; / Watt&lt;/td&gt;
&lt;td&gt;1500 &lt;span class="caps"&gt;VA&lt;/span&gt; / 1000 W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Outlets&lt;/td&gt;
&lt;td&gt;8 (all battery-backed)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Topology&lt;/td&gt;
&lt;td&gt;Line-interactive (Smart-&lt;span class="caps"&gt;UPS&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Form&lt;/td&gt;
&lt;td&gt;2U rackmount&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;USB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Yes (&lt;span class="caps"&gt;USB&lt;/span&gt;-B)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network card&lt;/td&gt;
&lt;td&gt;Optional (&lt;span class="caps"&gt;AP9640&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Display&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;LCD&lt;/span&gt; (front panel)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runtime @ 50%&lt;/td&gt;
&lt;td&gt;~18 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Warranty&lt;/td&gt;
&lt;td&gt;3 years (online warranty)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Rackmount form factor fits standard 19&amp;#8221;&amp;nbsp;racks.&lt;/li&gt;
&lt;li&gt;Higher wattage (1000 W) supports dual-socket&amp;nbsp;servers.&lt;/li&gt;
&lt;li&gt;Can add external battery modules (&lt;span class="caps"&gt;SURT48XLBP&lt;/span&gt;) for 30+ minute&amp;nbsp;runtime.&lt;/li&gt;
&lt;li&gt;Network card enables &lt;span class="caps"&gt;SNMP&lt;/span&gt; monitoring and email&amp;nbsp;alerts.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Loud fans (40–50 dB). Not for living&amp;nbsp;rooms.&lt;/li&gt;
&lt;li&gt;Heavy (30+ kg). Requires a sturdy&amp;nbsp;rack.&lt;/li&gt;
&lt;li&gt;Expensive.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Rack homelabs with 500–800 W loads and need for rackmount&amp;nbsp;integration.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;New:&lt;/strong&gt; $600–$800 &lt;span class="caps"&gt;USD&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Used (eBay):&lt;/strong&gt; $250–400 (often missing network&amp;nbsp;card)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;External battery pack:&lt;/strong&gt;&amp;nbsp;$400–600&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;#5: Eaton&amp;nbsp;5E650iUSB&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;For a very small homelab (one mini &lt;span class="caps"&gt;PC&lt;/span&gt; and a router), the Eaton 5E650iUSB is a compact, budget-friendly &lt;span class="caps"&gt;UPS&lt;/span&gt;. It provides 650 &lt;span class="caps"&gt;VA&lt;/span&gt; / 360 W, which is enough for a Beelink &lt;span class="caps"&gt;SER6&lt;/span&gt; + switch +&amp;nbsp;modem.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;VA&lt;/span&gt; / Watt&lt;/td&gt;
&lt;td&gt;650 &lt;span class="caps"&gt;VA&lt;/span&gt; / 360 W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Outlets&lt;/td&gt;
&lt;td&gt;4 (2 battery + 2 surge)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Topology&lt;/td&gt;
&lt;td&gt;Standby (offline)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Form&lt;/td&gt;
&lt;td&gt;Mini-tower&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;USB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Yes (&lt;span class="caps"&gt;USB&lt;/span&gt;-B)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network card&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Display&lt;/td&gt;
&lt;td&gt;LEDs only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runtime @ 50%&lt;/td&gt;
&lt;td&gt;~8 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Warranty&lt;/td&gt;
&lt;td&gt;2 years&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Very affordable and&amp;nbsp;compact.&lt;/li&gt;
&lt;li&gt;Eaton&amp;#8217;s software works well with Linux and &lt;span class="caps"&gt;NUT&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;Quiet&amp;nbsp;operation.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Standby topology means a brief transfer time (4–10 ms). Not ideal for sensitive&amp;nbsp;servers.&lt;/li&gt;
&lt;li&gt;Only 2 battery outlets. You need a power strip for additional surge&amp;nbsp;protection.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Single-node mini &lt;span class="caps"&gt;PC&lt;/span&gt; homelabs with a load under 200&amp;nbsp;W.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;New:&lt;/strong&gt; $60–$80 &lt;span class="caps"&gt;USD&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Replacement battery:&lt;/strong&gt;&amp;nbsp;$25–35&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Quick Comparison&amp;nbsp;Table&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;VA&lt;/span&gt; / Watt&lt;/th&gt;
&lt;th&gt;Outlets&lt;/th&gt;
&lt;th&gt;Form&lt;/th&gt;
&lt;th&gt;Runtime @ 50%&lt;/th&gt;
&lt;th&gt;Pure Sine&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;APC&lt;/span&gt; &lt;span class="caps"&gt;BR1500G&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1500 / 865&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;Tower&lt;/td&gt;
&lt;td&gt;~12 min&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;$180–220&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CyberPower &lt;span class="caps"&gt;CP1500PFCLCD&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1500 / 900&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;Tower&lt;/td&gt;
&lt;td&gt;~10 min&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;$170–210&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tripp Lite &lt;span class="caps"&gt;SMART1500LCD&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1500 / 900&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;Tower&lt;/td&gt;
&lt;td&gt;~11 min&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;$160–200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;APC&lt;/span&gt; &lt;span class="caps"&gt;SMT1500RM2U&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1500 / 1000&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;2U Rack&lt;/td&gt;
&lt;td&gt;~18 min&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;$600–800&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Eaton 5E650iUSB&lt;/td&gt;
&lt;td&gt;650 / 360&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Mini Tower&lt;/td&gt;
&lt;td&gt;~8 min&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;$60–80&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Calculate Your Load Before&amp;nbsp;Buying&lt;/h3&gt;
&lt;p&gt;Use a Kill-A-Watt meter&amp;nbsp;or &lt;code&gt;ipmitool&lt;/code&gt; / &lt;code&gt;sensors&lt;/code&gt; to measure your homelab&amp;#8217;s actual wattage. Add 20% headroom. If your load is 300 W, buy a 600 W (or higher) &lt;span class="caps"&gt;UPS&lt;/span&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# On Linux, estimate power for a mini PC&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;powertop
powertop
&lt;span class="c1"&gt;# Look for &amp;quot;The battery reports a discharge rate of...&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 2: Use &lt;span class="caps"&gt;NUT&lt;/span&gt; for Automated&amp;nbsp;Shutdown&lt;/h3&gt;
&lt;p&gt;&lt;span class="caps"&gt;NUT&lt;/span&gt; (Network &lt;span class="caps"&gt;UPS&lt;/span&gt; Tools) lets your Proxmox host or &lt;span class="caps"&gt;NAS&lt;/span&gt; monitor the &lt;span class="caps"&gt;UPS&lt;/span&gt; and shut down gracefully when battery is&amp;nbsp;low.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Install NUT on Proxmox&lt;/span&gt;
apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;nut
&lt;span class="c1"&gt;# Edit /etc/nut/ups.conf to add your UPS (usbhid-ups driver)&lt;/span&gt;
&lt;span class="c1"&gt;# Edit /etc/nut/upsmon.conf to set the shutdown threshold (e.g., 20% battery)&lt;/span&gt;
systemctl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;nut-client
systemctl&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;nut-client
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 3: Replace Batteries Every 3–5&amp;nbsp;Years&lt;/h3&gt;
&lt;p&gt;Sealed lead-acid (&lt;span class="caps"&gt;SLA&lt;/span&gt;) batteries degrade. Even if the &lt;span class="caps"&gt;UPS&lt;/span&gt; &amp;#8220;works,&amp;#8221; a 5-year-old battery may give only 2 minutes of runtime. Replace&amp;nbsp;proactively.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;For most homelabbers, the &lt;strong&gt;&lt;span class="caps"&gt;APC&lt;/span&gt; Back-&lt;span class="caps"&gt;UPS&lt;/span&gt; Pro &lt;span class="caps"&gt;BR1500G&lt;/span&gt;&lt;/strong&gt; or the &lt;strong&gt;CyberPower &lt;span class="caps"&gt;CP1500PFCLCD&lt;/span&gt;&lt;/strong&gt; is the sweet spot. They offer enough wattage for a mini &lt;span class="caps"&gt;PC&lt;/span&gt; or tower server, have &lt;span class="caps"&gt;USB&lt;/span&gt; monitoring, and support &lt;span class="caps"&gt;NUT&lt;/span&gt;. If you have a rack server, step up to the &lt;strong&gt;&lt;span class="caps"&gt;APC&lt;/span&gt; Smart-&lt;span class="caps"&gt;UPS&lt;/span&gt; &lt;span class="caps"&gt;SMT1500RM2U&lt;/span&gt;&lt;/strong&gt;. For a single-node mini &lt;span class="caps"&gt;PC&lt;/span&gt;, the &lt;strong&gt;Eaton 5E650iUSB&lt;/strong&gt; is a budget-friendly&amp;nbsp;start.&lt;/p&gt;
&lt;h3&gt;Our&amp;nbsp;Recommendation&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mini &lt;span class="caps"&gt;PC&lt;/span&gt; homelab (1 node):&lt;/strong&gt; Eaton 5E650iUSB ($70) or CyberPower &lt;span class="caps"&gt;CP1500PFCLCD&lt;/span&gt;&amp;nbsp;($190)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tower server / &lt;span class="caps"&gt;NAS&lt;/span&gt; (2–3 nodes):&lt;/strong&gt; &lt;span class="caps"&gt;APC&lt;/span&gt; &lt;span class="caps"&gt;BR1500G&lt;/span&gt; ($200) or CyberPower &lt;span class="caps"&gt;CP1500PFCLCD&lt;/span&gt;&amp;nbsp;($190)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rack server (500+ W):&lt;/strong&gt; &lt;span class="caps"&gt;APC&lt;/span&gt; &lt;span class="caps"&gt;SMT1500RM2U&lt;/span&gt; ($700) + external battery&amp;nbsp;pack&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;APC&lt;/span&gt; / CyberPower / Eaton&lt;/strong&gt;: Amazon, B&amp;amp;H, or Newegg affiliate&amp;nbsp;links&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Replacement batteries&lt;/strong&gt;: &lt;span class="caps"&gt;RBC123&lt;/span&gt;, &lt;span class="caps"&gt;RBC7&lt;/span&gt;, and generic 12V 7Ah battery&amp;nbsp;packs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;NUT&lt;/span&gt; accessories&lt;/strong&gt;: &lt;span class="caps"&gt;USB&lt;/span&gt; cables, network&amp;nbsp;cards&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;why-this-matters&lt;/code&gt; → &lt;code&gt;homelab-server-hardware-2026&lt;/code&gt; — &amp;#8220;calculate your server&amp;#8217;s power&amp;nbsp;draw&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;item-1&lt;/code&gt; → &lt;code&gt;best-rack-server-for-homelab&lt;/code&gt; — &amp;#8220;rack server power&amp;nbsp;requirements&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;proxmox-beginner-guide-2026&lt;/code&gt; — &amp;#8220;protect your Proxmox host with a &lt;span class="caps"&gt;UPS&lt;/span&gt;&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] What &lt;span class="caps"&gt;UPS&lt;/span&gt; are you running? How long does it keep your lab alive? Share your runtime&amp;nbsp;below!&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for power efficiency guides, &lt;span class="caps"&gt;UPS&lt;/span&gt; reviews, and homelab safety&amp;nbsp;tips.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Guides"/><category term="ups"/><category term="homelab"/><category term="power"/><category term="backup"/><category term="apc"/><category term="cyberpower"/><category term="tripp-lite"/></entry><entry><title>Best Used Server Hardware for Homelab in 2026: Dell, HP, and Supermicro</title><link href="https://steadypub.com/2026/06/used-server-hardware-for-homelab/" rel="alternate"/><published>2026-06-05T00:00:00+07:00</published><updated>2026-06-05T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/used-server-hardware-for-homelab/</id><summary type="html">&lt;p&gt;A curated guide to the best used enterprise servers for homelab in 2026. Compare Dell PowerEdge, &lt;span class="caps"&gt;HP&lt;/span&gt; ProLiant, and Supermicro models with real specs, eBay pricing, and power&amp;nbsp;consumption.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~14 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelabbers seeking enterprise-grade hardware on a&amp;nbsp;budget&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why Buy Used Enterprise&amp;nbsp;Servers?&lt;/h2&gt;
&lt;p&gt;Used enterprise servers offer unmatched value for homelabbers. A $200 used Dell R720 can deliver dual Xeon CPUs, &lt;span class="caps"&gt;128GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; support, and 8 drive bays — specs that would cost $1,000+ to build from scratch with new consumer&amp;nbsp;hardware.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key&amp;nbsp;advantages:&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Advantage&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Price&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$150–$400 for a complete server vs. $500+ for new mini PCs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt; capacity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;192GB&lt;/span&gt;–1.&lt;span class="caps"&gt;5TB&lt;/span&gt; &lt;span class="caps"&gt;ECC&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; support (critical for &lt;span class="caps"&gt;ZFS&lt;/span&gt;/VMs)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Drive bays&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;8–24 hot-swap bays with hardware &lt;span class="caps"&gt;RAID&lt;/span&gt; or &lt;span class="caps"&gt;HBA&lt;/span&gt; support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;IPMI&lt;/span&gt;/iDRAC/iLO&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Out-of-band management (remote power, console, &lt;span class="caps"&gt;ISO&lt;/span&gt; mount)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;ECC&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Error-correcting memory prevents data corruption&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Reliability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Built for 24/7 operation over 5–10 year lifespans&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Trade-offs:&lt;/strong&gt;
- Power consumption: 100–200W idle vs. 10–15W for mini PCs
- Noise: 1U servers can be loud; 2U and tower models are quieter
- Size: Rack servers need a rack or shelf space
- Weight: 20–30 kg shipping&amp;nbsp;costs&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Evaluation&amp;nbsp;Criteria&lt;/h2&gt;
&lt;h3&gt;Price-to-Performance&lt;/h3&gt;
&lt;p&gt;The sweet spot is Gen 8–9 Intel (Sandy Bridge/Ivy Bridge) and Gen 8–10 &lt;span class="caps"&gt;AMD&lt;/span&gt; (Bulldozer/Piledriver). These generations offer PCIe 3.0, &lt;span class="caps"&gt;DDR3&lt;/span&gt;/&lt;span class="caps"&gt;DDR4&lt;/span&gt;, and modern virtualization support at rock-bottom&amp;nbsp;prices.&lt;/p&gt;
&lt;h3&gt;Feature&amp;nbsp;Set&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Remote management:&lt;/strong&gt; iDRAC (Dell), iLO (&lt;span class="caps"&gt;HP&lt;/span&gt;), &lt;span class="caps"&gt;IPMI&lt;/span&gt; (Supermicro) — essential for headless&amp;nbsp;operation&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PCIe slots:&lt;/strong&gt; For 10GbE NICs, &lt;span class="caps"&gt;HBA&lt;/span&gt; cards, or&amp;nbsp;GPUs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Drive bays:&lt;/strong&gt; &lt;span class="caps"&gt;LFF&lt;/span&gt; (3.5&amp;#8221;) for bulk storage, &lt;span class="caps"&gt;SFF&lt;/span&gt; (2.5&amp;#8221;) for&amp;nbsp;SSDs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Power supply:&lt;/strong&gt; Redundant PSUs preferred; single &lt;span class="caps"&gt;PSU&lt;/span&gt; is acceptable for&amp;nbsp;homelab&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Community &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;Support&lt;/h3&gt;
&lt;p&gt;Dell and &lt;span class="caps"&gt;HP&lt;/span&gt; have the largest homelab communities. Supermicro has less hand-holding but more flexibility. Lenovo ThinkSystem is the dark horse with excellent&amp;nbsp;value.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;#1: Dell PowerEdge R720 (Best&amp;nbsp;All-Rounder)&lt;/h2&gt;
&lt;h3&gt;Why It Tops Our&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;The R720 is the undisputed king of the homelab. It balances price, performance, and community support perfectly. With dual-socket Xeon E5-2600 v1/v2, 24 &lt;span class="caps"&gt;DIMM&lt;/span&gt; slots, and up to 16 drive bays, it can handle anything from a Plex server to a Proxmox cluster&amp;nbsp;node.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Specification&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Dual Xeon E5-2600 v1/v2 (up to 12 cores/24 threads per socket)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;24x &lt;span class="caps"&gt;DDR3&lt;/span&gt; &lt;span class="caps"&gt;DIMM&lt;/span&gt; slots (up to &lt;span class="caps"&gt;768GB&lt;/span&gt; &lt;span class="caps"&gt;ECC&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;8x &lt;span class="caps"&gt;LFF&lt;/span&gt; or 16x &lt;span class="caps"&gt;SFF&lt;/span&gt; hot-swap bays&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAID&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;PERC&lt;/span&gt; H710/&lt;span class="caps"&gt;H710P&lt;/span&gt; (up to 6Gb/s &lt;span class="caps"&gt;SAS&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PCIe&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;7x PCIe 3.0 slots (full-height, full-length)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Network&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;4x 1GbE (Broadcom) or 2x 10GbE + 2x 1GbE (optional)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;IPMI&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;iDRAC 7 Enterprise (dedicated &lt;span class="caps"&gt;NIC&lt;/span&gt;, remote console)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;PSU&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Dual redundant 750W/1100W (hot-swap)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Form factor&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2U rack&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Massive community support (Reddit r/homelab,&amp;nbsp;ServeTheHome)&lt;/li&gt;
&lt;li&gt;iDRAC 7 Enterprise is excellent for remote&amp;nbsp;management&lt;/li&gt;
&lt;li&gt;16x &lt;span class="caps"&gt;SFF&lt;/span&gt; version is ideal for all-&lt;span class="caps"&gt;SSD&lt;/span&gt;&amp;nbsp;setups&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;PERC&lt;/span&gt; H710 supports &lt;span class="caps"&gt;IT&lt;/span&gt; mode flash for &lt;span class="caps"&gt;ZFS&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;PCIe slots allow 10GbE, &lt;span class="caps"&gt;HBA&lt;/span&gt;, or even low-profile &lt;span class="caps"&gt;GPU&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="caps"&gt;DDR3&lt;/span&gt; is aging; &lt;span class="caps"&gt;DDR4&lt;/span&gt; models (R730) cost&amp;nbsp;more&lt;/li&gt;
&lt;li&gt;2U size still needs rack or shelf&amp;nbsp;space&lt;/li&gt;
&lt;li&gt;Idle power: ~120W with dual &lt;span class="caps"&gt;CPU&lt;/span&gt; and &lt;span class="caps"&gt;64GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Loud at boot; manageable with fan curve&amp;nbsp;tuning&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Proxmox/&lt;span class="caps"&gt;KVM&lt;/span&gt; virtualization&amp;nbsp;hosts&lt;/li&gt;
&lt;li&gt;TrueNAS/FreeNAS with 8+&amp;nbsp;drives&lt;/li&gt;
&lt;li&gt;Plex/Jellyfin with hardware transcoding (add Intel &lt;span class="caps"&gt;GPU&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;Learning enterprise server&amp;nbsp;management&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing (eBay,&amp;nbsp;2026)&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Configuration&lt;/th&gt;
&lt;th&gt;Price Range&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Barebones (no &lt;span class="caps"&gt;CPU&lt;/span&gt;/&lt;span class="caps"&gt;RAM&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;$80–$120&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Single E5-2670, &lt;span class="caps"&gt;32GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$150–$200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dual E5-2680 v2, &lt;span class="caps"&gt;64GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$220–$300&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fully loaded (dual &lt;span class="caps"&gt;CPU&lt;/span&gt;, &lt;span class="caps"&gt;128GB&lt;/span&gt;, &lt;span class="caps"&gt;HBA&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;$350–$450&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rails + bezel + cable arm&lt;/td&gt;
&lt;td&gt;$40–$60 extra&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;#2: &lt;span class="caps"&gt;HP&lt;/span&gt; ProLiant DL380p Gen8 (Best Build&amp;nbsp;Quality)&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;The DL380p Gen8 is &lt;span class="caps"&gt;HP&lt;/span&gt;&amp;#8217;s answer to the R720 and is arguably better built. The tool-less chassis, excellent iLO 4, and &lt;span class="caps"&gt;HP&lt;/span&gt;&amp;#8217;s firmware ecosystem make it a favorite for sysadmins. It often sells for 20–30% less than the equivalent&amp;nbsp;R720.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Specification&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Dual Xeon E5-2600 v1/v2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;24x &lt;span class="caps"&gt;DDR3&lt;/span&gt; &lt;span class="caps"&gt;DIMM&lt;/span&gt; slots (up to &lt;span class="caps"&gt;768GB&lt;/span&gt; &lt;span class="caps"&gt;ECC&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;8x &lt;span class="caps"&gt;LFF&lt;/span&gt; or 16x &lt;span class="caps"&gt;SFF&lt;/span&gt; hot-swap bays&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAID&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Smart Array P420i/P420 (supports &lt;span class="caps"&gt;IT&lt;/span&gt; mode)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PCIe&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;6x PCIe 3.0 slots&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Network&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;4x 1GbE (&lt;span class="caps"&gt;HP&lt;/span&gt; FlexLOM, upgradable to 10GbE)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;IPMI&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;iLO 4 Advanced (&lt;span class="caps"&gt;HTML5&lt;/span&gt; remote console)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;PSU&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Dual redundant (460W/750W/1200W options)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Form factor&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2U rack&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Often cheaper than R720 ($140–$180 for dual &lt;span class="caps"&gt;CPU&lt;/span&gt;&amp;nbsp;config)&lt;/li&gt;
&lt;li&gt;iLO 4 Advanced has &lt;span class="caps"&gt;HTML5&lt;/span&gt; console (no Java&amp;nbsp;needed)&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;HP&lt;/span&gt; FlexLOM lets you swap NICs without a PCIe&amp;nbsp;slot&lt;/li&gt;
&lt;li&gt;Excellent build quality and cable&amp;nbsp;management&lt;/li&gt;
&lt;li&gt;Tool-less drive bays and PCIe&amp;nbsp;risers&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="caps"&gt;HP&lt;/span&gt; custom drive caddies cost $5–$10 each if&amp;nbsp;missing&lt;/li&gt;
&lt;li&gt;iLO 4 Advanced license may need to be purchased separately ($20–$30 on&amp;nbsp;eBay)&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;HP&lt;/span&gt; Smart Array requires more effort for &lt;span class="caps"&gt;HBA&lt;/span&gt;/&lt;span class="caps"&gt;IT&lt;/span&gt;&amp;nbsp;mode&lt;/li&gt;
&lt;li&gt;Slightly smaller PCIe ecosystem than&amp;nbsp;Dell&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Budget-conscious buyers wanting R720-class&amp;nbsp;specs&lt;/li&gt;
&lt;li&gt;Sysadmins training on &lt;span class="caps"&gt;HP&lt;/span&gt;/&lt;span class="caps"&gt;HPE&lt;/span&gt; enterprise&amp;nbsp;tools&lt;/li&gt;
&lt;li&gt;Homelabs needing 16x &lt;span class="caps"&gt;SFF&lt;/span&gt; drive&amp;nbsp;bays&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing (eBay,&amp;nbsp;2026)&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Configuration&lt;/th&gt;
&lt;th&gt;Price Range&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Single E5-2670, &lt;span class="caps"&gt;32GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$130–$170&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dual E5-2680 v2, &lt;span class="caps"&gt;64GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$190–$250&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Barebones&lt;/td&gt;
&lt;td&gt;$70–$100&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Drive caddies (8-pack)&lt;/td&gt;
&lt;td&gt;$40–$50&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;#3: Dell PowerEdge R730 (Best &lt;span class="caps"&gt;DDR4&lt;/span&gt;&amp;nbsp;Value)&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;The R730 is the &lt;span class="caps"&gt;DDR4&lt;/span&gt; successor to the R720. It supports Xeon E5-2600 v3/v4 (Haswell/Broadwell), &lt;span class="caps"&gt;DDR4&lt;/span&gt; &lt;span class="caps"&gt;ECC&lt;/span&gt;, and has PCIe 3.0 slots. As datacenters decommission these, prices are dropping rapidly in&amp;nbsp;2026.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Specification&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Dual Xeon E5-2600 v3/v4 (up to 22 cores per socket)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;24x &lt;span class="caps"&gt;DDR4&lt;/span&gt; &lt;span class="caps"&gt;DIMM&lt;/span&gt; slots (up to 1.&lt;span class="caps"&gt;5TB&lt;/span&gt; &lt;span class="caps"&gt;ECC&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;8x &lt;span class="caps"&gt;LFF&lt;/span&gt;, 16x &lt;span class="caps"&gt;SFF&lt;/span&gt;, or 24x 2.5&amp;#8221; NVMe-ready&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAID&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;PERC&lt;/span&gt; H730/&lt;span class="caps"&gt;H730P&lt;/span&gt; (12Gb/s &lt;span class="caps"&gt;SAS&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PCIe&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;7x PCIe 3.0 slots (includes x16 for &lt;span class="caps"&gt;GPU&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Network&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;4x 1GbE or 2x 10GbE + 2x 1GbE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;IPMI&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;iDRAC 8 Enterprise&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;PSU&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Dual redundant (750W/1100W/1600W)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Form factor&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2U rack&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="caps"&gt;DDR4&lt;/span&gt; is faster and uses less power than &lt;span class="caps"&gt;DDR3&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;E5-2680 v4 (14 cores) offers excellent performance per&amp;nbsp;watt&lt;/li&gt;
&lt;li&gt;NVMe-ready backplane available on some&amp;nbsp;models&lt;/li&gt;
&lt;li&gt;iDRAC 8 has improved &lt;span class="caps"&gt;HTML5&lt;/span&gt;&amp;nbsp;interface&lt;/li&gt;
&lt;li&gt;Future-proofed for 5+ years of homelab&amp;nbsp;use&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Higher upfront cost than&amp;nbsp;R720&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;DDR4&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; is more expensive than &lt;span class="caps"&gt;DDR3&lt;/span&gt; (but&amp;nbsp;dropping)&lt;/li&gt;
&lt;li&gt;Idle power: ~100W (more efficient than&amp;nbsp;R720)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Performance-hungry virtualization&amp;nbsp;clusters&lt;/li&gt;
&lt;li&gt;Future-proof builds where &lt;span class="caps"&gt;DDR4&lt;/span&gt; is&amp;nbsp;preferred&lt;/li&gt;
&lt;li&gt;Proxmox Ceph or VMware vSAN&amp;nbsp;clusters&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing (eBay,&amp;nbsp;2026)&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Configuration&lt;/th&gt;
&lt;th&gt;Price Range&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Single E5-2620 v3, &lt;span class="caps"&gt;32GB&lt;/span&gt; &lt;span class="caps"&gt;DDR4&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$180–$250&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dual E5-2680 v3, &lt;span class="caps"&gt;64GB&lt;/span&gt; &lt;span class="caps"&gt;DDR4&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$300–$400&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dual E5-2680 v4, &lt;span class="caps"&gt;128GB&lt;/span&gt; &lt;span class="caps"&gt;DDR4&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$450–$600&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;#4: Supermicro X9/X10 Series (Best&amp;nbsp;Flexibility)&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;Supermicro doesn&amp;#8217;t have the brand recognition of Dell or &lt;span class="caps"&gt;HP&lt;/span&gt;, but their motherboards and chassis are beloved by &lt;span class="caps"&gt;DIY&lt;/span&gt; homelabbers. You can buy a barebones chassis and build exactly what you want — perfect for custom TrueNAS or Proxmox&amp;nbsp;builds.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Specification&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Single or dual Xeon E5-2600 v1/v2/v3/v4 (board dependent)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;8–24 &lt;span class="caps"&gt;DIMM&lt;/span&gt; slots (up to 1.&lt;span class="caps"&gt;5TB&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;8–24 hot-swap bays (&lt;span class="caps"&gt;LFF&lt;/span&gt; or &lt;span class="caps"&gt;SFF&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAID&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;LSI&lt;/span&gt; 9211-8i / 9300-8i &lt;span class="caps"&gt;HBA&lt;/span&gt; (commonly used)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PCIe&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;3–7x PCIe slots (full-height on tower models)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Network&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Dual 1GbE (Intel i350); 10GbE optional via add-on&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;IPMI&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;IPMI&lt;/span&gt; 2.0 with &lt;span class="caps"&gt;KVM&lt;/span&gt;-over-&lt;span class="caps"&gt;IP&lt;/span&gt; (Aspeed &lt;span class="caps"&gt;AST2400&lt;/span&gt;/2500)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Form factor&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1U, 2U, 3U, 4U, or tower&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Massive flexibility: build exactly what you&amp;nbsp;need&lt;/li&gt;
&lt;li&gt;Tower models (&lt;span class="caps"&gt;SC743&lt;/span&gt;, &lt;span class="caps"&gt;SC745&lt;/span&gt;) are desktop-friendly and&amp;nbsp;quiet&lt;/li&gt;
&lt;li&gt;Excellent &lt;span class="caps"&gt;IPMI&lt;/span&gt; with full remote&amp;nbsp;console&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;LSI&lt;/span&gt; HBAs are widely supported for &lt;span class="caps"&gt;ZFS&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;4U models can fit full-length&amp;nbsp;GPUs&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Smaller community; fewer &amp;#8220;hand-holding&amp;#8221;&amp;nbsp;guides&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;IPMI&lt;/span&gt; firmware updates can be&amp;nbsp;tricky&lt;/li&gt;
&lt;li&gt;Mixing and matching requires more&amp;nbsp;knowledge&lt;/li&gt;
&lt;li&gt;Resale value is lower than Dell/&lt;span class="caps"&gt;HP&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="caps"&gt;DIY&lt;/span&gt; builders who want custom&amp;nbsp;configs&lt;/li&gt;
&lt;li&gt;TrueNAS &lt;span class="caps"&gt;SCALE&lt;/span&gt; with 12+&amp;nbsp;drives&lt;/li&gt;
&lt;li&gt;Tower form factor without rack&amp;nbsp;noise&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;GPU&lt;/span&gt; passthrough builds (4U&amp;nbsp;chassis)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing (eBay,&amp;nbsp;2026)&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Configuration&lt;/th&gt;
&lt;th&gt;Price Range&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;X9DRi barebones + chassis&lt;/td&gt;
&lt;td&gt;$150–$250&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;X10DRi barebones + chassis&lt;/td&gt;
&lt;td&gt;$250–$350&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tower chassis (&lt;span class="caps"&gt;SC743&lt;/span&gt;) + &lt;span class="caps"&gt;PSU&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$100–$150&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;LSI&lt;/span&gt; 9211-8i &lt;span class="caps"&gt;HBA&lt;/span&gt; (flashed &lt;span class="caps"&gt;IT&lt;/span&gt; mode)&lt;/td&gt;
&lt;td&gt;$40–$60&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;#5: Lenovo ThinkSystem &lt;span class="caps"&gt;SR530&lt;/span&gt; (Best Modern&amp;nbsp;Value)&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;The &lt;span class="caps"&gt;SR530&lt;/span&gt; is Lenovo&amp;#8217;s 1U Gen 1 server (Intel Xeon Scalable). As datacenters upgrade to Gen 2/3, Gen 1 systems are flooding the used market. It&amp;#8217;s a 1U server, but quieter than older 1U models and supports modern Xeon Silver/Gold&amp;nbsp;CPUs.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Specification&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Dual Xeon Scalable (Bronze/Silver/Gold Gen 1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;12x &lt;span class="caps"&gt;DDR4&lt;/span&gt; &lt;span class="caps"&gt;DIMM&lt;/span&gt; slots (up to 1.&lt;span class="caps"&gt;5TB&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;4x &lt;span class="caps"&gt;LFF&lt;/span&gt; or 8x &lt;span class="caps"&gt;SFF&lt;/span&gt; hot-swap bays&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAID&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;ThinkSystem &lt;span class="caps"&gt;RAID&lt;/span&gt; 530/930 (supports &lt;span class="caps"&gt;JBOD&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PCIe&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;3x PCIe 3.0 slots (low-profile)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Network&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2x 1GbE ( onboard); 10GbE via PCIe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;IPMI&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;XClarity Controller (remote console, virtual media)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;PSU&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Dual redundant (550W/750W)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Form factor&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1U rack&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Modern Xeon Scalable architecture (PCIe 3.0, &lt;span class="caps"&gt;AVX&lt;/span&gt;-512)&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;DDR4&lt;/span&gt; memory is affordable and&amp;nbsp;fast&lt;/li&gt;
&lt;li&gt;XClarity is a capable remote management&amp;nbsp;tool&lt;/li&gt;
&lt;li&gt;1U form factor fits in shallow racks or&amp;nbsp;cabinets&lt;/li&gt;
&lt;li&gt;Often cheaper than Dell R640&amp;nbsp;equivalent&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;1U = louder than 2U (fan speed is&amp;nbsp;higher)&lt;/li&gt;
&lt;li&gt;Limited PCIe slots (3x&amp;nbsp;low-profile)&lt;/li&gt;
&lt;li&gt;4x &lt;span class="caps"&gt;LFF&lt;/span&gt; or 8x &lt;span class="caps"&gt;SFF&lt;/span&gt; maximum (not for massive&amp;nbsp;storage)&lt;/li&gt;
&lt;li&gt;Smaller homelab community than&amp;nbsp;Dell&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Compact homelabs with shallow depth&amp;nbsp;racks&lt;/li&gt;
&lt;li&gt;Modern virtualization (VMware vSphere&amp;nbsp;7/8)&lt;/li&gt;
&lt;li&gt;Kubernetes clusters needing modern &lt;span class="caps"&gt;CPU&lt;/span&gt;&amp;nbsp;features&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing (eBay,&amp;nbsp;2026)&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Configuration&lt;/th&gt;
&lt;th&gt;Price Range&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Xeon Silver 4110, &lt;span class="caps"&gt;32GB&lt;/span&gt; &lt;span class="caps"&gt;DDR4&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$250–$350&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Xeon Silver 4210, &lt;span class="caps"&gt;64GB&lt;/span&gt; &lt;span class="caps"&gt;DDR4&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$350–$450&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Barebones&lt;/td&gt;
&lt;td&gt;$150–$200&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Quick Comparison&amp;nbsp;Table&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Form Factor&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt; Gen&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt; Max&lt;/th&gt;
&lt;th&gt;Drive Bays&lt;/th&gt;
&lt;th&gt;iDRAC/iLO&lt;/th&gt;
&lt;th&gt;Idle Power&lt;/th&gt;
&lt;th&gt;Price Range&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Dell R720&lt;/td&gt;
&lt;td&gt;2U&lt;/td&gt;
&lt;td&gt;E5 v1/v2&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;768GB&lt;/span&gt; &lt;span class="caps"&gt;DDR3&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;8/16&lt;/td&gt;
&lt;td&gt;iDRAC 7&lt;/td&gt;
&lt;td&gt;~120W&lt;/td&gt;
&lt;td&gt;$150–$350&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;HP&lt;/span&gt; DL380p G8&lt;/td&gt;
&lt;td&gt;2U&lt;/td&gt;
&lt;td&gt;E5 v1/v2&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;768GB&lt;/span&gt; &lt;span class="caps"&gt;DDR3&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;8/16&lt;/td&gt;
&lt;td&gt;iLO 4&lt;/td&gt;
&lt;td&gt;~120W&lt;/td&gt;
&lt;td&gt;$130–$280&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dell R730&lt;/td&gt;
&lt;td&gt;2U&lt;/td&gt;
&lt;td&gt;E5 v3/v4&lt;/td&gt;
&lt;td&gt;1.&lt;span class="caps"&gt;5TB&lt;/span&gt; &lt;span class="caps"&gt;DDR4&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;8/16/24&lt;/td&gt;
&lt;td&gt;iDRAC 8&lt;/td&gt;
&lt;td&gt;~100W&lt;/td&gt;
&lt;td&gt;$200–$500&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Supermicro X9/X10&lt;/td&gt;
&lt;td&gt;1U–4U&lt;/td&gt;
&lt;td&gt;E5 v1–v4&lt;/td&gt;
&lt;td&gt;1.&lt;span class="caps"&gt;5TB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;8–24&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;IPMI&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;~110W&lt;/td&gt;
&lt;td&gt;$150–$400&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lenovo &lt;span class="caps"&gt;SR530&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1U&lt;/td&gt;
&lt;td&gt;Scalable G1&lt;/td&gt;
&lt;td&gt;1.&lt;span class="caps"&gt;5TB&lt;/span&gt; &lt;span class="caps"&gt;DDR4&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;4/8&lt;/td&gt;
&lt;td&gt;XClarity&lt;/td&gt;
&lt;td&gt;~90W&lt;/td&gt;
&lt;td&gt;$200–$400&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Buy from eBay Sellers with&amp;nbsp;Warranties&lt;/h3&gt;
&lt;p&gt;Look for eBay sellers offering 30-day &lt;span class="caps"&gt;DOA&lt;/span&gt; warranties. Enterprise gear is reliable, but a dead &lt;span class="caps"&gt;PSU&lt;/span&gt; or &lt;span class="caps"&gt;RAID&lt;/span&gt; battery can sour the experience. Top sellers: SaveMyServer, TheServerStore,&amp;nbsp;ServerMonkey.&lt;/p&gt;
&lt;h3&gt;Tip 2: Flash Your &lt;span class="caps"&gt;RAID&lt;/span&gt; Controller to &lt;span class="caps"&gt;IT&lt;/span&gt;&amp;nbsp;Mode&lt;/h3&gt;
&lt;p&gt;For &lt;span class="caps"&gt;ZFS&lt;/span&gt; (TrueNAS, Proxmox with Ceph), you want the &lt;span class="caps"&gt;HBA&lt;/span&gt; to pass drives directly to the &lt;span class="caps"&gt;OS&lt;/span&gt;. Flash Dell &lt;span class="caps"&gt;PERC&lt;/span&gt; H310/H710 or &lt;span class="caps"&gt;HP&lt;/span&gt; P420 to &lt;span class="caps"&gt;IT&lt;/span&gt; mode (or buy an &lt;span class="caps"&gt;LSI&lt;/span&gt; 9211-8i). This is critical for homelab&amp;nbsp;storage.&lt;/p&gt;
&lt;h3&gt;Tip 3: Replace Thermal&amp;nbsp;Paste&lt;/h3&gt;
&lt;p&gt;Servers from 2012–2016 have dried-out thermal paste. A $10 tube of Arctic &lt;span class="caps"&gt;MX&lt;/span&gt;-6 and 30 minutes of work can drop &lt;span class="caps"&gt;CPU&lt;/span&gt; temps by 10–20°C and reduce fan noise&amp;nbsp;dramatically.&lt;/p&gt;
&lt;h3&gt;Tip 4: Get the Rails (But Check Your&amp;nbsp;Rack)&lt;/h3&gt;
&lt;p&gt;R720/DL380p rails are ~29&amp;#8221; deep. If you have a network cabinet (shorter depth), you&amp;#8217;ll need a shelf. Always verify rack depth before buying&amp;nbsp;rails.&lt;/p&gt;
&lt;h3&gt;Tip 5: Plan for Power&amp;nbsp;Costs&lt;/h3&gt;
&lt;p&gt;A 120W idle server costs about $10–$15/month in electricity (at $0.12/kWh). Over 3 years, that&amp;#8217;s $360–$540 in power. A mini &lt;span class="caps"&gt;PC&lt;/span&gt; at 15W costs $45–$65 over the same period. Factor this into your total cost of&amp;nbsp;ownership.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;For most homelabbers in 2026, the &lt;strong&gt;Dell R720&lt;/strong&gt; remains the best starting point due to its balance of price, performance, and community support. If you want a quieter, more modern build, the &lt;strong&gt;Dell R730&lt;/strong&gt; or &lt;strong&gt;Supermicro tower&lt;/strong&gt; are excellent alternatives. The &lt;strong&gt;&lt;span class="caps"&gt;HP&lt;/span&gt; DL380p Gen8&lt;/strong&gt; is the budget king, and the &lt;strong&gt;Lenovo &lt;span class="caps"&gt;SR530&lt;/span&gt;&lt;/strong&gt; offers modern architecture at a reasonable&amp;nbsp;price.&lt;/p&gt;
&lt;h3&gt;Our&amp;nbsp;Recommendation&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Budget&lt;/th&gt;
&lt;th&gt;Recommendation&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Under $150&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;HP&lt;/span&gt; DL380p Gen8 barebones + single &lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Cheapest entry to enterprise features&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$150–$300&lt;/td&gt;
&lt;td&gt;Dell R720 dual E5-2670, &lt;span class="caps"&gt;64GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Best community support and iDRAC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$300–$500&lt;/td&gt;
&lt;td&gt;Dell R730 dual E5-2680 v3, &lt;span class="caps"&gt;64GB&lt;/span&gt; &lt;span class="caps"&gt;DDR4&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Future-proofed with &lt;span class="caps"&gt;DDR4&lt;/span&gt; and efficiency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$500+&lt;/td&gt;
&lt;td&gt;Supermicro tower + custom build&lt;/td&gt;
&lt;td&gt;Maximum flexibility and quiet operation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dell R720&lt;/strong&gt;: eBay server listings — contextual link in pricing&amp;nbsp;section&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;HP&lt;/span&gt; DL380p&lt;/strong&gt;: eBay server listings — contextual link in pricing&amp;nbsp;section&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;LSI&lt;/span&gt; 9211-8i&lt;/strong&gt;: &lt;span class="caps"&gt;HBA&lt;/span&gt; card affiliate&amp;nbsp;links&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Arctic &lt;span class="caps"&gt;MX&lt;/span&gt;-6&lt;/strong&gt;: Thermal paste Amazon&amp;nbsp;affiliate&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;intro&lt;/code&gt; → &lt;code&gt;best-rack-server-for-homelab&lt;/code&gt; for rack&amp;nbsp;recommendations&lt;/li&gt;
&lt;li&gt;&lt;code&gt;power-costs&lt;/code&gt; → &lt;code&gt;ups-for-homelab&lt;/code&gt; for &lt;span class="caps"&gt;UPS&lt;/span&gt;&amp;nbsp;sizing&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;proxmox-beginner-guide-2026&lt;/code&gt; for next steps after buying&amp;nbsp;hardware&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] What&amp;#8217;s your used server homelab setup? Share your specs and eBay deals in the&amp;nbsp;comments!&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for monthly homelab hardware deal roundups and price&amp;nbsp;tracking.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Guides"/><category term="used server hardware"/><category term="homelab"/><category term="dell r720"/><category term="hp dl380p"/><category term="supermicro"/><category term="rack server"/><category term="budget homelab"/></entry><entry><title>VPS vs Homelab Server: Which One Wins for Your Self-Hosting?</title><link href="https://steadypub.com/2026/06/vps-vs-homelab-server/" rel="alternate"/><published>2026-06-05T00:00:00+07:00</published><updated>2026-06-05T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/vps-vs-homelab-server/</id><summary type="html">&lt;p&gt;A head-to-head comparison of &lt;span class="caps"&gt;VPS&lt;/span&gt; hosting and a physical homelab server. Covers cost, performance, privacy, scalability, and real use cases to help you&amp;nbsp;decide.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~11 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Self-hosters deciding between a cloud &lt;span class="caps"&gt;VPS&lt;/span&gt; and a home&amp;nbsp;server&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The &lt;span class="caps"&gt;VPS&lt;/span&gt; vs Homelab Server&amp;nbsp;Dilemma&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;A &lt;span class="caps"&gt;VPS&lt;/span&gt; (Virtual Private Server) is a slice of a datacenter server you rent by the month. A homelab server is a physical machine sitting in your home. Both let you self-host apps, but they differ radically in cost, privacy, performance, and control. This guide breaks down the trade-offs so you can choose the right infrastructure for your&amp;nbsp;goals.&lt;/p&gt;
&lt;h3&gt;Key Differences at a&amp;nbsp;Glance&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt; (Cloud)&lt;/th&gt;
&lt;th&gt;Homelab Server&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Location&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Remote datacenter&lt;/td&gt;
&lt;td&gt;Your home or office&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hardware&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Shared (oversubscribed)&lt;/td&gt;
&lt;td&gt;Dedicated (yours alone)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Upfront cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;td&gt;$150–$2,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Monthly cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$5–$100+&lt;/td&gt;
&lt;td&gt;$5–$30 (electricity)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Internet speed&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1–10 Gbps symmetric&lt;/td&gt;
&lt;td&gt;Depends on your &lt;span class="caps"&gt;ISP&lt;/span&gt; (usually asymmetric)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;IP&lt;/span&gt; address&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Static or dynamic (provider dependent)&lt;/td&gt;
&lt;td&gt;Dynamic (unless you pay for static)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Privacy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Provider can inspect VMs&lt;/td&gt;
&lt;td&gt;Physical control; no third-party access&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Noise / heat&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Yes (depends on hardware)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scalability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Instant resize&lt;/td&gt;
&lt;td&gt;Must buy new hardware&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Learning value&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Limited (managed infra)&lt;/td&gt;
&lt;td&gt;High (networking, hardware, virtualization)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Option A: &lt;span class="caps"&gt;VPS&lt;/span&gt; (Virtual Private&amp;nbsp;Server)&lt;/h2&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No hardware hassle:&lt;/strong&gt; No buying, building, or maintaining a physical&amp;nbsp;machine.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Datacenter connectivity:&lt;/strong&gt; 1 Gbps+ uplink, DDoS protection, and redundant&amp;nbsp;power.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Static &lt;span class="caps"&gt;IP&lt;/span&gt;:&lt;/strong&gt; Most providers offer a static IPv4 address (essential for &lt;span class="caps"&gt;DNS&lt;/span&gt; and mail&amp;nbsp;servers).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Global presence:&lt;/strong&gt; Deploy in Tokyo, Frankfurt, or New York to reduce latency for&amp;nbsp;users.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Snapshot backups:&lt;/strong&gt; One-click disk snapshots stored&amp;nbsp;off-site.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No noise / heat:&lt;/strong&gt; Perfect for apartments or shared living&amp;nbsp;spaces.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Recurring cost:&lt;/strong&gt; A $10/month &lt;span class="caps"&gt;VPS&lt;/span&gt; costs $120/year. A $40/month &lt;span class="caps"&gt;VPS&lt;/span&gt; costs $480/year. Over 3 years, you could have bought a powerful mini &lt;span class="caps"&gt;PC&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Oversubscription:&lt;/strong&gt; Many budget &lt;span class="caps"&gt;VPS&lt;/span&gt; providers oversell &lt;span class="caps"&gt;CPU&lt;/span&gt; and &lt;span class="caps"&gt;RAM&lt;/span&gt;. Your &amp;#8220;2 core&amp;#8221; &lt;span class="caps"&gt;VPS&lt;/span&gt; may share a physical core with 10 other&amp;nbsp;users.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Privacy risk:&lt;/strong&gt; The provider can snapshot your disk, monitor traffic, or comply with legal requests. You do not own the&amp;nbsp;hardware.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bandwidth caps:&lt;/strong&gt; Cheap &lt;span class="caps"&gt;VPS&lt;/span&gt; plans often have 1–2 &lt;span class="caps"&gt;TB&lt;/span&gt;/month transfer limits. Exceeding them incurs&amp;nbsp;fees.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No custom hardware:&lt;/strong&gt; You cannot add a &lt;span class="caps"&gt;GPU&lt;/span&gt;, a 10GbE &lt;span class="caps"&gt;NIC&lt;/span&gt;, or a &lt;span class="caps"&gt;ZFS&lt;/span&gt;&amp;nbsp;array.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Users who need a public-facing server with a static &lt;span class="caps"&gt;IP&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;Hosting websites, mail servers, or VPNs that need 24/7 uptime and DDoS&amp;nbsp;protection.&lt;/li&gt;
&lt;li&gt;Short-term projects or testing where you do not want to buy&amp;nbsp;hardware.&lt;/li&gt;
&lt;li&gt;Users in regions with unreliable power or&amp;nbsp;internet.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Budget:&lt;/strong&gt; $5–8/month (1 vCPU, 1 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, 25 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt;) — Hetzner &lt;span class="caps"&gt;CX11&lt;/span&gt;, Vultr &lt;span class="caps"&gt;HF&lt;/span&gt;, DigitalOcean&amp;nbsp;Droplet.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mid-range:&lt;/strong&gt; $20–40/month (2–4 vCPU, 4–8 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, 80–160 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt;) — Linode, &lt;span class="caps"&gt;OVH&lt;/span&gt;, Hetzner &lt;span class="caps"&gt;CPX21&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;High-end:&lt;/strong&gt; $80–200/month (8+ vCPU, 32 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, dedicated &lt;span class="caps"&gt;CPU&lt;/span&gt;) — &lt;span class="caps"&gt;AWS&lt;/span&gt; &lt;span class="caps"&gt;EC2&lt;/span&gt;, Azure, Google&amp;nbsp;Cloud.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Option B: Homelab&amp;nbsp;Server&lt;/h2&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;One-time cost:&lt;/strong&gt; A $300 mini &lt;span class="caps"&gt;PC&lt;/span&gt; or used rack server runs for 5–7 years. No monthly&amp;nbsp;bill.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Total control:&lt;/strong&gt; You own the hardware, the disks, and the network. No provider terms of service restricting crypto nodes, Tor, or game&amp;nbsp;servers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No bandwidth limits:&lt;/strong&gt; Use your home &lt;span class="caps"&gt;ISP&lt;/span&gt;&amp;#8217;s data cap (usually 1– &lt;span class="caps"&gt;TB&lt;/span&gt; or unlimited). No provider&amp;nbsp;throttling.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Custom hardware:&lt;/strong&gt; Add GPUs for transcoding, 10GbE NICs for fast storage, or 20 &lt;span class="caps"&gt;TB&lt;/span&gt; of hard drives for a &lt;span class="caps"&gt;NAS&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Privacy:&lt;/strong&gt; Your data never leaves your home. No third-party has root&amp;nbsp;access.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Learning:&lt;/strong&gt; You learn real sysadmin skills (&lt;span class="caps"&gt;BIOS&lt;/span&gt;, &lt;span class="caps"&gt;RAID&lt;/span&gt;, networking, &lt;span class="caps"&gt;UPS&lt;/span&gt;, power&amp;nbsp;management).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dynamic &lt;span class="caps"&gt;IP&lt;/span&gt;:&lt;/strong&gt; Most residential ISPs rotate IPs. You need &lt;span class="caps"&gt;DDNS&lt;/span&gt; (e.g., DuckDNS, Cloudflare) or a reverse proxy &lt;span class="caps"&gt;VPS&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;ISP&lt;/span&gt; restrictions:&lt;/strong&gt; Some ISPs block port 80/443, forbid servers in the ToS, or use &lt;span class="caps"&gt;CGNAT&lt;/span&gt; (no inbound connections at&amp;nbsp;all).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Power and cooling:&lt;/strong&gt; A rack server uses 100–300W and generates heat. A mini &lt;span class="caps"&gt;PC&lt;/span&gt; is better&amp;nbsp;(10–40W).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hardware failure:&lt;/strong&gt; If a disk dies, you replace it. No provider &lt;span class="caps"&gt;SLA&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Initial complexity:&lt;/strong&gt; You must set up the network, firewall, and backups&amp;nbsp;yourself.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Users who want to learn Linux, virtualization, and networking&amp;nbsp;hands-on.&lt;/li&gt;
&lt;li&gt;Media servers (Plex, Jellyfin) that need large local storage and hardware&amp;nbsp;transcoding.&lt;/li&gt;
&lt;li&gt;Privacy advocates who want total data&amp;nbsp;sovereignty.&lt;/li&gt;
&lt;li&gt;Users with a stable home internet connection and a spare room or&amp;nbsp;closet.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mini &lt;span class="caps"&gt;PC&lt;/span&gt;:&lt;/strong&gt; $150–400 (Beelink, Minisforum, Intel &lt;span class="caps"&gt;NUC&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Used rack server:&lt;/strong&gt; $200–600 (Dell R720, &lt;span class="caps"&gt;HP&lt;/span&gt;&amp;nbsp;DL380p)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Electricity:&lt;/strong&gt; $3–25/month depending on hardware and local&amp;nbsp;rates&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Option C: The Hybrid&amp;nbsp;Approach&lt;/h2&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Many advanced homelabbers use both: a &lt;strong&gt;homelab server&lt;/strong&gt; for local storage and media, and a &lt;strong&gt;cheap &lt;span class="caps"&gt;VPS&lt;/span&gt;&lt;/strong&gt; for public ingress (reverse proxy, mail, &lt;span class="caps"&gt;VPN&lt;/span&gt;).&lt;/li&gt;
&lt;li&gt;You can use a &lt;span class="caps"&gt;VPS&lt;/span&gt; as a WireGuard &amp;#8220;bounce&amp;#8221; node to tunnel into your home network, bypassing &lt;span class="caps"&gt;CGNAT&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;This gives you the best of both worlds: local performance and global&amp;nbsp;reach.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Two systems to manage and&amp;nbsp;patch.&lt;/li&gt;
&lt;li&gt;Two sets of backup&amp;nbsp;strategies.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Users who want public services but also local, high-performance&amp;nbsp;storage.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt;: $3–5/month (for reverse proxy /&amp;nbsp;tunnel)&lt;/li&gt;
&lt;li&gt;Homelab server: $300 upfront + $5/month&amp;nbsp;electricity&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Comparison&amp;nbsp;Matrix&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Homelab Server&lt;/th&gt;
&lt;th&gt;Winner&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Public website / blog&lt;/td&gt;
&lt;td&gt;✅ Static &lt;span class="caps"&gt;IP&lt;/span&gt;, fast uplink&lt;/td&gt;
&lt;td&gt;❌ Dynamic &lt;span class="caps"&gt;IP&lt;/span&gt;, &lt;span class="caps"&gt;ISP&lt;/span&gt; blocks&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Plex / Jellyfin (4K)&lt;/td&gt;
&lt;td&gt;❌ Storage too expensive&lt;/td&gt;
&lt;td&gt;✅ Local storage + &lt;span class="caps"&gt;GPU&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Homelab&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nextcloud (personal files)&lt;/td&gt;
&lt;td&gt;❌ Bandwidth caps&lt;/td&gt;
&lt;td&gt;✅ Unlimited, private&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Homelab&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mail server&lt;/td&gt;
&lt;td&gt;✅ Static &lt;span class="caps"&gt;IP&lt;/span&gt;, no blacklist&lt;/td&gt;
&lt;td&gt;❌ Dynamic &lt;span class="caps"&gt;IP&lt;/span&gt; blacklisted&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Learning Linux / DevOps&lt;/td&gt;
&lt;td&gt;❌ Abstracted hardware&lt;/td&gt;
&lt;td&gt;✅ Full stack experience&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Homelab&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DDoS protection needed&lt;/td&gt;
&lt;td&gt;✅ Built-in&lt;/td&gt;
&lt;td&gt;❌ None&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;GPU&lt;/span&gt; transcoding / &lt;span class="caps"&gt;AI&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;❌ Expensive or unavailable&lt;/td&gt;
&lt;td&gt;✅ Add any &lt;span class="caps"&gt;GPU&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Homelab&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Running Tor / crypto node&lt;/td&gt;
&lt;td&gt;❌ ToS violation&lt;/td&gt;
&lt;td&gt;✅ No restrictions&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Homelab&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Which Should You&amp;nbsp;Choose?&lt;/h2&gt;
&lt;h3&gt;Scenario 1: &amp;#8220;I want to host a blog and a mail&amp;nbsp;server.&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose a &lt;span class="caps"&gt;VPS&lt;/span&gt;.&lt;/strong&gt; You need a static &lt;span class="caps"&gt;IP&lt;/span&gt; and clean reputation for email deliverability. A $5–10/month &lt;span class="caps"&gt;VPS&lt;/span&gt; from Hetzner or Vultr is&amp;nbsp;perfect.&lt;/p&gt;
&lt;h3&gt;Scenario 2: &amp;#8220;I want a media server and personal &lt;span class="caps"&gt;NAS&lt;/span&gt;.&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose a homelab server.&lt;/strong&gt; A mini &lt;span class="caps"&gt;PC&lt;/span&gt; or old desktop with a 4 &lt;span class="caps"&gt;TB&lt;/span&gt; drive can run Jellyfin, Sonarr, and Samba. No bandwidth limits, no monthly storage&amp;nbsp;fees.&lt;/p&gt;
&lt;h3&gt;Scenario 3: &amp;#8220;I have &lt;span class="caps"&gt;CGNAT&lt;/span&gt; and no static &lt;span class="caps"&gt;IP&lt;/span&gt;, but I want public&amp;nbsp;access.&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose the hybrid approach.&lt;/strong&gt; Buy a cheap &lt;span class="caps"&gt;VPS&lt;/span&gt; ($3/month) and run a WireGuard tunnel. Point your domain to the &lt;span class="caps"&gt;VPS&lt;/span&gt;. The &lt;span class="caps"&gt;VPS&lt;/span&gt; forwards traffic through the tunnel to your homelab. You get public access without changing your &lt;span class="caps"&gt;ISP&lt;/span&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Migration Path: &lt;span class="caps"&gt;VPS&lt;/span&gt; to&amp;nbsp;Homelab&lt;/h2&gt;
&lt;h3&gt;Step 1: Export &lt;span class="caps"&gt;VPS&lt;/span&gt;&amp;nbsp;Data&lt;/h3&gt;
&lt;p&gt;On your &lt;span class="caps"&gt;VPS&lt;/span&gt;, backup your data to a portable&amp;nbsp;format:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Example: export a Nextcloud database and files&lt;/span&gt;
mysqldump&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;nextcloud&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;nextcloud.sql
tar&lt;span class="w"&gt; &lt;/span&gt;czvf&lt;span class="w"&gt; &lt;/span&gt;nextcloud-data.tar.gz&lt;span class="w"&gt; &lt;/span&gt;/var/www/nextcloud/data
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Download the backups via &lt;span class="caps"&gt;SCP&lt;/span&gt; or&amp;nbsp;rsync:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;scp&lt;span class="w"&gt; &lt;/span&gt;user@vps-ip:/home/user/nextcloud-*&lt;span class="w"&gt; &lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Step 2: Set Up Homelab&amp;nbsp;Hardware&lt;/h3&gt;
&lt;p&gt;Install Proxmox or Ubuntu Server on your local machine. Create a &lt;span class="caps"&gt;VM&lt;/span&gt; or &lt;span class="caps"&gt;LXC&lt;/span&gt; container for the&amp;nbsp;app.&lt;/p&gt;
&lt;h3&gt;Step 3: Restore&amp;nbsp;Data&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# On the homelab server&lt;/span&gt;
mysql&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="w"&gt; &lt;/span&gt;root&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;nextcloud&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;&lt;span class="w"&gt; &lt;/span&gt;nextcloud.sql
tar&lt;span class="w"&gt; &lt;/span&gt;xzvf&lt;span class="w"&gt; &lt;/span&gt;nextcloud-data.tar.gz&lt;span class="w"&gt; &lt;/span&gt;-C&lt;span class="w"&gt; &lt;/span&gt;/var/www/nextcloud/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Step 4: Update &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Point your domain&amp;#8217;s A record from the &lt;span class="caps"&gt;VPS&lt;/span&gt; &lt;span class="caps"&gt;IP&lt;/span&gt; to your home &lt;span class="caps"&gt;IP&lt;/span&gt; (or the &lt;span class="caps"&gt;VPS&lt;/span&gt; tunnel &lt;span class="caps"&gt;IP&lt;/span&gt; if using the hybrid&amp;nbsp;model).&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The&amp;nbsp;Verdict&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Verdict&lt;/th&gt;
&lt;th&gt;Recommendation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for beginners&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt; (no hardware, instant setup)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for learning&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Homelab server (hands-on, full stack)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for media / storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Homelab server (cheap storage, no caps)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for public services&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt; (static &lt;span class="caps"&gt;IP&lt;/span&gt;, DDoS protection)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best overall value&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hybrid (&lt;span class="caps"&gt;VPS&lt;/span&gt; + homelab)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;A &lt;span class="caps"&gt;VPS&lt;/span&gt; is rented convenience. A homelab server is owned power. If you want to host a public website or need a static &lt;span class="caps"&gt;IP&lt;/span&gt;, start with a &lt;span class="caps"&gt;VPS&lt;/span&gt;. If you want to learn, store files, or run media locally, build a homelab. The hybrid approach—a cheap &lt;span class="caps"&gt;VPS&lt;/span&gt; for ingress and a homelab for storage—is the sweet spot for advanced&amp;nbsp;users.&lt;/p&gt;
&lt;h3&gt;Ready to Get&amp;nbsp;Started?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;[internal_link] Building a homelab? Read our &lt;a href="https://steadypub.com/2026/06/homelab-server-hardware-2026/"&gt;homelab server hardware guide&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;[internal_link] Choosing a &lt;span class="caps"&gt;VPS&lt;/span&gt;? See our &lt;a href="https://steadypub.com/2026/06/best-europe-vps-homelab/"&gt;best Europe &lt;span class="caps"&gt;VPS&lt;/span&gt; for homelab&lt;/a&gt;&amp;nbsp;guide.&lt;/li&gt;
&lt;li&gt;[internal_link] Want the hybrid setup? Learn &lt;a href="https://steadypub.com/2026/06/homelab-networking-basics/"&gt;WireGuard &lt;span class="caps"&gt;VPN&lt;/span&gt; configuration&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt; providers&lt;/strong&gt;: Hetzner, Vultr, Linode, DigitalOcean referral&amp;nbsp;links&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Homelab hardware&lt;/strong&gt;: Beelink, Dell, Minisforum affiliate&amp;nbsp;links&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;DDNS&lt;/span&gt; services&lt;/strong&gt;: DuckDNS, Cloudflare (free&amp;nbsp;tier)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;intro-dilemma&lt;/code&gt; → &lt;code&gt;best-europe-vps-homelab&lt;/code&gt; — &amp;#8220;our &lt;span class="caps"&gt;VPS&lt;/span&gt; comparison&amp;nbsp;guide&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;migration-path&lt;/code&gt; → &lt;code&gt;homelab-server-hardware-2026&lt;/code&gt; — &amp;#8220;choose your homelab&amp;nbsp;hardware&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;proxmox-beginner-guide-2026&lt;/code&gt; — &amp;#8220;install Proxmox on your new&amp;nbsp;server&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] Are you running a &lt;span class="caps"&gt;VPS&lt;/span&gt;, a homelab, or both? Share your setup and monthly&amp;nbsp;costs!&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for &lt;span class="caps"&gt;VPS&lt;/span&gt; deal alerts, hardware reviews, and hybrid networking&amp;nbsp;guides.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Comparisons"/><category term="vps"/><category term="homelab server"/><category term="self-hosted"/><category term="comparison"/><category term="cloud"/><category term="dedicated"/></entry><entry><title>Wazuh Docker Compose Setup: Self-Hosted SIEM for Homelab Security</title><link href="https://steadypub.com/2026/06/wazuh-docker-compose/" rel="alternate"/><published>2026-06-05T00:00:00+07:00</published><updated>2026-06-05T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-05:/2026/06/wazuh-docker-compose/</id><summary type="html">&lt;p&gt;Deploy Wazuh &lt;span class="caps"&gt;XDR&lt;/span&gt;/&lt;span class="caps"&gt;SIEM&lt;/span&gt; with Docker Compose for homelab security monitoring. Collect logs, detect threats, and visualize alerts with the Wazuh&amp;nbsp;Dashboard.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~14 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelabbers wanting enterprise-grade security&amp;nbsp;monitoring&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is&amp;nbsp;Wazuh?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Wazuh is a free, open-source security platform that unifies &lt;span class="caps"&gt;SIEM&lt;/span&gt; (Security Information and Event Management) and &lt;span class="caps"&gt;XDR&lt;/span&gt; (Extended Detection and Response) capabilities. It protects endpoints, cloud workloads, and containers by collecting security events, analyzing them for threats, and alerting you to suspicious&amp;nbsp;activity.&lt;/p&gt;
&lt;h3&gt;Key&amp;nbsp;Benefits&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Benefit&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Log analysis&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Collect and parse logs from Linux, Windows, macOS, and containers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Intrusion detection&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;File integrity monitoring (&lt;span class="caps"&gt;FIM&lt;/span&gt;) and rootkit detection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Vulnerability detection&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt; scanning for installed packages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Configuration assessment&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;CIS&lt;/span&gt; benchmark compliance checks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Malware detection&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;YARA&lt;/span&gt; integration and threat intelligence feeds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cloud security&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Monitor &lt;span class="caps"&gt;AWS&lt;/span&gt;, Azure, and &lt;span class="caps"&gt;GCP&lt;/span&gt; environments&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Container security&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Docker and Kubernetes monitoring&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Alerting&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Email, Slack, webhook, and syslog notifications&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dashboard&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Built-in OpenSearch Dashboards for visualization&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;h3&gt;Hardware&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Host with &lt;span class="caps"&gt;4GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; minimum (&lt;span class="caps"&gt;8GB&lt;/span&gt; recommended for small&amp;nbsp;homelabs)&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;50GB&lt;/span&gt; storage for Wazuh Indexer (grows with log&amp;nbsp;volume)&lt;/li&gt;
&lt;li&gt;2 &lt;span class="caps"&gt;CPU&lt;/span&gt; cores&amp;nbsp;minimum&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Software&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Docker Engine 24.x+ and Docker Compose&amp;nbsp;v2+&lt;/li&gt;
&lt;li&gt;Linux host (Debian 12, Ubuntu 22.04/24.04, or Proxmox &lt;span class="caps"&gt;LXC&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;vm.max_map_count&lt;/code&gt; ≥ 262144 (required for Wazuh&amp;nbsp;Indexer)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Knowledge&amp;nbsp;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Docker Compose&amp;nbsp;basics&lt;/li&gt;
&lt;li&gt;Linux command&amp;nbsp;line&lt;/li&gt;
&lt;li&gt;Basic networking and security&amp;nbsp;concepts&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Prepare the&amp;nbsp;Host&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Set required kernel parameters and create the Wazuh project&amp;nbsp;directory.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Increase &lt;code&gt;vm.max_map_count&lt;/code&gt; (required for&amp;nbsp;OpenSearch):&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Temporary (until reboot)&lt;/span&gt;
sysctl&lt;span class="w"&gt; &lt;/span&gt;-w&lt;span class="w"&gt; &lt;/span&gt;vm.max_map_count&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;262144&lt;/span&gt;

&lt;span class="c1"&gt;# Permanent&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;vm.max_map_count=262144&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/sysctl.conf
sysctl&lt;span class="w"&gt; &lt;/span&gt;-p
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Verify:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sysctl&lt;span class="w"&gt; &lt;/span&gt;vm.max_map_count
&lt;span class="c1"&gt;# Output: vm.max_map_count = 262144&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Create the project&amp;nbsp;directory:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;~/docker/wazuh&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/docker/wazuh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 2: Deploy Wazuh with Docker&amp;nbsp;Compose&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Run the full Wazuh stack: Manager, Indexer, Dashboard, and Agent&amp;nbsp;enrollment.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Create &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;wazuh.manager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh/wazuh-manager:4.9.0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh-manager&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh.manager&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1514:1514&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1515:1515&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;514:514/udp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;55000:55000&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh-api-data:/var/ossec/api/configuration&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh-var:/var/ossec/var&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh-etc:/var/ossec/etc&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh-logs:/var/ossec/logs&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh-queue:/var/ossec/queue&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;wazuh.indexer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh/wazuh-indexer:4.9.0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh-indexer&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh.indexer&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;9200:9200&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;OPENSEARCH_JAVA_OPTS=-Xms1g&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-Xmx1g&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;bootstrap.memory_lock=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ulimits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;memlock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;soft&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;-1&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;hard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;-1&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;nofile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;soft&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;65536&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;hard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;65536&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh-indexer-data:/var/lib/wazuh-indexer&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;wazuh.dashboard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh/wazuh-dashboard:4.9.0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh-dashboard&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh.dashboard&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;5601:5601&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;WAZUH_INDEXER_URL=https://wazuh.indexer:9200&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;WAZUH_API_URL=https://wazuh.manager:55000&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh-dashboard-data:/data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh.indexer&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;wazuh-api-data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;wazuh-var&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;wazuh-etc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;wazuh-logs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;wazuh-queue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;wazuh-indexer-data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;wazuh-dashboard-data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;wazuh&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;bridge&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Deploy:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Wait 2–3 minutes&lt;/strong&gt; for services to&amp;nbsp;initialize.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Generate enrollment&amp;nbsp;credentials:&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;wazuh-manager&lt;span class="w"&gt; &lt;/span&gt;/var/ossec/bin/wazuh-apid&lt;span class="w"&gt; &lt;/span&gt;-f
&lt;span class="c1"&gt;# Default dashboard login: admin / admin&lt;/span&gt;
&lt;span class="c1"&gt;# Change password after first login&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Access Wazuh&amp;nbsp;Dashboard:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;URL&lt;/span&gt;: &lt;code&gt;https://your-server-ip:5601&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Default&amp;nbsp;credentials: &lt;code&gt;admin&lt;/code&gt; / &lt;code&gt;admin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Change the password immediately&lt;/strong&gt; after first&amp;nbsp;login&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Step 3: Install Wazuh Agent on&amp;nbsp;Endpoints&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Collect security events from your homelab servers, VMs, and&amp;nbsp;containers.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Linux Agent&amp;nbsp;Installation:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Download and install the agent&lt;/span&gt;
curl&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;https://packages.wazuh.com/key/GPG-KEY-WAZUH&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;gpg&lt;span class="w"&gt; &lt;/span&gt;--no-default-keyring&lt;span class="w"&gt; &lt;/span&gt;--keyring&lt;span class="w"&gt; &lt;/span&gt;gnupg-ring:/usr/share/keyrings/wazuh.gpg&lt;span class="w"&gt; &lt;/span&gt;--import&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;chmod&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;644&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/usr/share/keyrings/wazuh.gpg
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;deb [signed-by=/usr/share/keyrings/wazuh.gpg] https://packages.wazuh.com/4.x/apt/ stable main&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;tee&lt;span class="w"&gt; &lt;/span&gt;/etc/apt/sources.list.d/wazuh.list
apt&lt;span class="w"&gt; &lt;/span&gt;update
apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;wazuh-agent

&lt;span class="c1"&gt;# Register the agent with the manager&lt;/span&gt;
/var/ossec/bin/agent-auth&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;wazuh.manager&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1515&lt;/span&gt;

&lt;span class="c1"&gt;# Set the manager address&lt;/span&gt;
sed&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;s/&amp;lt;ADDRESS&amp;gt;YOUR_MANAGER_IP&amp;lt;/&amp;lt;ADDRESS&amp;gt;wazuh.manager&amp;lt;/&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/ossec/etc/ossec.conf

&lt;span class="c1"&gt;# Start the agent&lt;/span&gt;
systemctl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;wazuh-agent
systemctl&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;wazuh-agent
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Windows Agent Installation:&lt;/strong&gt;
1. Download the &lt;span class="caps"&gt;MSI&lt;/span&gt;&amp;nbsp;from &lt;code&gt;https://packages.wazuh.com/4.x/windows/wazuh-agent-4.9.0-1.msi&lt;/code&gt;
2. Install&amp;nbsp;with: &lt;code&gt;msiexec /i wazuh-agent-4.9.0-1.msi /q WAZUH_MANAGER="wazuh.manager"&lt;/code&gt;
3. Start the&amp;nbsp;service: &lt;code&gt;NET START WazuhSvc&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Docker Agent (Container&amp;nbsp;Monitoring):&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;wazuh-agent&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--network&lt;span class="w"&gt; &lt;/span&gt;wazuh&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;/var/run/docker.sock:/var/run/docker.sock&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;/:/host:ro&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;wazuh/wazuh-agent:4.9.0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 4: Enable Key Security&amp;nbsp;Features&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Configure &lt;span class="caps"&gt;FIM&lt;/span&gt;, vulnerability detection, and &lt;span class="caps"&gt;CIS&lt;/span&gt;&amp;nbsp;benchmarks.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;File Integrity Monitoring (&lt;span class="caps"&gt;FIM&lt;/span&gt;):&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Go to &lt;strong&gt;Management → Configuration&lt;/strong&gt; (edit agent or&amp;nbsp;manager)&lt;/li&gt;
&lt;li&gt;Under &lt;code&gt;syscheck&lt;/code&gt;, add directories to&amp;nbsp;monitor:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;syscheck&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;directories&amp;gt;&lt;/span&gt;/etc,/usr/bin,/usr/sbin&lt;span class="nt"&gt;&amp;lt;/directories&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;directories&amp;gt;&lt;/span&gt;/bin,/sbin,/boot&lt;span class="nt"&gt;&amp;lt;/directories&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;directories&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;check_all=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;yes&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;/home,/root&lt;span class="nt"&gt;&amp;lt;/directories&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/syscheck&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Vulnerability&amp;nbsp;Detection:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;In Wazuh Manager configuration,&amp;nbsp;enable:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;vulnerability-detection&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;enabled&amp;gt;&lt;/span&gt;yes&lt;span class="nt"&gt;&amp;lt;/enabled&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;index-status&amp;gt;&lt;/span&gt;yes&lt;span class="nt"&gt;&amp;lt;/index-status&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;feed-update-interval&amp;gt;&lt;/span&gt;60m&lt;span class="nt"&gt;&amp;lt;/feed-update-interval&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/vulnerability-detection&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Configuration Assessment (&lt;span class="caps"&gt;CIS&lt;/span&gt;&amp;nbsp;Benchmarks):&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Enabled by default. View results in &lt;strong&gt;Security Events → Configuration&amp;nbsp;Assessment&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Check compliance scores for Ubuntu, Debian, CentOS, or&amp;nbsp;Windows&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Use a Reverse Proxy for &lt;span class="caps"&gt;HTTPS&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Expose Wazuh Dashboard through &lt;span class="caps"&gt;NGINX&lt;/span&gt; Proxy Manager with a valid &lt;span class="caps"&gt;SSL&lt;/span&gt;&amp;nbsp;certificate:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;https://wazuh.yourdomain.com → http://wazuh-dashboard:5601
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 2: Backup Wazuh&amp;nbsp;Data&lt;/h3&gt;
&lt;p&gt;Back up the named volumes&amp;nbsp;regularly:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/docker/wazuh
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;stop
tar&lt;span class="w"&gt; &lt;/span&gt;czvf&lt;span class="w"&gt; &lt;/span&gt;wazuh-backup-&lt;span class="k"&gt;$(&lt;/span&gt;date&lt;span class="w"&gt; &lt;/span&gt;+%F&lt;span class="k"&gt;)&lt;/span&gt;.tar.gz&lt;span class="w"&gt; &lt;/span&gt;/var/lib/docker/volumes/wazuh-*
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 3: Reduce Resource Usage for Small&amp;nbsp;Homelabs&lt;/h3&gt;
&lt;p&gt;If running on a mini &lt;span class="caps"&gt;PC&lt;/span&gt; with &lt;span class="caps"&gt;8GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, reduce Indexer&amp;nbsp;memory:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;OPENSEARCH_JAVA_OPTS=-Xms512m&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-Xmx512m&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 4: Integrate with TheHive or&amp;nbsp;Shuffle&lt;/h3&gt;
&lt;p&gt;Send Wazuh alerts to TheHive (case management) or Shuffle (&lt;span class="caps"&gt;SOAR&lt;/span&gt; automation) for advanced incident&amp;nbsp;response.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Troubleshooting Common&amp;nbsp;Issues&lt;/h2&gt;
&lt;h3&gt;Problem 1: &amp;#8220;Indexer Fails to Start —&amp;nbsp;vm.max_map_count&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Cause:&lt;/strong&gt; Kernel parameter not set&amp;nbsp;correctly.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sysctl&lt;span class="w"&gt; &lt;/span&gt;-w&lt;span class="w"&gt; &lt;/span&gt;vm.max_map_count&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;262144&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;vm.max_map_count=262144&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/sysctl.conf
&lt;span class="c1"&gt;# Restart the container&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;restart&lt;span class="w"&gt; &lt;/span&gt;wazuh.indexer
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Problem 2: &amp;#8220;Agent Not Appearing in&amp;nbsp;Dashboard&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Cause:&lt;/strong&gt; Agent registration failed, or firewall blocking port&amp;nbsp;1514/1515.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Check agent registration on manager&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;wazuh-manager&lt;span class="w"&gt; &lt;/span&gt;/var/ossec/bin/agent_control&lt;span class="w"&gt; &lt;/span&gt;-l

&lt;span class="c1"&gt;# Check agent logs on the endpoint&lt;/span&gt;
tail&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;/var/ossec/logs/ossec.log
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Problem 3: &amp;#8220;Dashboard Shows No&amp;nbsp;Alerts&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Cause:&lt;/strong&gt; Rules not loaded, or no agents&amp;nbsp;reporting.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;
- Verify agents are active in &lt;strong&gt;Management → Agents&lt;/strong&gt;
- Check that the manager is receiving&amp;nbsp;events: &lt;code&gt;docker logs wazuh-manager&lt;/code&gt;
- Restart&amp;nbsp;manager: &lt;code&gt;docker compose restart wazuh-manager&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Wazuh is the most powerful free security platform for homelabs. With Docker Compose, you can deploy a full &lt;span class="caps"&gt;SIEM&lt;/span&gt;/&lt;span class="caps"&gt;XDR&lt;/span&gt; stack in minutes. Monitor file integrity, detect vulnerabilities, assess &lt;span class="caps"&gt;CIS&lt;/span&gt; compliance, and respond to threats — all from a single&amp;nbsp;dashboard.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Install agents on all your homelab servers and&amp;nbsp;VMs&lt;/li&gt;
&lt;li&gt;Configure &lt;a href="grafana-docker-compose"&gt;Grafana&lt;/a&gt; for custom security&amp;nbsp;dashboards&lt;/li&gt;
&lt;li&gt;Compare Wazuh with &lt;a href="wazuh-vs-splunk"&gt;Splunk&lt;/a&gt; for enterprise&amp;nbsp;context&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Beelink Mini S12 Pro&lt;/strong&gt;: Mini &lt;span class="caps"&gt;PC&lt;/span&gt; for running Wazuh + other&amp;nbsp;services&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Samsung 990 &lt;span class="caps"&gt;EVO&lt;/span&gt;&lt;/strong&gt;: NVMe &lt;span class="caps"&gt;SSD&lt;/span&gt; for fast indexer&amp;nbsp;performance&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;intro&lt;/code&gt; → &lt;code&gt;wazuh-vs-splunk&lt;/code&gt; for &lt;span class="caps"&gt;SIEM&lt;/span&gt;&amp;nbsp;comparison&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tip-4&lt;/code&gt; → &lt;code&gt;grafana-docker-compose&lt;/code&gt; for dashboard&amp;nbsp;visualization&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → &lt;code&gt;homelab-security-monitoring&lt;/code&gt; for security monitoring&amp;nbsp;overview&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] Are you running Wazuh in your homelab? Share your alert rules and agent&amp;nbsp;count!&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for weekly homelab security and &lt;span class="caps"&gt;SIEM&lt;/span&gt; setup&amp;nbsp;guides.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Tutorials"/><category term="wazuh"/><category term="docker compose"/><category term="siem"/><category term="security"/><category term="homelab"/><category term="xdr"/><category term="monitoring"/></entry><entry><title>AdGuard Home Docker Setup: Network-Wide Ad Blocking for Your Homelab</title><link href="https://steadypub.com/2026/06/adguard-home-docker/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T10:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/adguard-home-docker/</id><summary type="html">&lt;p&gt;Deploy AdGuard Home via Docker for network-wide ad blocking, parental controls, and &lt;span class="caps"&gt;DNS&lt;/span&gt; privacy. Covers Compose setup, upstream &lt;span class="caps"&gt;DNS&lt;/span&gt;, and Pi-hole&amp;nbsp;migration.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~14 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab and self-hosting&amp;nbsp;enthusiasts&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is AdGuard&amp;nbsp;Home?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;AdGuard Home is a network-wide ad and tracker blocking &lt;span class="caps"&gt;DNS&lt;/span&gt; server. Like Pi-hole, it acts as a &lt;span class="caps"&gt;DNS&lt;/span&gt; sinkhole, but it offers a modern web interface, built-in &lt;span class="caps"&gt;DNS&lt;/span&gt;-over-&lt;span class="caps"&gt;HTTPS&lt;/span&gt; (DoH) and &lt;span class="caps"&gt;DNS&lt;/span&gt;-over-&lt;span class="caps"&gt;TLS&lt;/span&gt; (DoT) support, and parental controls out of the box. It is written in Go, lightweight, and actively maintained by the AdGuard&amp;nbsp;team.&lt;/p&gt;
&lt;h3&gt;A Brief&amp;nbsp;History&lt;/h3&gt;
&lt;p&gt;AdGuard Home was released in 2019 as an open-source alternative to Pi-hole and AdGuard&amp;#8217;s own commercial &lt;span class="caps"&gt;DNS&lt;/span&gt;. It gained popularity for its polished &lt;span class="caps"&gt;UI&lt;/span&gt;, native &lt;span class="caps"&gt;HTTPS&lt;/span&gt; support, and aggressive filtering engine. By 2026, it has become the default recommendation for users who want a modern &lt;span class="caps"&gt;DNS&lt;/span&gt; sinkhole without the plugin ecosystem of&amp;nbsp;Pi-hole.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why Use AdGuard Home in Your&amp;nbsp;Homelab?&lt;/h2&gt;
&lt;h3&gt;Modern &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;Privacy&lt;/h3&gt;
&lt;p&gt;AdGuard Home supports DoH, DoT, and &lt;span class="caps"&gt;DNS&lt;/span&gt;-over-&lt;span class="caps"&gt;QUIC&lt;/span&gt; natively. This encrypts &lt;span class="caps"&gt;DNS&lt;/span&gt; queries between your network and the upstream resolver, preventing ISPs and middlemen from snooping on your browsing&amp;nbsp;history.&lt;/p&gt;
&lt;h3&gt;Built-in Parental&amp;nbsp;Controls&lt;/h3&gt;
&lt;p&gt;Block adult websites, enforce safe search, and set time limits per client. This is useful for family networks and guest Wi-Fi without requiring client-side&amp;nbsp;software.&lt;/p&gt;
&lt;h3&gt;Fast, Lightweight&amp;nbsp;Engine&lt;/h3&gt;
&lt;p&gt;AdGuard Home&amp;#8217;s filtering engine is written in Go and is faster than Pi-hole&amp;#8217;s &lt;span class="caps"&gt;FTL&lt;/span&gt; for large blocklists. It handles millions of queries per day on a Raspberry Pi without&amp;nbsp;strain.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;h3&gt;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Linux server or Raspberry Pi with&amp;nbsp;Docker&lt;/li&gt;
&lt;li&gt;Port 53 (&lt;span class="caps"&gt;TCP&lt;/span&gt;/&lt;span class="caps"&gt;UDP&lt;/span&gt;) and 3000 (web &lt;span class="caps"&gt;UI&lt;/span&gt;)&amp;nbsp;available&lt;/li&gt;
&lt;li&gt;A static &lt;span class="caps"&gt;IP&lt;/span&gt; or &lt;span class="caps"&gt;DHCP&lt;/span&gt; reservation for the AdGuard&amp;nbsp;host&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Method 1: Docker&amp;nbsp;Compose&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;adguardhome&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;adguard/adguardhome:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;adguardhome&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;53:53/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;53:53/udp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;80:80/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;443:443/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3000:3000/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;853:853/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./workdir:/opt/adguardhome/work&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./confdir:/opt/adguardhome/conf&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;cap_add&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;NET_ADMIN&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Deploy:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Complete the setup wizard&amp;nbsp;at &lt;code&gt;http://your-server:3000&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Method 2: Docker&amp;nbsp;Run&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;adguardhome&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--restart&lt;span class="o"&gt;=&lt;/span&gt;always&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;53&lt;/span&gt;:53/tcp&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;53&lt;/span&gt;:53/udp&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;:80/tcp&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;443&lt;/span&gt;:443/tcp&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3000&lt;/span&gt;:3000/tcp&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;853&lt;/span&gt;:853/tcp&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;/workdir:/opt/adguardhome/work&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;/confdir:/opt/adguardhome/conf&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--cap-add&lt;span class="o"&gt;=&lt;/span&gt;NET_ADMIN&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;adguard/adguardhome:latest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Basic Setup and&amp;nbsp;Configuration&lt;/h2&gt;
&lt;h3&gt;Step 1: Configure Upstream &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;In &lt;strong&gt;Settings&lt;/strong&gt; → &lt;strong&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt; settings&lt;/strong&gt;, choose encrypted&amp;nbsp;upstreams:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;https://dns.cloudflare.com/dns-query&lt;/code&gt; (Cloudflare&amp;nbsp;DoH)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tls://dns.quad9.net&lt;/code&gt; (Quad9&amp;nbsp;DoT)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;https://dns.adguard-dns.com/dns-query&lt;/code&gt; (AdGuard&amp;nbsp;DoH)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For maximum privacy, run a local Unbound recursive resolver and&amp;nbsp;set &lt;code&gt;127.0.0.1:5335&lt;/code&gt; as the&amp;nbsp;upstream.&lt;/p&gt;
&lt;h3&gt;Step 2: Add Filter&amp;nbsp;Lists&lt;/h3&gt;
&lt;p&gt;AdGuard Home ships with default lists. Add more in &lt;strong&gt;Filters&lt;/strong&gt; → &lt;strong&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt; blocklists&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;StevenBlack&amp;nbsp;hosts&lt;/li&gt;
&lt;li&gt;AdGuard &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;filter&lt;/li&gt;
&lt;li&gt;MalwareDomainList&lt;/li&gt;
&lt;li&gt;NoCoin filter&amp;nbsp;list&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Step 3: Set Up Client-Specific&amp;nbsp;Rules&lt;/h3&gt;
&lt;p&gt;In &lt;strong&gt;Client settings&lt;/strong&gt;, add devices by &lt;span class="caps"&gt;MAC&lt;/span&gt; or &lt;span class="caps"&gt;IP&lt;/span&gt; and assign custom filtering rules. Block social media for kids, allow all traffic for the home server, and enforce safe search for&amp;nbsp;guests.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Advanced&amp;nbsp;Features&lt;/h2&gt;
&lt;h3&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt; Rebinding&amp;nbsp;Protection&lt;/h3&gt;
&lt;p&gt;AdGuard Home blocks &lt;span class="caps"&gt;DNS&lt;/span&gt; rebinding attacks by default. This prevents malicious websites from resolving private &lt;span class="caps"&gt;IP&lt;/span&gt; ranges&amp;nbsp;(e.g., &lt;code&gt;192.168.x.x&lt;/code&gt;) to attack your router or internal&amp;nbsp;services.&lt;/p&gt;
&lt;h3&gt;&lt;span class="caps"&gt;HTTPS&lt;/span&gt; Encryption for the Web &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;AdGuard Home can generate a Let&amp;#8217;s Encrypt certificate for its web interface. In &lt;strong&gt;Encryption settings&lt;/strong&gt;, enable automatic &lt;span class="caps"&gt;HTTPS&lt;/span&gt; and redirect &lt;span class="caps"&gt;HTTP&lt;/span&gt; to &lt;span class="caps"&gt;HTTPS&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;Statistics and Query&amp;nbsp;Log&lt;/h3&gt;
&lt;p&gt;The dashboard shows query volume, blocked percentage, top queried domains, and top clients. The query log is searchable and exportable. Use this to identify misbehaving IoT devices or tune your&amp;nbsp;blocklists.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Integrating with Your&amp;nbsp;Homelab&lt;/h2&gt;
&lt;h3&gt;Reverse&amp;nbsp;Proxy&lt;/h3&gt;
&lt;p&gt;Place AdGuard Home behind Traefik or Nginx Proxy&amp;nbsp;Manager:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.enable=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.adguard.rule=Host(`dns.yourdomain.com`)&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.adguard.tls.certresolver=letsencrypt&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.services.adguard.loadbalancer.server.port=80&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;&lt;span class="caps"&gt;VPN&lt;/span&gt;&amp;nbsp;Integration&lt;/h3&gt;
&lt;p&gt;Set your &lt;span class="caps"&gt;VPN&lt;/span&gt;&amp;#8217;s &lt;span class="caps"&gt;DNS&lt;/span&gt; to AdGuard Home for ad blocking on mobile devices. In WireGuard,&amp;nbsp;set &lt;code&gt;DNS = 192.168.1.10&lt;/code&gt; in the client&amp;nbsp;config.&lt;/p&gt;
&lt;h3&gt;Migration from&amp;nbsp;Pi-hole&lt;/h3&gt;
&lt;p&gt;AdGuard Home can import Pi-hole blocklists and custom rules. Export your Pi-hole whitelist and blacklist, then import them via &lt;strong&gt;Filters&lt;/strong&gt; → &lt;strong&gt;Custom filtering rules&lt;/strong&gt;. The statistics history will not&amp;nbsp;transfer.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Alternatives to&amp;nbsp;Consider&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;DoH/DoT&lt;/th&gt;
&lt;th&gt;Parental Controls&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;AdGuard Home&lt;/td&gt;
&lt;td&gt;Modern &lt;span class="caps"&gt;DNS&lt;/span&gt; filtering&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Excellent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pi-hole&lt;/td&gt;
&lt;td&gt;Community, plugins&lt;/td&gt;
&lt;td&gt;Via Unbound&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Functional&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Technitium &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Full &lt;span class="caps"&gt;DNS&lt;/span&gt; server&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Advanced&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NextDNS&lt;/td&gt;
&lt;td&gt;Cloud-based, no hardware&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Excellent&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Frequently Asked&amp;nbsp;Questions&lt;/h2&gt;
&lt;h3&gt;Can I run AdGuard Home and Pi-hole&amp;nbsp;together?&lt;/h3&gt;
&lt;p&gt;Not recommended on the same host due to port 53 conflicts. Choose one. If you need both features, use AdGuard Home as the primary and forward specific queries to Pi-hole for custom&amp;nbsp;plugins.&lt;/p&gt;
&lt;h3&gt;Does AdGuard Home block YouTube&amp;nbsp;ads?&lt;/h3&gt;
&lt;p&gt;Partially. &lt;span class="caps"&gt;DNS&lt;/span&gt;-level blocking cannot block all YouTube ads because they are served from the same domains as content. Use a browser extension for complete YouTube ad&amp;nbsp;blocking.&lt;/p&gt;
&lt;h3&gt;How do I update AdGuard&amp;nbsp;Home?&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;pull&lt;span class="w"&gt; &lt;/span&gt;adguard/adguardhome:latest
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;AdGuard Home is the modern successor to Pi-hole for users who want &lt;span class="caps"&gt;DNS&lt;/span&gt; privacy, parental controls, and a polished &lt;span class="caps"&gt;UI&lt;/span&gt; in a single package. With Docker, it deploys in minutes. With DoH/DoT, it protects your queries from &lt;span class="caps"&gt;ISP&lt;/span&gt; surveillance. For new homelabs, AdGuard Home is the recommended default &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;sinkhole.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Deploy AdGuard Home and set it as your router&amp;#8217;s &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Enable DoH or DoT for encrypted upstream&amp;nbsp;queries&lt;/li&gt;
&lt;li&gt;Configure client-specific rules for family&amp;nbsp;devices&lt;/li&gt;
&lt;li&gt;Monitor query statistics and tune&amp;nbsp;blocklists&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;installation&lt;/strong&gt;: hardware — Raspberry Pi kits, mini&amp;nbsp;PCs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;integration&lt;/strong&gt;: tool — &lt;span class="caps"&gt;VPN&lt;/span&gt; services, parental control&amp;nbsp;subscriptions&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;alternatives&lt;/strong&gt;: tool — NextDNS, AdGuard &lt;span class="caps"&gt;VPN&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;installation&lt;/code&gt; → setup_guide: &lt;a href="https://steadypub.com/2026/06/docker-compose-for-beginners/"&gt;Docker Compose for&amp;nbsp;beginners&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;integration&lt;/code&gt; → related_guide: &lt;a href="https://steadypub.com/2026/06/adguard-home-vs-pihole-2026/"&gt;Pi-hole vs AdGuard Home&amp;nbsp;comparison&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;alternatives&lt;/code&gt; → comparison: &lt;a href="https://steadypub.com/2026/06/dns-filtering-homelab/"&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt; filtering in the&amp;nbsp;homelab&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] AdGuard Home or Pi-hole? Which do you prefer and&amp;nbsp;why?&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for weekly homelab networking and privacy&amp;nbsp;guides.&lt;/li&gt;
&lt;li&gt;[internal_link] Next: compare &lt;a href="https://steadypub.com/2026/06/adguard-home-vs-pihole-2026/"&gt;AdGuard Home with&amp;nbsp;Pi-hole&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Networking"/><category term="adguard"/><category term="dns"/><category term="ad blocking"/><category term="docker"/><category term="homelab"/><category term="privacy"/></entry><entry><title>AdGuard Home vs Pi-hole 2026: Which One Wins for Your Homelab?</title><link href="https://steadypub.com/2026/06/adguard-home-vs-pihole-2026/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T06:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/adguard-home-vs-pihole-2026/</id><summary type="html">&lt;p&gt;Head-to-head comparison of AdGuard Home and Pi-hole in 2026. Features, performance, resource use, and real Docker setups for&amp;nbsp;both.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~12 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelabbers choosing a &lt;span class="caps"&gt;DNS&lt;/span&gt; ad&amp;nbsp;blocker&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The AdGuard Home vs Pi-hole&amp;nbsp;Dilemma&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt;-level ad blocking is the most impactful single improvement you can make to your home network. It blocks ads, trackers, and malware domains before any device loads them—phones, smart TVs, IoT devices, and guests all benefit without per-device&amp;nbsp;configuration.&lt;/p&gt;
&lt;p&gt;The two dominant open-source solutions are &lt;strong&gt;Pi-hole&lt;/strong&gt; (the veteran, Linux-first) and &lt;strong&gt;AdGuard Home&lt;/strong&gt; (the modern alternative with a polished &lt;span class="caps"&gt;UI&lt;/span&gt;). Both are free, Docker-friendly, and actively maintained. The right choice depends on your feature priorities and technical comfort&amp;nbsp;level.&lt;/p&gt;
&lt;h3&gt;Key Differences at a&amp;nbsp;Glance&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Pi-hole&lt;/th&gt;
&lt;th&gt;AdGuard Home&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;First release&lt;/td&gt;
&lt;td&gt;2015&lt;/td&gt;
&lt;td&gt;2019&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;UI&lt;/span&gt; polish&lt;/td&gt;
&lt;td&gt;Functional, classic&lt;/td&gt;
&lt;td&gt;Modern, responsive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DoH/DoT upstreams&lt;/td&gt;
&lt;td&gt;Via cloudflared/unbound&lt;/td&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt; rewrites&lt;/td&gt;
&lt;td&gt;Via Local &lt;span class="caps"&gt;DNS&lt;/span&gt; Records&lt;/td&gt;
&lt;td&gt;Built-in, easier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Per-client filtering&lt;/td&gt;
&lt;td&gt;Via groups&lt;/td&gt;
&lt;td&gt;Built-in, simpler&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Parental controls&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Built-in (safe search)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Query log retention&lt;/td&gt;
&lt;td&gt;Configurable&lt;/td&gt;
&lt;td&gt;Configurable, faster search&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Blocklist syntax&lt;/td&gt;
&lt;td&gt;Hosts + adlists + regex&lt;/td&gt;
&lt;td&gt;Hosts + adlists + regex + $important&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Statistics&lt;/td&gt;
&lt;td&gt;Detailed, raw&lt;/td&gt;
&lt;td&gt;Visual, polished&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mobile app&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes (remote management)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Community size&lt;/td&gt;
&lt;td&gt;Massive (r/pihole)&lt;/td&gt;
&lt;td&gt;Large (r/Adguard)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Option A:&amp;nbsp;Pi-hole&lt;/h2&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mature ecosystem:&lt;/strong&gt; 10+ years of community blocklists, documentation, and troubleshooting guides. If you have a problem, someone has solved&amp;nbsp;it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lightweight:&lt;/strong&gt; Runs on a Raspberry Pi Zero 2 W with 512 &lt;span class="caps"&gt;MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;. In a container, it uses ~60 &lt;span class="caps"&gt;MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; and minimal &lt;span class="caps"&gt;CPU&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flexible blocklists:&lt;/strong&gt; Supports standard hosts files, adlists, wildcard blocking, and advanced regex. The community maintains blocklists for every niche (gaming, smart &lt;span class="caps"&gt;TV&lt;/span&gt;, TikTok,&amp;nbsp;etc.).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Teleporter:&lt;/strong&gt; Built-in backup/restore tool exports settings, blocklists, and local &lt;span class="caps"&gt;DNS&lt;/span&gt; records to a &lt;span class="caps"&gt;JSON&lt;/span&gt; file. Migration between instances is&amp;nbsp;trivial.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Gravity &lt;span class="caps"&gt;DB&lt;/span&gt;:&lt;/strong&gt; Custom SQLite-based blocklist compiler. Fast query resolution even with 5 million blocked&amp;nbsp;domains.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;UI&lt;/span&gt; is dated:&lt;/strong&gt; The web interface works but looks like a 2015 admin panel. No dark mode (as of 2026&amp;nbsp;v5.x).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DoH/DoT requires extra setup:&lt;/strong&gt; You need a&amp;nbsp;separate &lt;code&gt;cloudflared&lt;/code&gt; or &lt;code&gt;unbound&lt;/code&gt; container to encrypt upstream &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;queries.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No native mobile app:&lt;/strong&gt; Management is web-only. No push notifications for blocked&amp;nbsp;queries.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Per-client rules are clunky:&lt;/strong&gt; Group management exists but is not intuitive for non-technical&amp;nbsp;users.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Raspberry Pi and low-resource&amp;nbsp;deployments&lt;/li&gt;
&lt;li&gt;Users who want maximum blocklist flexibility and community&amp;nbsp;support&lt;/li&gt;
&lt;li&gt;Headless or automated setups (Pi-hole has excellent &lt;span class="caps"&gt;CLI&lt;/span&gt;/&lt;span class="caps"&gt;API&lt;/span&gt;&amp;nbsp;tools)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;p&gt;Free (open source, GPLv2). Optional donations via Open&amp;nbsp;Collective.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Option B: AdGuard&amp;nbsp;Home&lt;/h2&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Modern &lt;span class="caps"&gt;UI&lt;/span&gt;:&lt;/strong&gt; Dark mode, responsive design, and a query log that is actually searchable in real time. The dashboard is usable on a phone without&amp;nbsp;pinching.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Built-in encryption:&lt;/strong&gt; DoH, DoT, and &lt;span class="caps"&gt;DNS&lt;/span&gt;-over-&lt;span class="caps"&gt;QUIC&lt;/span&gt; upstreams are configurable in the web &lt;span class="caps"&gt;UI&lt;/span&gt; without extra containers. AdGuard Home can also act as a DoH/DoT server for your&amp;nbsp;devices.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Per-client configuration:&lt;/strong&gt; Assign different filtering rules, blocklists, and &lt;span class="caps"&gt;DNS&lt;/span&gt; rewrites to specific &lt;span class="caps"&gt;MAC&lt;/span&gt; addresses or &lt;span class="caps"&gt;IP&lt;/span&gt; ranges. Easy to set up kids&amp;#8217; devices with stricter&amp;nbsp;filters.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Parental controls:&lt;/strong&gt; Force safe search on Google, Bing, and YouTube. Block adult sites via a built-in category&amp;nbsp;filter.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Query log performance:&lt;/strong&gt; Uses a custom database engine that handles high query volumes without slowing down the web &lt;span class="caps"&gt;UI&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mobile app:&lt;/strong&gt; AdGuard Home Manager (Android/iOS) allows remote status checks, top client monitoring, and temporary&amp;nbsp;disable.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Slightly heavier:&lt;/strong&gt; Uses ~100–150 &lt;span class="caps"&gt;MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; vs Pi-hole&amp;#8217;s ~60 &lt;span class="caps"&gt;MB&lt;/span&gt;. Still trivial on modern&amp;nbsp;hardware.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Smaller blocklist ecosystem:&lt;/strong&gt; Most Pi-hole lists work, but some syntax differences exist. The AdGuard Home community&amp;nbsp;maintains &lt;code&gt;AdGuard SDN filter&lt;/code&gt; and &lt;code&gt;AdGuard DNS filter&lt;/code&gt; as&amp;nbsp;defaults.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fewer third-party integrations:&lt;/strong&gt; Pi-hole has native Home Assistant integration, Pi-hole 5 &lt;span class="caps"&gt;API&lt;/span&gt; wrappers in every language, and extensive automation scripts. AdGuard Home&amp;#8217;s &lt;span class="caps"&gt;API&lt;/span&gt; is good but less widely&amp;nbsp;used.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Users who value &lt;span class="caps"&gt;UI&lt;/span&gt;/&lt;span class="caps"&gt;UX&lt;/span&gt; and mobile&amp;nbsp;management&lt;/li&gt;
&lt;li&gt;Families needing parental controls and per-client&amp;nbsp;rules&lt;/li&gt;
&lt;li&gt;Users who want encrypted &lt;span class="caps"&gt;DNS&lt;/span&gt; without extra&amp;nbsp;containers&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;p&gt;Free (open source, GPLv3). AdGuard also sells commercial &lt;span class="caps"&gt;DNS&lt;/span&gt; and &lt;span class="caps"&gt;VPN&lt;/span&gt; services, but Home is fully&amp;nbsp;free.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Option C: Block &lt;span class="caps"&gt;DNS&lt;/span&gt; Ads at the Router (Adblock) or Hosts&amp;nbsp;File&lt;/h2&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Zero infrastructure:&lt;/strong&gt; Some routers (OpenWrt, &lt;span class="caps"&gt;ASUSWRT&lt;/span&gt;-Merlin, pfSense) have ad-blocking packages built&amp;nbsp;in.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hosts file:&lt;/strong&gt;&amp;nbsp;Edit &lt;code&gt;/etc/hosts&lt;/code&gt; on each device. No server&amp;nbsp;needed.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Limited blocklists:&lt;/strong&gt; Routers typically support smaller lists. Hosts files are painful to sync across&amp;nbsp;devices.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No stats:&lt;/strong&gt; You lose visibility into what is being&amp;nbsp;blocked.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Harder to manage:&lt;/strong&gt; Updating blocklists requires &lt;span class="caps"&gt;SSH&lt;/span&gt; or manual&amp;nbsp;edits.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Temporary setups or testing before committing to Pi-hole/AdGuard&amp;nbsp;Home&lt;/li&gt;
&lt;li&gt;Travel routers or single-device&amp;nbsp;use&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Comparison&amp;nbsp;Matrix&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Criteria&lt;/th&gt;
&lt;th&gt;Pi-hole&lt;/th&gt;
&lt;th&gt;AdGuard Home&lt;/th&gt;
&lt;th&gt;Router Adblock&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Setup ease&lt;/td&gt;
&lt;td&gt;Easy&lt;/td&gt;
&lt;td&gt;Easy&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;UI&lt;/span&gt; quality&lt;/td&gt;
&lt;td&gt;Functional&lt;/td&gt;
&lt;td&gt;Excellent&lt;/td&gt;
&lt;td&gt;Varies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resource use&lt;/td&gt;
&lt;td&gt;Very Low&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DoH/DoT&lt;/td&gt;
&lt;td&gt;Extra container&lt;/td&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;td&gt;Varies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Per-client rules&lt;/td&gt;
&lt;td&gt;Groups&lt;/td&gt;
&lt;td&gt;Easy&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Parental controls&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Query log speed&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;td&gt;Excellent&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mobile app&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Blocklist count&lt;/td&gt;
&lt;td&gt;10,000+&lt;/td&gt;
&lt;td&gt;5,000+&lt;/td&gt;
&lt;td&gt;100+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Community size&lt;/td&gt;
&lt;td&gt;Massive&lt;/td&gt;
&lt;td&gt;Large&lt;/td&gt;
&lt;td&gt;Small&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Which Should You&amp;nbsp;Choose?&lt;/h2&gt;
&lt;h3&gt;Scenario 1: Raspberry Pi or Mini &lt;span class="caps"&gt;PC&lt;/span&gt; with 2 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose Pi-hole.&lt;/strong&gt; It is lighter, and the 10-year community knowledge base means every edge case is documented. Pair it&amp;nbsp;with &lt;code&gt;unbound&lt;/code&gt; for recursive &lt;span class="caps"&gt;DNS&lt;/span&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Docker Compose: Pi-hole + Unbound&lt;/span&gt;
services:
&lt;span class="w"&gt;  &lt;/span&gt;pihole:
&lt;span class="w"&gt;    &lt;/span&gt;image:&lt;span class="w"&gt; &lt;/span&gt;pihole/pihole:2024.07.0
&lt;span class="w"&gt;    &lt;/span&gt;ports:
&lt;span class="w"&gt;      &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;53:53/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;53:53/udp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;80:80/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;environment:
&lt;span class="w"&gt;      &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;PIHOLE_DNS_&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;unbound#5053
&lt;span class="w"&gt;  &lt;/span&gt;unbound:
&lt;span class="w"&gt;    &lt;/span&gt;image:&lt;span class="w"&gt; &lt;/span&gt;mvance/unbound:latest
&lt;span class="w"&gt;    &lt;/span&gt;ports:
&lt;span class="w"&gt;      &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;5053:53/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;5053:53/udp&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Scenario 2: Family Network with Kids and&amp;nbsp;Guests&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose AdGuard Home.&lt;/strong&gt; The parental controls, per-client rules, and safe search enforcement are family-friendly. You can set different blocklists for the kids&amp;#8217; tablets vs your work laptop. The mobile app lets you temporarily disable blocking when a false positive breaks a&amp;nbsp;site.&lt;/p&gt;
&lt;h3&gt;Scenario 3: You Want the &amp;#8220;Best of&amp;nbsp;Both&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Run both.&lt;/strong&gt; Seriously. Some homelabbers run Pi-hole as the primary &lt;span class="caps"&gt;DNS&lt;/span&gt; (for its Gravity blocklist performance) and AdGuard Home as a secondary upstream with different filtering rules. Or use Pi-hole for the network and AdGuard Home on a separate &lt;span class="caps"&gt;VLAN&lt;/span&gt; for&amp;nbsp;guests.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Migration&amp;nbsp;Path&lt;/h2&gt;
&lt;h3&gt;Pi-hole to AdGuard&amp;nbsp;Home&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Export Pi-hole settings via Teleporter (Settings →&amp;nbsp;Teleporter)&lt;/li&gt;
&lt;li&gt;In AdGuard Home, go to Settings → &lt;span class="caps"&gt;DNS&lt;/span&gt; Blocklists → Add&amp;nbsp;blocklist&lt;/li&gt;
&lt;li&gt;Import your Pi-hole adlists manually (AdGuard Home does not parse Pi-hole Teleporter files&amp;nbsp;directly)&lt;/li&gt;
&lt;li&gt;Re-create Local &lt;span class="caps"&gt;DNS&lt;/span&gt; Records as &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;rewrites&lt;/li&gt;
&lt;li&gt;Re-create client groups as per-client&amp;nbsp;settings&lt;/li&gt;
&lt;li&gt;Point your router &lt;span class="caps"&gt;DHCP&lt;/span&gt; &lt;span class="caps"&gt;DNS&lt;/span&gt; to AdGuard&amp;nbsp;Home&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;AdGuard Home to&amp;nbsp;Pi-hole&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Export settings from AdGuard Home (Settings → General →&amp;nbsp;Export)&lt;/li&gt;
&lt;li&gt;In Pi-hole, add your AdGuard blocklists as&amp;nbsp;adlists&lt;/li&gt;
&lt;li&gt;Add &lt;span class="caps"&gt;DNS&lt;/span&gt; rewrites as Local &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;Records&lt;/li&gt;
&lt;li&gt;Re-create per-client settings as Group Management&amp;nbsp;rules&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;The&amp;nbsp;Verdict&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Priority&lt;/th&gt;
&lt;th&gt;Winner&lt;/th&gt;
&lt;th&gt;Reason&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Raw performance&lt;/td&gt;
&lt;td&gt;Tie&lt;/td&gt;
&lt;td&gt;Both resolve &lt;span class="caps"&gt;DNS&lt;/span&gt; in &amp;lt;5 ms on modern hardware&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;UI&lt;/span&gt;/&lt;span class="caps"&gt;UX&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;AdGuard Home&lt;/td&gt;
&lt;td&gt;Modern, dark mode, mobile app&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Community/docs&lt;/td&gt;
&lt;td&gt;Pi-hole&lt;/td&gt;
&lt;td&gt;10 years of Reddit threads, scripts, and guides&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Low-resource&lt;/td&gt;
&lt;td&gt;Pi-hole&lt;/td&gt;
&lt;td&gt;~60 &lt;span class="caps"&gt;MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; vs ~120 &lt;span class="caps"&gt;MB&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Family features&lt;/td&gt;
&lt;td&gt;AdGuard Home&lt;/td&gt;
&lt;td&gt;Parental controls, per-client rules, safe search&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Encryption&lt;/td&gt;
&lt;td&gt;AdGuard Home&lt;/td&gt;
&lt;td&gt;Built-in DoH/DoT/&lt;span class="caps"&gt;DNS&lt;/span&gt;-over-&lt;span class="caps"&gt;QUIC&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Blocklist flexibility&lt;/td&gt;
&lt;td&gt;Pi-hole&lt;/td&gt;
&lt;td&gt;Larger ecosystem, more regex support&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Our recommendation:&lt;/strong&gt; If you are a technical user running a headless lab, choose &lt;strong&gt;Pi-hole&lt;/strong&gt; for its community and lightness. If you share your network with family or want a polished, app-friendly experience, choose &lt;strong&gt;AdGuard Home&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Both Pi-hole and AdGuard Home are excellent &lt;span class="caps"&gt;DNS&lt;/span&gt; ad blockers. Pi-hole wins on maturity and resource efficiency. AdGuard Home wins on modern &lt;span class="caps"&gt;UI&lt;/span&gt;, built-in encryption, and family features. The &amp;#8220;best&amp;#8221; tool is the one that fits your household&amp;#8217;s technical&amp;nbsp;culture.&lt;/p&gt;
&lt;h3&gt;Ready to Get&amp;nbsp;Started?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Deploy&amp;nbsp;Pi-hole: &lt;code&gt;docker run -d --name pihole -p 53:53/tcp -p 53:53/udp -p 80:80 pihole/pihole:latest&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Deploy AdGuard&amp;nbsp;Home: &lt;code&gt;docker run -d --name adguardhome -p 53:53/tcp -p 53:53/udp -p 3000:3000 adguard/adguardhome:latest&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Raspberry Pi:&lt;/strong&gt; Raspberry Pi 5 kits (Amazon, The Pi&amp;nbsp;Hut)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mini PCs:&lt;/strong&gt; Minisforum, Beelink&amp;nbsp;(Amazon)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Networking:&lt;/strong&gt; Ubiquiti, &lt;span class="caps"&gt;TP&lt;/span&gt;-Link Omada&amp;nbsp;(Amazon)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;setup-scenarios&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;pihole-docker-compose.md&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;setup-scenarios&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;adguard-home-docker.md&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dns-encryption&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;dns-filtering-homelab.md&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;router-setup&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;homelab-networking-basics.md&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] Which &lt;span class="caps"&gt;DNS&lt;/span&gt; blocker do you run? Pi-hole, AdGuard Home, or both? Vote in the&amp;nbsp;comments.&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for our monthly network security and privacy stack&amp;nbsp;updates.&lt;/li&gt;
&lt;li&gt;[internal_link] Want to set one up? Read our &lt;a href="https://steadypub.com/2026/06/pihole-docker-compose/"&gt;Pi-hole Docker guide&lt;/a&gt; or &lt;a href="https://steadypub.com/2026/06/adguard-home-setup/"&gt;AdGuard Home setup guide&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Comparisons"/><category term="adguard home"/><category term="homelab"/><category term="self-hosted"/><category term="pihole"/><category term="dns filtering"/></entry><entry><title>Best Mini PCs for Homelab in 2026: N100, N305, and Beyond</title><link href="https://steadypub.com/2026/06/best-mini-pc-for-homelab/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T10:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/best-mini-pc-for-homelab/</id><summary type="html">&lt;p&gt;Compare the best mini PCs for homelab use in 2026. Intel N100, N305, &lt;span class="caps"&gt;AMD&lt;/span&gt; Ryzen, and premium options reviewed for power, noise, and&amp;nbsp;virtualization.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~15 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelabbers choosing a compact, low-power&amp;nbsp;server&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why Mini PCs for&amp;nbsp;Homelab?&lt;/h2&gt;
&lt;p&gt;Mini PCs have become the dominant homelab hardware for good&amp;nbsp;reason:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Advantage&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Power efficiency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;6–15W idle vs. 100W+ for rack servers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Noise&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Silent or near-silent (fanless options)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Size&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fits on a desk, shelf, or behind a monitor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$150–$400 vs. $500+ for used rack servers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Modern connectivity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2.5GbE, Wi-Fi 6, &lt;span class="caps"&gt;USB&lt;/span&gt;-C, NVMe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Virtualization&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;VT&lt;/span&gt;-x/&lt;span class="caps"&gt;VT&lt;/span&gt;-d or &lt;span class="caps"&gt;AMD&lt;/span&gt;-V/&lt;span class="caps"&gt;IOMMU&lt;/span&gt; support&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Top Mini PCs for Homelab&amp;nbsp;(2026)&lt;/h2&gt;
&lt;h3&gt;1. Intel N100/N305 (Best&amp;nbsp;Budget)&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;N100&lt;/th&gt;
&lt;th&gt;N305&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cores/Threads&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;4C/4T&lt;/td&gt;
&lt;td&gt;8C/8T&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;TDP&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;6W&lt;/td&gt;
&lt;td&gt;15W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Max &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;16GB&lt;/span&gt; &lt;span class="caps"&gt;DDR5&lt;/span&gt; (single &lt;span class="caps"&gt;SODIMM&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;32GB&lt;/span&gt; &lt;span class="caps"&gt;DDR5&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ethernet&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1x 2.5GbE (typical)&lt;/td&gt;
&lt;td&gt;2x 2.5GbE (some models)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1x NVMe + 1x &lt;span class="caps"&gt;SATA&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1x NVMe + 1x &lt;span class="caps"&gt;SATA&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Price&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$150–$200&lt;/td&gt;
&lt;td&gt;$250–$350&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Idle power&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;6–8W&lt;/td&gt;
&lt;td&gt;10–15W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Proxmox VMs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;3–5&lt;/td&gt;
&lt;td&gt;5–10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Noise&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Silent (fanless options)&lt;/td&gt;
&lt;td&gt;Low fan noise&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Beginners, low-power 24/7 servers, Docker containers
&lt;strong&gt;Recommended models:&lt;/strong&gt; Minisforum &lt;span class="caps"&gt;UN100D&lt;/span&gt;, Beelink U59 Pro, Intel &lt;span class="caps"&gt;NUC&lt;/span&gt; 13&amp;nbsp;Pro&lt;/p&gt;
&lt;h3&gt;2. Minisforum &lt;span class="caps"&gt;MS&lt;/span&gt;-01 (Best&amp;nbsp;All-Rounder)&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Intel i9-12900H (14C/20T)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;TDP&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;45W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;64GB&lt;/span&gt; &lt;span class="caps"&gt;DDR5&lt;/span&gt; (2x &lt;span class="caps"&gt;SODIMM&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ethernet&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2x 10GbE &lt;span class="caps"&gt;SFP&lt;/span&gt;+ + 2x 2.5GbE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;3x M.2 NVMe + 1x U.2 (with adapter)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PCIe&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1x PCIe x16 (discrete &lt;span class="caps"&gt;GPU&lt;/span&gt; or &lt;span class="caps"&gt;HBA&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Price&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$600–$800&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Idle power&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;15–20W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Proxmox VMs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;15–25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Noise&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Moderate (blowers under load)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Power users, virtualization clusters, 10GbE networking, &lt;span class="caps"&gt;NAS&lt;/span&gt; + &lt;span class="caps"&gt;VM&lt;/span&gt; combo
&lt;strong&gt;Full review:&lt;/strong&gt; See our&amp;nbsp;dedicated &lt;code&gt;minisforum-ms-01-review.md&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;3. &lt;span class="caps"&gt;AMD&lt;/span&gt; Ryzen 7 &lt;span class="caps"&gt;7840HS&lt;/span&gt; (Best&amp;nbsp;Performance)&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;AMD&lt;/span&gt; Ryzen 7 &lt;span class="caps"&gt;7840HS&lt;/span&gt; (8C/16T)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;iGPU&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Radeon 780M (&lt;span class="caps"&gt;RDNA3&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;TDP&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;35–54W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;64GB&lt;/span&gt; &lt;span class="caps"&gt;DDR5&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ethernet&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2x 2.5GbE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2x NVMe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Price&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$500–$700&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Idle power&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;12–18W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Proxmox VMs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;10–20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Noise&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Moderate&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; &lt;span class="caps"&gt;GPU&lt;/span&gt; passthrough, &lt;span class="caps"&gt;AI&lt;/span&gt;/&lt;span class="caps"&gt;ML&lt;/span&gt; workloads (Ollama), gaming + homelab combo
&lt;strong&gt;Recommended models:&lt;/strong&gt; Minisforum &lt;span class="caps"&gt;UM790&lt;/span&gt; Pro, Beelink &lt;span class="caps"&gt;SER7&lt;/span&gt;, &lt;span class="caps"&gt;GTR7&lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;4. Beelink &lt;span class="caps"&gt;EQ12&lt;/span&gt; (Best N100&amp;nbsp;Variant)&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Intel N100&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;16GB&lt;/span&gt; &lt;span class="caps"&gt;DDR5&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ethernet&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2x 2.5GbE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1x NVMe + 1x &lt;span class="caps"&gt;SATA&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Price&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$180–$220&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Idle power&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;6W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Special&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Dual 2.5GbE ideal for router/firewall&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Router/firewall builds (pfSense, OPNsense, OpenWrt), low-power &lt;span class="caps"&gt;NAS&lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;5. Intel &lt;span class="caps"&gt;NUC&lt;/span&gt; 13 Pro (Best&amp;nbsp;Enterprise)&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;NUC13ANKi3&lt;/th&gt;
&lt;th&gt;NUC13ANKi5&lt;/th&gt;
&lt;th&gt;NUC13ANKi7&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;i3-1315U&lt;/td&gt;
&lt;td&gt;i5-1340P&lt;/td&gt;
&lt;td&gt;i7-1360P&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cores&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;6C/8T&lt;/td&gt;
&lt;td&gt;12C/16T&lt;/td&gt;
&lt;td&gt;12C/16T&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;64GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;64GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;64GB&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ethernet&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1x 2.5GbE&lt;/td&gt;
&lt;td&gt;1x 2.5GbE&lt;/td&gt;
&lt;td&gt;1x 2.5GbE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2x NVMe&lt;/td&gt;
&lt;td&gt;2x NVMe&lt;/td&gt;
&lt;td&gt;2x NVMe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Price&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$350&lt;/td&gt;
&lt;td&gt;$450&lt;/td&gt;
&lt;td&gt;$550&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Idle power&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;8W&lt;/td&gt;
&lt;td&gt;10W&lt;/td&gt;
&lt;td&gt;12W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Proxmox VMs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;5–8&lt;/td&gt;
&lt;td&gt;10–15&lt;/td&gt;
&lt;td&gt;12–18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Noise&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Very quiet&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Warranty&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;3 years Intel&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Business environments, vPro remote management, stable&amp;nbsp;drivers&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Comparison&amp;nbsp;Matrix&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;th&gt;Power&lt;/th&gt;
&lt;th&gt;VMs&lt;/th&gt;
&lt;th&gt;Network&lt;/th&gt;
&lt;th&gt;Best Use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Intel N100&lt;/td&gt;
&lt;td&gt;$150–$200&lt;/td&gt;
&lt;td&gt;6W&lt;/td&gt;
&lt;td&gt;3–5&lt;/td&gt;
&lt;td&gt;1–2x 2.5GbE&lt;/td&gt;
&lt;td&gt;Beginner, Docker, low power&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Beelink &lt;span class="caps"&gt;EQ12&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$180–$220&lt;/td&gt;
&lt;td&gt;6W&lt;/td&gt;
&lt;td&gt;3–5&lt;/td&gt;
&lt;td&gt;2x 2.5GbE&lt;/td&gt;
&lt;td&gt;Router/firewall, &lt;span class="caps"&gt;NAS&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Intel N305&lt;/td&gt;
&lt;td&gt;$250–$350&lt;/td&gt;
&lt;td&gt;15W&lt;/td&gt;
&lt;td&gt;5–10&lt;/td&gt;
&lt;td&gt;2x 2.5GbE&lt;/td&gt;
&lt;td&gt;Intermediate VMs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Intel &lt;span class="caps"&gt;NUC&lt;/span&gt; 13 i5&lt;/td&gt;
&lt;td&gt;$450&lt;/td&gt;
&lt;td&gt;10W&lt;/td&gt;
&lt;td&gt;10–15&lt;/td&gt;
&lt;td&gt;1x 2.5GbE&lt;/td&gt;
&lt;td&gt;Enterprise, reliable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Minisforum &lt;span class="caps"&gt;MS&lt;/span&gt;-01&lt;/td&gt;
&lt;td&gt;$600–$800&lt;/td&gt;
&lt;td&gt;20W&lt;/td&gt;
&lt;td&gt;15–25&lt;/td&gt;
&lt;td&gt;2x 10GbE + 2x 2.5GbE&lt;/td&gt;
&lt;td&gt;Power user, 10GbE, &lt;span class="caps"&gt;NAS&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ryzen 7 &lt;span class="caps"&gt;7840HS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$500–$700&lt;/td&gt;
&lt;td&gt;15W&lt;/td&gt;
&lt;td&gt;10–20&lt;/td&gt;
&lt;td&gt;2x 2.5GbE&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;GPU&lt;/span&gt; passthrough, &lt;span class="caps"&gt;AI&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Performance&amp;nbsp;Benchmarks&lt;/h2&gt;
&lt;h3&gt;Proxmox &lt;span class="caps"&gt;VM&lt;/span&gt; Density&amp;nbsp;Test&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Hardware&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;1GB&lt;/span&gt; VMs&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;2GB&lt;/span&gt; VMs&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;4GB&lt;/span&gt; VMs&lt;/th&gt;
&lt;th&gt;Containers&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;N100 (&lt;span class="caps"&gt;16GB&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;20+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;N305 (&lt;span class="caps"&gt;32GB&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;40+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;MS&lt;/span&gt;-01 (&lt;span class="caps"&gt;64GB&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;80+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ryzen &lt;span class="caps"&gt;7840HS&lt;/span&gt; (&lt;span class="caps"&gt;64GB&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;80+&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;em&gt;Tested with Ubuntu 22.04 &lt;span class="caps"&gt;LTS&lt;/span&gt; VMs, idle load, 1 vCPU&amp;nbsp;each&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Power&amp;nbsp;Consumption&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Hardware&lt;/th&gt;
&lt;th&gt;Idle&lt;/th&gt;
&lt;th&gt;Load&lt;/th&gt;
&lt;th&gt;Annual Cost (@$0.15/kWh)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;N100&lt;/td&gt;
&lt;td&gt;6W&lt;/td&gt;
&lt;td&gt;15W&lt;/td&gt;
&lt;td&gt;~$8–$20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;N305&lt;/td&gt;
&lt;td&gt;12W&lt;/td&gt;
&lt;td&gt;25W&lt;/td&gt;
&lt;td&gt;~$16–$33&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;MS&lt;/span&gt;-01&lt;/td&gt;
&lt;td&gt;18W&lt;/td&gt;
&lt;td&gt;65W&lt;/td&gt;
&lt;td&gt;~$24–$85&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ryzen &lt;span class="caps"&gt;7840HS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;15W&lt;/td&gt;
&lt;td&gt;55W&lt;/td&gt;
&lt;td&gt;~$20–$72&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Used rack server (Dell R720)&lt;/td&gt;
&lt;td&gt;80W&lt;/td&gt;
&lt;td&gt;200W&lt;/td&gt;
&lt;td&gt;~$105–$263&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;What to Look&amp;nbsp;For&lt;/h2&gt;
&lt;h3&gt;Essential&amp;nbsp;Features&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Why It Matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;2.5GbE or faster&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Future-proof for &lt;span class="caps"&gt;NAS&lt;/span&gt;, backups, &lt;span class="caps"&gt;VM&lt;/span&gt; migration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;DDR5&lt;/span&gt; support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;50% faster than &lt;span class="caps"&gt;DDR4&lt;/span&gt;, better power efficiency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;NVMe slot&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;5x faster than &lt;span class="caps"&gt;SATA&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt; for &lt;span class="caps"&gt;VM&lt;/span&gt; storage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;VT&lt;/span&gt;-x + &lt;span class="caps"&gt;VT&lt;/span&gt;-d (Intel) / &lt;span class="caps"&gt;AMD&lt;/span&gt;-V + &lt;span class="caps"&gt;IOMMU&lt;/span&gt; (&lt;span class="caps"&gt;AMD&lt;/span&gt;)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Required for virtualization and PCIe passthrough&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Fanless or low-noise&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;24/7 operation in living spaces&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;2+ storage slots&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Mirror/boot redundancy or NVMe + &lt;span class="caps"&gt;SATA&lt;/span&gt; combo&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Nice-to-Have&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Benefit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;10GbE &lt;span class="caps"&gt;SFP&lt;/span&gt;+&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fast &lt;span class="caps"&gt;NAS&lt;/span&gt;, &lt;span class="caps"&gt;VM&lt;/span&gt; migration, clustering&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PCIe slot&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Add &lt;span class="caps"&gt;HBA&lt;/span&gt;, &lt;span class="caps"&gt;NIC&lt;/span&gt;, or &lt;span class="caps"&gt;GPU&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;USB&lt;/span&gt;-C (DisplayPort)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Single-cable monitor + power&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;VESA&lt;/span&gt; mount&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hide behind monitor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;TPM&lt;/span&gt; 2.0&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Windows 11, BitLocker, security&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;vPro/&lt;span class="caps"&gt;AMT&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Remote management even when &lt;span class="caps"&gt;OS&lt;/span&gt; is down&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Setup&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;&lt;span class="caps"&gt;BIOS&lt;/span&gt;&amp;nbsp;Configuration&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="mf"&gt;1.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="n"&gt;el&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VT&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;AMD&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;V&lt;/span&gt;
&lt;span class="mf"&gt;2.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="n"&gt;el&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VT&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;AMD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IOMMU&lt;/span&gt;
&lt;span class="mf"&gt;3.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Disable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Secure&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Boot&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Proxmox&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;Linux&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mf"&gt;4.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;SATA&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;AHCI&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ow"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RAID&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ZFS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mf"&gt;5.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Wake&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="kr"&gt;on&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;LAN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;remote power on)&lt;/span&gt;
&lt;span class="mf"&gt;6.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Disable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;unnecessary&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;on&lt;/span&gt;&lt;span class="n"&gt;board&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;devices&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Proxmox on Mini &lt;span class="caps"&gt;PC&lt;/span&gt;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Install Proxmox VE (see our guide)&lt;/span&gt;
&lt;span class="c1"&gt;# After install, optimize for low power:&lt;/span&gt;
apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;cpufrequtils
sed&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;s/GOVERNOR=&amp;quot;performance&amp;quot;/GOVERNOR=&amp;quot;ondemand&amp;quot;/&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/init.d/cpufrequtils
systemctl&lt;span class="w"&gt; &lt;/span&gt;restart&lt;span class="w"&gt; &lt;/span&gt;cpufrequtils

&lt;span class="c1"&gt;# Verify CPU scaling&lt;/span&gt;
cat&lt;span class="w"&gt; &lt;/span&gt;/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
&lt;span class="c1"&gt;# Should show: ondemand&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;For most homelabbers in 2026, the &lt;strong&gt;Intel N100&lt;/strong&gt; ($150–$200) is the unbeatable starting point. If you need more VMs or 10GbE, the &lt;strong&gt;Minisforum &lt;span class="caps"&gt;MS&lt;/span&gt;-01&lt;/strong&gt; ($600–$800) is the premium choice. For &lt;span class="caps"&gt;GPU&lt;/span&gt; passthrough or &lt;span class="caps"&gt;AI&lt;/span&gt; workloads, &lt;strong&gt;&lt;span class="caps"&gt;AMD&lt;/span&gt; Ryzen &lt;span class="caps"&gt;7840HS&lt;/span&gt;&lt;/strong&gt; mini PCs offer the best iGPU&amp;nbsp;performance.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Check your budget and power&amp;nbsp;constraints&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Buy from Amazon or AliExpress&lt;/strong&gt; (Minisforum/Beelink official&amp;nbsp;stores)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Install Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;&lt;/strong&gt; (see our beginner&amp;nbsp;guide)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deploy your first 5 services&lt;/strong&gt; (see our self-hosted services&amp;nbsp;list)&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Amazon:&lt;/strong&gt; Mini PCs, &lt;span class="caps"&gt;RAM&lt;/span&gt;,&amp;nbsp;SSDs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AliExpress:&lt;/strong&gt; Direct from Minisforum/Beelink (often&amp;nbsp;cheaper)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;B&amp;amp;H Photo:&lt;/strong&gt; Intel &lt;span class="caps"&gt;NUC&lt;/span&gt;, enterprise&amp;nbsp;options&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Newegg:&lt;/strong&gt; &lt;span class="caps"&gt;PC&lt;/span&gt; components, NVMe&amp;nbsp;SSDs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Accessories:&lt;/strong&gt; &lt;span class="caps"&gt;USB&lt;/span&gt;-C hubs, &lt;span class="caps"&gt;VESA&lt;/span&gt; mounts, 2.5GbE&amp;nbsp;switches&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal&amp;nbsp;Linking&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;proxmox&lt;/code&gt; → &lt;code&gt;proxmox-beginner-guide-2026.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ms-01&lt;/code&gt; → &lt;code&gt;minisforum-ms-01-review.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;n100&lt;/code&gt; → &lt;code&gt;intel-n100-mini-pc-homelab.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker&lt;/code&gt; → &lt;code&gt;home-server-docker-setup.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hardware&lt;/code&gt; → &lt;code&gt;homelab-server-hardware-2026.md&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Which mini &lt;span class="caps"&gt;PC&lt;/span&gt; powers your homelab?&lt;/strong&gt; Share your specs in the&amp;nbsp;comments.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subscribe&lt;/strong&gt; for mini &lt;span class="caps"&gt;PC&lt;/span&gt; reviews and homelab build&amp;nbsp;guides.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Reviews"/><category term="best mini pc for homelab"/><category term="intel n100 homelab"/><category term="minisforum"/><category term="beelink"/><category term="homelab hardware"/></entry><entry><title>Best Self-Hosted Software 2026: The Privacy-First Toolkit for Your Homelab</title><link href="https://steadypub.com/2026/06/best-self-hosted-software-2025/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T10:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/best-self-hosted-software-2025/</id><summary type="html">&lt;p&gt;The definitive list of the best self-hosted software for 2026. Covers cloud storage, media servers, password managers, and &lt;span class="caps"&gt;AI&lt;/span&gt; tools with real deployment&amp;nbsp;advice.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~18 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab and self-hosting&amp;nbsp;enthusiasts&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;Self-hosting is the practice of running software on your own hardware instead of relying on third-party cloud services. In 2026, the self-hosted ecosystem is more mature than ever, with polished alternatives to Google, Microsoft, and Apple services. This guide presents the best self-hosted software across 10 categories, selected for stability, community support, and real-world&amp;nbsp;usability.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why Use Self-Hosted&amp;nbsp;Software?&lt;/h2&gt;
&lt;h3&gt;Data&amp;nbsp;Sovereignty&lt;/h3&gt;
&lt;p&gt;Your data stays on your hardware. No terms-of-service changes, no account bans, and no &lt;span class="caps"&gt;AI&lt;/span&gt; training on your personal&amp;nbsp;files.&lt;/p&gt;
&lt;h3&gt;Cost&amp;nbsp;Control&lt;/h3&gt;
&lt;p&gt;A one-time hardware purchase replaces recurring subscriptions. A family of four can save $500+ annually by self-hosting cloud storage, photos, and password&amp;nbsp;management.&lt;/p&gt;
&lt;h3&gt;Customization&lt;/h3&gt;
&lt;p&gt;Self-hosted software is open-source and extensible. You can add features, integrate with other tools, and modify the &lt;span class="caps"&gt;UI&lt;/span&gt; to match your&amp;nbsp;workflow.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The 2026 Self-Hosted&amp;nbsp;Toolkit&lt;/h2&gt;
&lt;h3&gt;1. Cloud Storage:&amp;nbsp;Nextcloud&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Why it tops our list:&lt;/strong&gt; Nextcloud is the most mature self-hosted cloud platform. It offers file sync, sharing, document editing, and a 400+ app&amp;nbsp;ecosystem.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Specifications:&lt;/strong&gt;
- &lt;strong&gt;Platform:&lt;/strong&gt; Linux, Docker, snap
- &lt;strong&gt;Database:&lt;/strong&gt; PostgreSQL, MariaDB, SQLite
- &lt;strong&gt;Mobile:&lt;/strong&gt; iOS, Android, desktop clients
- &lt;strong&gt;Protocols:&lt;/strong&gt; WebDAV, CalDAV,&amp;nbsp;CardDAV&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;
- Full productivity suite (files, calendar, contacts, mail)
- End-to-end encryption available
- Active security team and bug&amp;nbsp;bounty&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;
- Higher resource usage than dedicated file servers
- &lt;span class="caps"&gt;UI&lt;/span&gt; can feel cluttered with many apps&amp;nbsp;enabled&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Families and small teams needing a unified private&amp;nbsp;cloud.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Free (community edition). Enterprise support&amp;nbsp;available.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;2. Photo Management:&amp;nbsp;Immich&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Why it made the list:&lt;/strong&gt; Immich is the closest self-hosted equivalent to Google Photos. It offers &lt;span class="caps"&gt;AI&lt;/span&gt;-powered search, face recognition, and a polished mobile&amp;nbsp;app.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Specifications:&lt;/strong&gt;
- &lt;strong&gt;Platform:&lt;/strong&gt; Docker
- &lt;strong&gt;Database:&lt;/strong&gt; PostgreSQL with pgvecto.rs
- &lt;strong&gt;&lt;span class="caps"&gt;ML&lt;/span&gt;:&lt;/strong&gt; Local &lt;span class="caps"&gt;CLIP&lt;/span&gt; and face recognition models
- &lt;strong&gt;Mobile:&lt;/strong&gt; Native iOS/Android&amp;nbsp;apps&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;
- Excellent &lt;span class="caps"&gt;AI&lt;/span&gt; search (&amp;#8220;photos of my dog at the beach&amp;#8221;)
- Fast background upload
- &lt;span class="caps"&gt;RAW&lt;/span&gt; file&amp;nbsp;support&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;
- Rapid development; occasional breaking changes
- No client-side encryption&amp;nbsp;yet&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Photo-heavy users wanting Google Photos functionality without the privacy&amp;nbsp;cost.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt;&amp;nbsp;Free.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;3. Media Server:&amp;nbsp;Jellyfin&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Why it made the list:&lt;/strong&gt; Jellyfin is the open-source fork of Emby, offering media streaming without paywalls or subscription&amp;nbsp;nagging.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Specifications:&lt;/strong&gt;
- &lt;strong&gt;Platform:&lt;/strong&gt; Windows, Linux, macOS, Docker
- &lt;strong&gt;Formats:&lt;/strong&gt; Direct play, transcoding (&lt;span class="caps"&gt;VAAPI&lt;/span&gt;, &lt;span class="caps"&gt;NVENC&lt;/span&gt;)
- &lt;strong&gt;Clients:&lt;/strong&gt; Web, Android, iOS, Roku, Android &lt;span class="caps"&gt;TV&lt;/span&gt;, Kodi
- &lt;strong&gt;Live &lt;span class="caps"&gt;TV&lt;/span&gt;:&lt;/strong&gt; &lt;span class="caps"&gt;DVR&lt;/span&gt; support with&amp;nbsp;HDHomeRun&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;
- Completely free, no premium tier
- Hardware transcoding on Intel iGPU and &lt;span class="caps"&gt;NVIDIA&lt;/span&gt;
- Active plugin&amp;nbsp;ecosystem&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;
- &lt;span class="caps"&gt;UI&lt;/span&gt; less polished than Plex
- No official cloud sync for watch&amp;nbsp;status&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Users who want a fully free media server with no feature&amp;nbsp;gates.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt;&amp;nbsp;Free.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;4. Password Manager:&amp;nbsp;Vaultwarden&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Why it made the list:&lt;/strong&gt; Vaultwarden is a lightweight Rust implementation of the Bitwarden server. It provides the same functionality with a fraction of the resource&amp;nbsp;usage.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Specifications:&lt;/strong&gt;
- &lt;strong&gt;Platform:&lt;/strong&gt; Docker, binary
- &lt;strong&gt;Database:&lt;/strong&gt; SQLite, MariaDB, PostgreSQL
- &lt;strong&gt;Clients:&lt;/strong&gt; Browser extensions, mobile apps, &lt;span class="caps"&gt;CLI&lt;/span&gt;
- &lt;strong&gt;Security:&lt;/strong&gt; &lt;span class="caps"&gt;AES&lt;/span&gt;-256, &lt;span class="caps"&gt;PBKDF2&lt;/span&gt;,&amp;nbsp;Argon2&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;
- Compatible with official Bitwarden clients
- Runs on a Raspberry Pi
- Supports &lt;span class="caps"&gt;2FA&lt;/span&gt;, collections, and&amp;nbsp;organizations&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;
- Some enterprise features (&lt;span class="caps"&gt;SSO&lt;/span&gt;, &lt;span class="caps"&gt;SCIM&lt;/span&gt;) not implemented
- Community-supported; no official &lt;span class="caps"&gt;SLA&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Individuals and families wanting a secure password manager without subscription&amp;nbsp;fees.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt;&amp;nbsp;Free.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;5. Ad Blocking:&amp;nbsp;Pi-hole&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Why it made the list:&lt;/strong&gt; Pi-hole blocks ads and trackers at the &lt;span class="caps"&gt;DNS&lt;/span&gt; level, protecting every device on your network without client-side&amp;nbsp;software.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Specifications:&lt;/strong&gt;
- &lt;strong&gt;Platform:&lt;/strong&gt; Raspberry Pi, Linux, Docker
- &lt;strong&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt;:&lt;/strong&gt; Custom upstream (Cloudflare, Quad9, Unbound)
- &lt;strong&gt;Lists:&lt;/strong&gt; StevenBlack, custom regex, whitelisting
- &lt;strong&gt;Stats:&lt;/strong&gt; Query log, dashboard, &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;
- Network-wide protection (IoT, smart TVs, phones)
- Low resource usage
- Active community and blocklist&amp;nbsp;curation&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;
- Does not block all YouTube ads (requires uBlock Origin)
- Can break sites with aggressive&amp;nbsp;lists&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Every homelab. This is foundational&amp;nbsp;infrastructure.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt;&amp;nbsp;Free.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;6. Monitoring: Grafana + Prometheus +&amp;nbsp;Loki&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Why it made the list:&lt;/strong&gt; This trio provides metrics, logs, and alerting for your entire infrastructure. It is the same stack used by cloud providers, now&amp;nbsp;self-hosted.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Specifications:&lt;/strong&gt;
- &lt;strong&gt;Prometheus:&lt;/strong&gt; Time-series metrics, PromQL
- &lt;strong&gt;Grafana:&lt;/strong&gt; Dashboards, alerts, annotations
- &lt;strong&gt;Loki:&lt;/strong&gt; Log aggregation, LogQL
- &lt;strong&gt;Alertmanager:&lt;/strong&gt; Routing, silencing,&amp;nbsp;grouping&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;
- Native Docker service discovery
- Hundreds of pre-built dashboards
- Scales from a single server to a&amp;nbsp;cluster&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;
- Steep learning curve for PromQL
- Resource usage grows with&amp;nbsp;cardinality&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Operators who want visibility into server health, container performance, and application&amp;nbsp;logs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt;&amp;nbsp;Free.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;7. &lt;span class="caps"&gt;VPN&lt;/span&gt;: WireGuard +&amp;nbsp;Tailscale&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Why it made the list:&lt;/strong&gt; WireGuard provides fast, modern &lt;span class="caps"&gt;VPN&lt;/span&gt; tunnels. Tailscale builds a mesh network on top of WireGuard with zero&amp;nbsp;configuration.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Specifications:&lt;/strong&gt;
- &lt;strong&gt;WireGuard:&lt;/strong&gt; Kernel module, 4,000 lines of code
- &lt;strong&gt;Tailscale:&lt;/strong&gt; &lt;span class="caps"&gt;NAT&lt;/span&gt; traversal, &lt;span class="caps"&gt;SSO&lt;/span&gt;, ACLs
- &lt;strong&gt;Headscale:&lt;/strong&gt; Self-hosted Tailscale control server
- &lt;strong&gt;Performance:&lt;/strong&gt; Near-line-speed on modern&amp;nbsp;CPUs&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;
- WireGuard is faster and simpler than OpenVPN/IPsec
- Tailscale works behind &lt;span class="caps"&gt;CGNAT&lt;/span&gt; without port forwarding
- Headscale gives full control without Tailscale&amp;#8217;s&amp;nbsp;cloud&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;
- Tailscale free tier has device limits
- Headscale requires&amp;nbsp;maintenance&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Remote access to homelab services and secure device-to-device&amp;nbsp;communication.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Free (self-hosted). Tailscale free: 20&amp;nbsp;devices.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;8. &lt;span class="caps"&gt;AI&lt;/span&gt; / &lt;span class="caps"&gt;LLM&lt;/span&gt;: Ollama +&amp;nbsp;OpenWebUI&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Why it made the list:&lt;/strong&gt; 2026 is the year of local &lt;span class="caps"&gt;AI&lt;/span&gt;. Ollama makes running LLMs as easy&amp;nbsp;as &lt;code&gt;ollama run llama3&lt;/code&gt;, and OpenWebUI provides a ChatGPT-like&amp;nbsp;interface.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Specifications:&lt;/strong&gt;
- &lt;strong&gt;Ollama:&lt;/strong&gt; Model management, &lt;span class="caps"&gt;GPU&lt;/span&gt; acceleration, &lt;span class="caps"&gt;REST&lt;/span&gt; &lt;span class="caps"&gt;API&lt;/span&gt;
- &lt;strong&gt;OpenWebUI:&lt;/strong&gt; Chat interface, &lt;span class="caps"&gt;RAG&lt;/span&gt;, multi-user
- &lt;strong&gt;Models:&lt;/strong&gt; Llama 3, Mistral, Gemma, CodeLlama
- &lt;strong&gt;Hardware:&lt;/strong&gt; Runs on &lt;span class="caps"&gt;NVIDIA&lt;/span&gt;, &lt;span class="caps"&gt;AMD&lt;/span&gt;, Apple Silicon, or &lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;
- Private &lt;span class="caps"&gt;AI&lt;/span&gt; conversations (no data sent to OpenAI)
- Custom model fine-tuning and &lt;span class="caps"&gt;RAG&lt;/span&gt; pipelines
- &lt;span class="caps"&gt;API&lt;/span&gt;-compatible with OpenAI for app&amp;nbsp;integration&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;
- Large models require 16+ &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;VRAM&lt;/span&gt;
- Slower than cloud APIs for complex&amp;nbsp;reasoning&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Privacy-conscious users and developers wanting local &lt;span class="caps"&gt;AI&lt;/span&gt;&amp;nbsp;APIs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt;&amp;nbsp;Free.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;9. Reverse Proxy:&amp;nbsp;Traefik&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Why it made the list:&lt;/strong&gt; Traefik is a cloud-native reverse proxy that automatically discovers Docker containers and provisions Let&amp;#8217;s Encrypt&amp;nbsp;certificates.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Specifications:&lt;/strong&gt;
- &lt;strong&gt;Platform:&lt;/strong&gt; Docker, Kubernetes, binary
- &lt;strong&gt;Discovery:&lt;/strong&gt; Docker labels, Consul, etcd
- &lt;strong&gt;&lt;span class="caps"&gt;TLS&lt;/span&gt;:&lt;/strong&gt; Let&amp;#8217;s Encrypt, custom certs, automatic &lt;span class="caps"&gt;HTTP&lt;/span&gt;→&lt;span class="caps"&gt;HTTPS&lt;/span&gt; redirect
- &lt;strong&gt;Middleware:&lt;/strong&gt; Basic auth, rate limiting, &lt;span class="caps"&gt;IP&lt;/span&gt;&amp;nbsp;whitelisting&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;
- Zero-config service discovery
- Native Docker integration
- Modern, active&amp;nbsp;development&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;
- Configuration can be verbose for complex rules
- Documentation assumes Kubernetes&amp;nbsp;familiarity&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Docker-based homelabs needing automatic &lt;span class="caps"&gt;HTTPS&lt;/span&gt; and&amp;nbsp;routing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt;&amp;nbsp;Free.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;10. Backup: Restic +&amp;nbsp;rclone&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Why it made the list:&lt;/strong&gt; Restic is a fast, encrypted, deduplicated backup tool. rclone syncs to any cloud storage. Together, they provide a 3-2-1 backup&amp;nbsp;strategy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Specifications:&lt;/strong&gt;
- &lt;strong&gt;Restic:&lt;/strong&gt; Deduplication, encryption, snapshots, prune
- &lt;strong&gt;rclone:&lt;/strong&gt; S3, B2, Google Drive, &lt;span class="caps"&gt;SFTP&lt;/span&gt;, 70+ backends
- &lt;strong&gt;Integration:&lt;/strong&gt; Cron, systemd timers, Docker
- &lt;strong&gt;Verification:&lt;/strong&gt; Built-in restore&amp;nbsp;testing&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;
- Incremental backups with deduplication
- Client-side encryption
- Supports any cloud or local&amp;nbsp;target&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;
- Command-line only (no web &lt;span class="caps"&gt;UI&lt;/span&gt;)
- Requires scripting for&amp;nbsp;automation&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Users who want reliable, encrypted, verifiable backups without vendor&amp;nbsp;lock-in.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt;&amp;nbsp;Free.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Comparison&amp;nbsp;Matrix&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Ease of Use&lt;/th&gt;
&lt;th&gt;Resource Use&lt;/th&gt;
&lt;th&gt;Mobile App&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;AI&lt;/span&gt; Features&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Nextcloud&lt;/td&gt;
&lt;td&gt;Cloud Storage&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Immich&lt;/td&gt;
&lt;td&gt;Photos&lt;/td&gt;
&lt;td&gt;Easy&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Excellent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Jellyfin&lt;/td&gt;
&lt;td&gt;Media&lt;/td&gt;
&lt;td&gt;Easy&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vaultwarden&lt;/td&gt;
&lt;td&gt;Passwords&lt;/td&gt;
&lt;td&gt;Easy&lt;/td&gt;
&lt;td&gt;Very Low&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pi-hole&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt;/Ad Block&lt;/td&gt;
&lt;td&gt;Easy&lt;/td&gt;
&lt;td&gt;Very Low&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Grafana Stack&lt;/td&gt;
&lt;td&gt;Monitoring&lt;/td&gt;
&lt;td&gt;Hard&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WireGuard/Tailscale&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;VPN&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Easy&lt;/td&gt;
&lt;td&gt;Very Low&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ollama + OpenWebUI&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;AI&lt;/span&gt;/&lt;span class="caps"&gt;LLM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Very High&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Traefik&lt;/td&gt;
&lt;td&gt;Reverse Proxy&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Restic + rclone&lt;/td&gt;
&lt;td&gt;Backup&lt;/td&gt;
&lt;td&gt;Hard&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Frequently Asked&amp;nbsp;Questions&lt;/h2&gt;
&lt;h3&gt;Can I run all of these on one&amp;nbsp;server?&lt;/h3&gt;
&lt;p&gt;Yes, on a 4-core, 16 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; mini &lt;span class="caps"&gt;PC&lt;/span&gt;. Use Docker Compose to manage the stack. For Ollama, add a dedicated &lt;span class="caps"&gt;GPU&lt;/span&gt; or run it on a separate&amp;nbsp;machine.&lt;/p&gt;
&lt;h3&gt;Which should I deploy&amp;nbsp;first?&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Pi-hole (network&amp;nbsp;foundation)&lt;/li&gt;
&lt;li&gt;Vaultwarden&amp;nbsp;(security)&lt;/li&gt;
&lt;li&gt;Nextcloud or Immich (data&amp;nbsp;storage)&lt;/li&gt;
&lt;li&gt;Traefik (&lt;span class="caps"&gt;HTTPS&lt;/span&gt;&amp;nbsp;access)&lt;/li&gt;
&lt;li&gt;Grafana stack&amp;nbsp;(monitoring)&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Are these truly&amp;nbsp;free?&lt;/h3&gt;
&lt;p&gt;All listed tools are open-source and free to use. Some offer optional paid support or hosted versions. There are no subscription traps or feature&amp;nbsp;gates.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;The 2026 self-hosted ecosystem offers polished, mature alternatives to every major cloud service. From Nextcloud&amp;#8217;s unified cloud to Immich&amp;#8217;s &lt;span class="caps"&gt;AI&lt;/span&gt;-powered photos, from Jellyfin&amp;#8217;s free media streaming to Ollama&amp;#8217;s local LLMs, the tools are ready for mainstream adoption. The common thread: your data, your hardware, your&amp;nbsp;control.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Start with Pi-hole and Vaultwarden (low risk, high&amp;nbsp;impact)&lt;/li&gt;
&lt;li&gt;Add Nextcloud or Immich for data&amp;nbsp;storage&lt;/li&gt;
&lt;li&gt;Deploy Traefik for secure remote&amp;nbsp;access&lt;/li&gt;
&lt;li&gt;Experiment with Ollama for private &lt;span class="caps"&gt;AI&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;installation&lt;/strong&gt;: hardware — Mini PCs, &lt;span class="caps"&gt;NAS&lt;/span&gt; devices, &lt;span class="caps"&gt;NVIDIA&lt;/span&gt; GPUs,&amp;nbsp;SSDs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;integration&lt;/strong&gt;: tool — &lt;span class="caps"&gt;VPS&lt;/span&gt; providers, cloud storage (Wasabi,&amp;nbsp;B2)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;alternatives&lt;/strong&gt;: tool — Proxmox,&amp;nbsp;TrueNAS&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;cloud-storage&lt;/code&gt; → setup_guide: &lt;a href="https://steadypub.com/2026/06/nextcloud-docker-compose/"&gt;Nextcloud Docker&amp;nbsp;setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;photos&lt;/code&gt; → setup_guide: &lt;a href="https://steadypub.com/2026/06/immich-photo-server/"&gt;Immich photo server&amp;nbsp;guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;media&lt;/code&gt; → setup_guide: &lt;a href="https://steadypub.com/2026/06/self-hosted-media-server-setup/"&gt;Self-hosted media&amp;nbsp;server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;passwords&lt;/code&gt; → setup_guide: &lt;a href="https://steadypub.com/2026/06/self-hosted-password-manager-comparison/"&gt;Self-hosted password manager&amp;nbsp;comparison&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] What self-hosted software is in your stack? Share your top&amp;nbsp;3.&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for weekly self-hosted app reviews and deployment&amp;nbsp;guides.&lt;/li&gt;
&lt;li&gt;[internal_link] Next: &lt;a href="https://steadypub.com/2026/06/nextcloud-docker-compose/"&gt;deploy Nextcloud with Docker&amp;nbsp;Compose&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Tool Guides"/><category term="self-hosted"/><category term="software"/><category term="homelab"/><category term="privacy"/><category term="2026"/><category term="apps"/></entry><entry><title>Broadcom VMware Pricing Shock: Why Homelabbers Are Fleeing to Proxmox</title><link href="https://steadypub.com/2026/06/broadcom-vmware-pricing-homelab/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T10:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/broadcom-vmware-pricing-homelab/</id><summary type="html">&lt;p&gt;Broadcom&amp;#8217;s acquisition of VMware killed the free ESXi hypervisor and raised enterprise prices by 300-1200%. Learn why homelabbers are migrating to Proxmox and how to make the&amp;nbsp;switch.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~15 minutes&lt;br&gt;
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab builders, &lt;span class="caps"&gt;IT&lt;/span&gt; professionals, self-hosting&amp;nbsp;enthusiasts&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The Broadcom Acquisition: What&amp;nbsp;Changed&lt;/h2&gt;
&lt;h3&gt;November 2023: The Deal&amp;nbsp;Closes&lt;/h3&gt;
&lt;p&gt;Broadcom completed its $61 billion acquisition of VMware on November 22, 2023. Within months, the company announced sweeping changes to VMware&amp;#8217;s product portfolio, licensing model, and pricing structure. For homelabbers who relied on VMware ESXi free edition, the impact was immediate and&amp;nbsp;devastating.&lt;/p&gt;
&lt;h3&gt;The Death of Free&amp;nbsp;ESXi&lt;/h3&gt;
&lt;p&gt;On December 13, 2023, Broadcom announced the &lt;strong&gt;end of VMware vSphere Hypervisor (ESXi) free edition&lt;/strong&gt;. The free version — which had been a staple of homelab environments for over a decade — was discontinued with no direct replacement. Key changes&amp;nbsp;included:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Free ESXi eliminated:&lt;/strong&gt; No new downloads, no new&amp;nbsp;licenses&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;VMware Workstation/Fusion sold:&lt;/strong&gt; Bought by KeySight, creating&amp;nbsp;uncertainty&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Product bundling:&lt;/strong&gt; Former à-la-carte products forced into expensive&amp;nbsp;bundles&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Partner program overhaul:&lt;/strong&gt; Thousands of VMware partners lost their&amp;nbsp;status&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Enterprise Price&amp;nbsp;Increases&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Product&lt;/th&gt;
&lt;th&gt;Pre-Broadcom Price&lt;/th&gt;
&lt;th&gt;Post-Broadcom Price&lt;/th&gt;
&lt;th&gt;Increase&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;vSphere Foundation (per &lt;span class="caps"&gt;CPU&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;~$1,200&lt;/td&gt;
&lt;td&gt;~$4,500&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;275%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;vSphere Essentials Kit&lt;/td&gt;
&lt;td&gt;~$576/year&lt;/td&gt;
&lt;td&gt;~$7,500/year&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1200%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;vCenter Server Std&lt;/td&gt;
&lt;td&gt;~$8,000&lt;/td&gt;
&lt;td&gt;~$35,000&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;340%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;vSAN (per &lt;span class="caps"&gt;CPU&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;~$2,500&lt;/td&gt;
&lt;td&gt;Bundled only&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;NSX&lt;/span&gt; (per &lt;span class="caps"&gt;CPU&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;~$2,000&lt;/td&gt;
&lt;td&gt;Bundled only&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;em&gt;Sources: Broadcom VMware pricing announcements, Reddit r/homelab community reports, The Register&amp;nbsp;reporting&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why It Matters for&amp;nbsp;Homelabbers&lt;/h2&gt;
&lt;h3&gt;The ESXi Free Edition Was the Gateway&amp;nbsp;Drug&lt;/h3&gt;
&lt;p&gt;For thousands of &lt;span class="caps"&gt;IT&lt;/span&gt; professionals, VMware ESXi free was the entry point into virtualization. It&amp;nbsp;offered:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Full hypervisor functionality&lt;/strong&gt; (with the 8-vCPU&amp;nbsp;limit)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;VMware vSphere Client&lt;/strong&gt; for&amp;nbsp;management&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;VMware Tools&lt;/strong&gt; for guest&amp;nbsp;optimization&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hardware compatibility list (&lt;span class="caps"&gt;HCL&lt;/span&gt;)&lt;/strong&gt; for reliable&amp;nbsp;builds&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Without a free tier, the barrier to entry for learning enterprise virtualization&amp;nbsp;skyrocketed.&lt;/p&gt;
&lt;h3&gt;The Homelab Community&amp;nbsp;Exodus&lt;/h3&gt;
&lt;p&gt;Reddit r/homelab and r/vmware saw a massive spike in migration posts during Q1 2024. Common&amp;nbsp;themes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;What do I use instead of ESXi?&amp;#8221;&lt;/strong&gt; — 15+ daily posts at&amp;nbsp;peak&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;Proxmox vs &lt;span class="caps"&gt;XCP&lt;/span&gt;-ng?&amp;#8221;&lt;/strong&gt; — The new default&amp;nbsp;debate&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;How do I migrate my VMs?&amp;#8221;&lt;/strong&gt; — Technical how-to&amp;nbsp;demand&lt;/li&gt;
&lt;/ul&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Quarter&lt;/th&gt;
&lt;th&gt;r/homelab &amp;#8220;Proxmox&amp;#8221; Mentions&lt;/th&gt;
&lt;th&gt;r/homelab &amp;#8220;ESXi&amp;#8221; Mentions&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Q3 2023&lt;/td&gt;
&lt;td&gt;~200/month&lt;/td&gt;
&lt;td&gt;~400/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Q1 2024&lt;/td&gt;
&lt;td&gt;~1,200/month&lt;/td&gt;
&lt;td&gt;~600/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Q3 2024&lt;/td&gt;
&lt;td&gt;~2,000/month&lt;/td&gt;
&lt;td&gt;~300/month&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;em&gt;Estimates based on Reddit search trends and community&amp;nbsp;observation&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Proxmox: The Default&amp;nbsp;Alternative&lt;/h2&gt;
&lt;h3&gt;What Is Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;?&lt;/h3&gt;
&lt;p&gt;Proxmox Virtual Environment (&lt;span class="caps"&gt;VE&lt;/span&gt;) is an open-source server virtualization management platform. It&amp;nbsp;combines:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;KVM&lt;/span&gt; hypervisor&lt;/strong&gt; for full&amp;nbsp;virtualization&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;LXC&lt;/span&gt; containers&lt;/strong&gt; for lightweight &lt;span class="caps"&gt;OS&lt;/span&gt;-level&amp;nbsp;virtualization&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Web-based management&lt;/strong&gt; — no separate client&amp;nbsp;needed&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;ZFS&lt;/span&gt; support&lt;/strong&gt;&amp;nbsp;built-in&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ceph integration&lt;/strong&gt; for distributed&amp;nbsp;storage&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Clustering&lt;/strong&gt; up to 32 nodes&amp;nbsp;(free)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Why Proxmox Won the Homelab&amp;nbsp;Market&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Factor&lt;/th&gt;
&lt;th&gt;Proxmox&lt;/th&gt;
&lt;th&gt;ESXi Free (&lt;span class="caps"&gt;RIP&lt;/span&gt;)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Free (subscription optional)&lt;/td&gt;
&lt;td&gt;$0 (discontinued)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Web &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Built-in, responsive&lt;/td&gt;
&lt;td&gt;vSphere Client required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Containers&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;LXC&lt;/span&gt; native&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;ZFS&lt;/span&gt;, Ceph, &lt;span class="caps"&gt;LVM&lt;/span&gt;, &lt;span class="caps"&gt;NFS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;VMFS&lt;/span&gt;, &lt;span class="caps"&gt;NFS&lt;/span&gt;, iSCSI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Backup&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Built-in (vzdump)&lt;/td&gt;
&lt;td&gt;N/A (free)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;API&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;REST&lt;/span&gt; &lt;span class="caps"&gt;API&lt;/span&gt; (full)&lt;/td&gt;
&lt;td&gt;Limited (free)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Community&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Very active, open-source&lt;/td&gt;
&lt;td&gt;Corporate, shrinking&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Proxmox Subscription Pricing (For&amp;nbsp;Context)&lt;/h3&gt;
&lt;p&gt;Even Proxmox&amp;#8217;s paid tiers are dramatically cheaper than&amp;nbsp;VMware:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Subscription&lt;/th&gt;
&lt;th&gt;CPUs&lt;/th&gt;
&lt;th&gt;Price/Year&lt;/th&gt;
&lt;th&gt;Support&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Community (free)&lt;/td&gt;
&lt;td&gt;Unlimited&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;td&gt;Forums only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Basic&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;~$95&lt;/td&gt;
&lt;td&gt;Business hours&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Standard&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;~$190&lt;/td&gt;
&lt;td&gt;24/7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Premium&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;~$380&lt;/td&gt;
&lt;td&gt;24/7 + phone&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;em&gt;Compare to VMware vSphere Foundation at ~$4,500/&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Migration Path: ESXi to&amp;nbsp;Proxmox&lt;/h2&gt;
&lt;h3&gt;Step 1: Inventory Your&amp;nbsp;VMs&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# On ESXi host, list all VMs&lt;/span&gt;
vim-cmd&lt;span class="w"&gt; &lt;/span&gt;vmsvc/getallvms

&lt;span class="c1"&gt;# Export VM configuration for documentation&lt;/span&gt;
vim-cmd&lt;span class="w"&gt; &lt;/span&gt;vmsvc/getallvms&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/tmp/vm-inventory.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Step 2: Export &lt;span class="caps"&gt;VM&lt;/span&gt; Disk&amp;nbsp;Images&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Export each VM&amp;#39;s disk to OVF/OVA format&lt;/span&gt;
&lt;span class="c1"&gt;# Use VMware vSphere Client or ovftool&lt;/span&gt;
ovftool&lt;span class="w"&gt; &lt;/span&gt;vi://root@esxi-host.local/VM_Name&lt;span class="w"&gt; &lt;/span&gt;/tmp/VM_Name.ova
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Step 3: Import to&amp;nbsp;Proxmox&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# On Proxmox host, import the OVA&lt;/span&gt;
qm&lt;span class="w"&gt; &lt;/span&gt;importovf&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/tmp/VM_Name.ova&lt;span class="w"&gt; &lt;/span&gt;local-lvm

&lt;span class="c1"&gt;# Or import raw disk images&lt;/span&gt;
qm&lt;span class="w"&gt; &lt;/span&gt;importdisk&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/tmp/VM_Name-disk1.vmdk&lt;span class="w"&gt; &lt;/span&gt;local-lvm&lt;span class="w"&gt; &lt;/span&gt;--format&lt;span class="w"&gt; &lt;/span&gt;qcow2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Step 4: Reconfigure&amp;nbsp;Networking&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Proxmox uses Linux bridges (vmbr0, vmbr1, etc.)&lt;/span&gt;
&lt;span class="c1"&gt;# Map your ESXi port groups to Proxmox bridges&lt;/span&gt;

&lt;span class="c1"&gt;# Example /etc/network/interfaces snippet&lt;/span&gt;
auto&lt;span class="w"&gt; &lt;/span&gt;vmbr0
iface&lt;span class="w"&gt; &lt;/span&gt;vmbr0&lt;span class="w"&gt; &lt;/span&gt;inet&lt;span class="w"&gt; &lt;/span&gt;static
&lt;span class="w"&gt;    &lt;/span&gt;address&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.1.10/24
&lt;span class="w"&gt;    &lt;/span&gt;gateway&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.1.1
&lt;span class="w"&gt;    &lt;/span&gt;bridge-ports&lt;span class="w"&gt; &lt;/span&gt;enp1s0
&lt;span class="w"&gt;    &lt;/span&gt;bridge-stp&lt;span class="w"&gt; &lt;/span&gt;off
&lt;span class="w"&gt;    &lt;/span&gt;bridge-fd&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Step 5: Install Guest&amp;nbsp;Agents&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# For Linux VMs&lt;/span&gt;
apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;qemu-guest-agent
systemctl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;qemu-guest-agent

&lt;span class="c1"&gt;# For Windows VMs&lt;/span&gt;
&lt;span class="c1"&gt;# Download virtio-win ISO, install QEMU Guest Agent&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Other ESXi Alternatives Worth&amp;nbsp;Considering&lt;/h2&gt;
&lt;h3&gt;&lt;span class="caps"&gt;XCP&lt;/span&gt;-ng + Xen&amp;nbsp;Orchestra&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Enterprise-grade, Xen heritage, commercial support&amp;nbsp;available&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cons:&lt;/strong&gt; Smaller community than Proxmox, steeper learning&amp;nbsp;curve&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Users who need Citrix XenApp/XenDesktop&amp;nbsp;compatibility&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;TrueNAS &lt;span class="caps"&gt;SCALE&lt;/span&gt;&amp;nbsp;(Virtualization)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pros:&lt;/strong&gt; &lt;span class="caps"&gt;ZFS&lt;/span&gt; storage + &lt;span class="caps"&gt;KVM&lt;/span&gt; in one platform, excellent &lt;span class="caps"&gt;NAS&lt;/span&gt;&amp;nbsp;features&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cons:&lt;/strong&gt; Newer virtualization stack, less mature than&amp;nbsp;Proxmox&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Storage-first homelabs wanting light&amp;nbsp;virtualization&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Hyper-V&amp;nbsp;(Windows)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Free with Windows Server, PowerShell automation, &lt;span class="caps"&gt;RDP&lt;/span&gt;&amp;nbsp;integration&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cons:&lt;/strong&gt; Windows-only, less container support, licensing&amp;nbsp;complexity&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Windows-centric&amp;nbsp;environments&lt;/li&gt;
&lt;/ul&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Alternative&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;Learning Curve&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;KVM&lt;/span&gt; + &lt;span class="caps"&gt;LXC&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;General homelab&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;XCP&lt;/span&gt;-ng&lt;/td&gt;
&lt;td&gt;Xen&lt;/td&gt;
&lt;td&gt;Enterprise features&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TrueNAS &lt;span class="caps"&gt;SCALE&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;KVM&lt;/span&gt; + &lt;span class="caps"&gt;ZFS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Storage-first&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hyper-V&lt;/td&gt;
&lt;td&gt;Type-1&lt;/td&gt;
&lt;td&gt;Windows shops&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ESXi (paid)&lt;/td&gt;
&lt;td&gt;Type-1&lt;/td&gt;
&lt;td&gt;Corporate compliance&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Common Migration&amp;nbsp;Mistakes&lt;/h2&gt;
&lt;h3&gt;Mistake 1: Trying to Run ESXi Without&amp;nbsp;Updates&lt;/h3&gt;
&lt;p&gt;ESXi free is dead. Running unpatched ESXi is a &lt;strong&gt;security risk&lt;/strong&gt;. Broadcom no longer releases free security patches. Migrate &lt;span class="caps"&gt;ASAP&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;Mistake 2: Ignoring Hardware&amp;nbsp;Compatibility&lt;/h3&gt;
&lt;p&gt;Proxmox has broader hardware support than VMware (no &lt;span class="caps"&gt;HCL&lt;/span&gt; required), but:
- &lt;strong&gt;NICs:&lt;/strong&gt; Intel i210/i225/i226 work best. Realtek NICs need extra drivers.
- &lt;strong&gt;Storage controllers:&lt;/strong&gt; &lt;span class="caps"&gt;LSI&lt;/span&gt;/Broadcom &lt;span class="caps"&gt;HBA&lt;/span&gt; cards (9211, 9300 series) are ideal.
- &lt;strong&gt;&lt;span class="caps"&gt;GPU&lt;/span&gt; passthrough:&lt;/strong&gt; Intel integrated graphics work well; &lt;span class="caps"&gt;NVIDIA&lt;/span&gt; requires extra&amp;nbsp;steps.&lt;/p&gt;
&lt;h3&gt;Mistake 3: Overlooking Backup&amp;nbsp;Strategy&lt;/h3&gt;
&lt;p&gt;Proxmox&amp;#8217;s built-in vzdump is excellent. Set it up&amp;nbsp;immediately:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Enable Proxmox Backup Server or local backups&lt;/span&gt;
&lt;span class="c1"&gt;# In Proxmox Web UI: Datacenter &amp;gt; Backup &amp;gt; Add&lt;/span&gt;

&lt;span class="c1"&gt;# Or use CLI:&lt;/span&gt;
vzdump&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--mode&lt;span class="w"&gt; &lt;/span&gt;snapshot&lt;span class="w"&gt; &lt;/span&gt;--compress&lt;span class="w"&gt; &lt;/span&gt;zstd&lt;span class="w"&gt; &lt;/span&gt;--storage&lt;span class="w"&gt; &lt;/span&gt;local-backup
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Broadcom&amp;#8217;s VMware acquisition destroyed the free ESXi ecosystem, raised enterprise prices by 300-1200%, and triggered the largest homelab migration in recent history. Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; has emerged as the default replacement, offering comparable functionality at zero cost with a vibrant open-source&amp;nbsp;community.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Inventory your ESXi VMs&lt;/strong&gt; and export disk&amp;nbsp;images&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Install Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;&lt;/strong&gt; on a spare machine or &lt;span class="caps"&gt;VM&lt;/span&gt; to&amp;nbsp;test&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Join the r/homelab and r/Proxmox communities&lt;/strong&gt; for migration&amp;nbsp;support&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Read our Proxmox beginner guide&lt;/strong&gt; for a complete setup&amp;nbsp;walkthrough&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mini PCs for Proxmox:&lt;/strong&gt; Minisforum &lt;span class="caps"&gt;MS&lt;/span&gt;-01, Beelink &lt;span class="caps"&gt;SER7&lt;/span&gt;, Intel &lt;span class="caps"&gt;NUC&lt;/span&gt; 13&amp;nbsp;Pro&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Storage HBAs:&lt;/strong&gt; &lt;span class="caps"&gt;LSI&lt;/span&gt; 9211-8i (&lt;span class="caps"&gt;IT&lt;/span&gt; mode), Broadcom&amp;nbsp;9300-8i&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Networking:&lt;/strong&gt; Intel i225/i226 NICs, 10GbE &lt;span class="caps"&gt;SFP&lt;/span&gt;+ &lt;span class="caps"&gt;DAC&lt;/span&gt;&amp;nbsp;cables&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;UPS&lt;/span&gt;:&lt;/strong&gt; &lt;span class="caps"&gt;APC&lt;/span&gt; Back-&lt;span class="caps"&gt;UPS&lt;/span&gt; Pro, CyberPower &lt;span class="caps"&gt;CP1500&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;proxmox-migration&lt;/code&gt; → &lt;code&gt;proxmox-beginner-guide.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hardware&lt;/code&gt; → &lt;code&gt;best-mini-pc-for-homelab.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;networking&lt;/code&gt; → &lt;code&gt;homelab-networking-basics.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;backup&lt;/code&gt; → &lt;code&gt;proxmox-backup-server-guide.md&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;What&amp;#8217;s your ESXi migration story?&lt;/strong&gt; Share your experience in the comments&amp;nbsp;below.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subscribe&lt;/strong&gt; to our newsletter for more self-hosting migration guides and homelab&amp;nbsp;tips.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Concepts"/><category term="broadcom vmware pricing homelab"/><category term="proxmox migration"/><category term="vmware esxi free alternative"/><category term="self-hosted virtualization"/><category term="homelab"/></entry><entry><title>Docker Compose Tutorial for Homelab: From Zero to Production Stacks</title><link href="https://steadypub.com/2026/06/docker-compose-tutorial/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T10:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/docker-compose-tutorial/</id><summary type="html">&lt;p&gt;Learn Docker Compose from scratch with a hands-on homelab tutorial. Covers syntax, networking, volumes, environment variables, and real-world stack&amp;nbsp;examples.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~18 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab and self-hosting&amp;nbsp;enthusiasts&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is Docker&amp;nbsp;Compose?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Docker Compose is a declarative tool for defining and running multi-container Docker applications. Instead of typing&amp;nbsp;long &lt;code&gt;docker run&lt;/code&gt; commands for each container, you write a &lt;span class="caps"&gt;YAML&lt;/span&gt; file that describes your entire application stack — services, networks, volumes, and environment variables. A single command&amp;nbsp;(&lt;code&gt;docker compose up -d&lt;/code&gt;) creates everything. This makes your infrastructure reproducible, version-controlled, and easy to&amp;nbsp;share.&lt;/p&gt;
&lt;h3&gt;Why It Matters for&amp;nbsp;Homelabs&lt;/h3&gt;
&lt;p&gt;Most homelab applications require multiple containers: a web app, a database, a cache, and a reverse proxy. Managing these with raw Docker commands is error-prone. Compose turns this into a single file that you can store in Git, deploy on any machine, and update with&amp;nbsp;confidence.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why Learn Docker&amp;nbsp;Compose?&lt;/h2&gt;
&lt;h3&gt;Declarative&amp;nbsp;Infrastructure&lt;/h3&gt;
&lt;p&gt;Your entire stack is defined in code. If your server dies, you can clone the repo,&amp;nbsp;run &lt;code&gt;docker compose up&lt;/code&gt;, and be back online in minutes. This is the foundation of modern infrastructure as&amp;nbsp;code.&lt;/p&gt;
&lt;h3&gt;Easy Updates and&amp;nbsp;Rollbacks&lt;/h3&gt;
&lt;p&gt;Update a service by changing the image tag in the Compose file and&amp;nbsp;running &lt;code&gt;docker compose up -d&lt;/code&gt;. If something breaks, revert the tag and redeploy. The old container is recreated&amp;nbsp;automatically.&lt;/p&gt;
&lt;h3&gt;Service Discovery and&amp;nbsp;Networking&lt;/h3&gt;
&lt;p&gt;Compose automatically creates a private network for your stack. Containers can reach each other by service name&amp;nbsp;(e.g., &lt;code&gt;http://db:5432&lt;/code&gt;). No manual &lt;span class="caps"&gt;IP&lt;/span&gt; management or port mapping required for internal&amp;nbsp;communication.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;h3&gt;Hardware&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Any Linux machine (mini &lt;span class="caps"&gt;PC&lt;/span&gt;, old laptop, &lt;span class="caps"&gt;VPS&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;2 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; minimum, 4 &lt;span class="caps"&gt;GB&lt;/span&gt;&amp;nbsp;recommended&lt;/li&gt;
&lt;li&gt;20 &lt;span class="caps"&gt;GB&lt;/span&gt;&amp;nbsp;storage&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Software&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Docker Engine&amp;nbsp;20.10+&lt;/li&gt;
&lt;li&gt;Docker Compose plugin&amp;nbsp;v2.x&lt;/li&gt;
&lt;li&gt;A text editor (nano, vim, or &lt;span class="caps"&gt;VS&lt;/span&gt;&amp;nbsp;Code)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Knowledge&amp;nbsp;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Basic Linux command&amp;nbsp;line&lt;/li&gt;
&lt;li&gt;Understanding of Docker images and&amp;nbsp;containers&lt;/li&gt;
&lt;li&gt;Familiarity with &lt;span class="caps"&gt;YAML&lt;/span&gt; indentation (spaces, not&amp;nbsp;tabs)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Install Docker&amp;nbsp;Compose&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Ensure the Docker Compose plugin is installed and&amp;nbsp;working.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Verify Docker Compose is installed&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;version
&lt;span class="c1"&gt;# Expected: Docker Compose version v2.x.x&lt;/span&gt;

&lt;span class="c1"&gt;# If missing, install it (Ubuntu/Debian)&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;update
sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;docker-compose-plugin

&lt;span class="c1"&gt;# Verify again&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;version
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you still have the&amp;nbsp;legacy &lt;code&gt;docker-compose&lt;/code&gt; (Python) binary, migrate to the plugin. The plugin is faster and supports the latest&amp;nbsp;features.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 2: Write Your First Compose&amp;nbsp;File&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Create a simple stack with an Nginx web&amp;nbsp;server.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;p&gt;Create a project&amp;nbsp;directory:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;~/homelab-tutorial&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/homelab-tutorial
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Create &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;web&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nginx:alpine&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;my-nginx&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8080:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./html:/usr/share/nginx/html:ro&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Create a simple &lt;span class="caps"&gt;HTML&lt;/span&gt;&amp;nbsp;file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;html
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;lt;h1&amp;gt;Hello from Docker Compose!&amp;lt;/h1&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;html/index.html
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Deploy:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Verify:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;curl&lt;span class="w"&gt; &lt;/span&gt;http://localhost:8080
&lt;span class="c1"&gt;# Output: &amp;lt;h1&amp;gt;Hello from Docker Compose!&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 3: Add a Database and Connect&amp;nbsp;Services&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Extend the stack with a MariaDB database and demonstrate service&amp;nbsp;discovery.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;p&gt;Update &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;web&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nginx:alpine&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;my-nginx&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8080:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./html:/usr/share/nginx/html:ro&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;db&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;mariadb:10.6&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;my-mariadb&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_ROOT_PASSWORD=secret_root_pass&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_DATABASE=myapp&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_USER=myapp&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_PASSWORD=secret_app_pass&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;db_data:/var/lib/mysql&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;db_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Key observations:
-&amp;nbsp;The &lt;code&gt;web&lt;/code&gt; service can reach the database&amp;nbsp;at &lt;code&gt;db:3306&lt;/code&gt; (service name becomes hostname)&amp;nbsp;- &lt;code&gt;depends_on&lt;/code&gt; ensures &lt;code&gt;db&lt;/code&gt; starts&amp;nbsp;before &lt;code&gt;web&lt;/code&gt;, but does not wait for it to be ready&amp;nbsp;- &lt;code&gt;db_data&lt;/code&gt; is a named volume managed by Docker; data persists across container&amp;nbsp;recreations&lt;/p&gt;
&lt;p&gt;Deploy the updated&amp;nbsp;stack:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 4: Use Environment Variables and&amp;nbsp;Secrets&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Externalize configuration with&amp;nbsp;a &lt;code&gt;.env&lt;/code&gt; file.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;p&gt;Create &lt;code&gt;.env&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;MYSQL_ROOT_PASSWORD=super_secret_root
MYSQL_DATABASE=myapp
MYSQL_USER=myapp
MYSQL_PASSWORD=super_secret_app
NGINX_PORT=8080
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Update &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;web&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nginx:alpine&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;my-nginx&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${NGINX_PORT}:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./html:/usr/share/nginx/html:ro&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;db&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;mariadb:10.6&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;my-mariadb&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_DATABASE=${MYSQL_DATABASE}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_USER=${MYSQL_USER}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_PASSWORD=${MYSQL_PASSWORD}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;db_data:/var/lib/mysql&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;db_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Add &lt;code&gt;.env&lt;/code&gt; to &lt;code&gt;.gitignore&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;.env&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;.gitignore
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 5: Add a Reverse Proxy and Custom&amp;nbsp;Network&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Deploy Traefik as a reverse proxy with automatic &lt;span class="caps"&gt;HTTPS&lt;/span&gt; and a custom bridge&amp;nbsp;network.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;frontend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;bridge&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;backend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;bridge&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;traefik&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;traefik:v3.0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;traefik&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;80:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;443:443&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/var/run/docker.sock:/var/run/docker.sock:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./letsencrypt:/letsencrypt&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--api.dashboard=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--providers.docker=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--providers.docker.exposedbydefault=false&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--entrypoints.web.address=:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--entrypoints.websecure.address=:443&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--certificatesresolvers.letsencrypt.acme.tlschallenge=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--certificatesresolvers.letsencrypt.acme.email=you@example.com&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;frontend&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.enable=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.traefik.rule=Host(`traefik.local`)&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.traefik.service=api@internal&amp;quot;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;web&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nginx:alpine&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;my-nginx&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./html:/usr/share/nginx/html:ro&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;frontend&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;backend&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.enable=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.web.rule=Host(`web.local`)&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.web.tls.certresolver=letsencrypt&amp;quot;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;mariadb:10.6&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;my-mariadb&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_DATABASE=${MYSQL_DATABASE}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_USER=${MYSQL_USER}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_PASSWORD=${MYSQL_PASSWORD}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;db_data:/var/lib/mysql&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;backend&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;db_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Use Profiles for Conditional&amp;nbsp;Services&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;dev-tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;phpmyadmin&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;profiles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Deploy&amp;nbsp;with &lt;code&gt;docker compose --profile dev up -d&lt;/code&gt; to include dev tools only when&amp;nbsp;needed.&lt;/p&gt;
&lt;h3&gt;Tip 2: Health Checks for&amp;nbsp;Reliability&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;mariadb:10.6&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;healthcheck&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;CMD&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;mysqladmin&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ping&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-h&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;localhost&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;10s&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;5s&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;retries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 3: Resource&amp;nbsp;Limits&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;web&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;cpus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;0.5&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;256M&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 4: Override Files for&amp;nbsp;Environments&lt;/h3&gt;
&lt;p&gt;Create &lt;code&gt;docker-compose.override.yml&lt;/code&gt; for local tweaks (not committed to&amp;nbsp;production):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;web&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8080:80&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Troubleshooting Common&amp;nbsp;Issues&lt;/h2&gt;
&lt;h3&gt;Problem 1: &amp;#8220;port is already&amp;nbsp;allocated&amp;#8221;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Find the conflicting process&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;ss&lt;span class="w"&gt; &lt;/span&gt;-tlnp&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;:80

&lt;span class="c1"&gt;# Kill it or change the host port in Compose&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Problem 2: &amp;#8220;Container&amp;nbsp;unhealthy&amp;#8221;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Check the healthcheck definition&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;inspect&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;container&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;jq&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;.[0].State.Health&amp;#39;&lt;/span&gt;

&lt;span class="c1"&gt;# Review logs&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;logs&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;service&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Problem 3: &amp;#8220;Permission denied on&amp;nbsp;volume&amp;#8221;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Check the user running inside the container&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;container&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;id

&lt;span class="c1"&gt;# Fix host permissions&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;chown&lt;span class="w"&gt; &lt;/span&gt;-R&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;:1000&lt;span class="w"&gt; &lt;/span&gt;./data
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Docker Compose is the essential tool for homelab deployment. It transforms complex multi-service applications into readable, version-controlled &lt;span class="caps"&gt;YAML&lt;/span&gt; files. With this tutorial, you learned how to define services, connect them via networks, persist data with volumes, externalize secrets&amp;nbsp;with &lt;code&gt;.env&lt;/code&gt;, and front everything with a reverse&amp;nbsp;proxy.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Version-control your Compose files in&amp;nbsp;Git&lt;/li&gt;
&lt;li&gt;Explore Docker Swarm for multi-node&amp;nbsp;orchestration&lt;/li&gt;
&lt;li&gt;Add health checks and restart policies to all&amp;nbsp;services&lt;/li&gt;
&lt;li&gt;Deploy a full homelab stack (Nextcloud, Pi-hole,&amp;nbsp;monitoring)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;prerequisites&lt;/strong&gt;: hosting — &lt;span class="caps"&gt;VPS&lt;/span&gt; providers for remote Compose&amp;nbsp;stacks&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;step-1&lt;/strong&gt;: tool — Docker Hub subscriptions, JetBrains&amp;nbsp;IDEs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;pro-tips&lt;/strong&gt;: service — Cloudflare for &lt;span class="caps"&gt;DNS&lt;/span&gt; and &lt;span class="caps"&gt;TLS&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;what-is&lt;/code&gt; → related_comparison: &lt;a href="https://steadypub.com/2026/06/docker-compose-vs-podman/"&gt;Docker Compose vs&amp;nbsp;Podman&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prerequisites&lt;/code&gt; → setup_guide: &lt;a href="https://steadypub.com/2026/06/home-server-docker-setup/"&gt;Home server Docker&amp;nbsp;setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → next_steps: &lt;a href="https://steadypub.com/2026/06/docker-compose-yml-examples/"&gt;Docker Compose &lt;span class="caps"&gt;YAML&lt;/span&gt;&amp;nbsp;examples&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] What was your first Docker Compose stack? Share your beginner&amp;nbsp;story.&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for weekly Docker and homelab&amp;nbsp;tutorials.&lt;/li&gt;
&lt;li&gt;[internal_link] Next: explore &lt;a href="https://steadypub.com/2026/06/docker-compose-yml-examples/"&gt;production-ready Compose&amp;nbsp;examples&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Tutorials"/><category term="docker compose"/><category term="tutorial"/><category term="homelab"/><category term="docker"/><category term="self-hosted"/></entry><entry><title>Docker Compose YML Examples for Homelab: A Practical Reference Guide</title><link href="https://steadypub.com/2026/06/docker-compose-yml-examples/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T10:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/docker-compose-yml-examples/</id><summary type="html">&lt;p&gt;A curated collection of production-ready Docker Compose examples for homelab services. Includes Traefik, Nextcloud, monitoring stacks, and security best&amp;nbsp;practices.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~18 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab and self-hosting&amp;nbsp;enthusiasts&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is Docker&amp;nbsp;Compose?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Docker Compose is a tool for defining and running multi-container Docker applications. With a single &lt;span class="caps"&gt;YAML&lt;/span&gt; file, you configure services, networks, and volumes. One command&amp;nbsp;(&lt;code&gt;docker compose up -d&lt;/code&gt;) brings the entire stack online. For homelab operators, Compose is the standard deployment method because it is declarative, version-controlled, and reproducible across&amp;nbsp;machines.&lt;/p&gt;
&lt;h3&gt;Key&amp;nbsp;Concepts&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Services&lt;/strong&gt;: Individual containers&amp;nbsp;(e.g., &lt;code&gt;nginx&lt;/code&gt;, &lt;code&gt;db&lt;/code&gt;, &lt;code&gt;app&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Networks&lt;/strong&gt;: Isolated communication channels between&amp;nbsp;services&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Volumes&lt;/strong&gt;: Persistent storage for container&amp;nbsp;data&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Environment Variables&lt;/strong&gt;: Secrets and configuration passed at&amp;nbsp;runtime&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Profiles&lt;/strong&gt;: Conditional service groups&amp;nbsp;(e.g., &lt;code&gt;dev&lt;/code&gt;, &lt;code&gt;prod&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;h3&gt;Hardware&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Any Linux server with Docker and Docker Compose&amp;nbsp;installed&lt;/li&gt;
&lt;li&gt;At least 2 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; for small stacks, 8 &lt;span class="caps"&gt;GB&lt;/span&gt;+ for full monitoring&amp;nbsp;suites&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Software&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Docker Engine&amp;nbsp;20.10+&lt;/li&gt;
&lt;li&gt;Docker Compose plugin&amp;nbsp;(v2.x)&lt;/li&gt;
&lt;li&gt;A text editor and basic &lt;span class="caps"&gt;YAML&lt;/span&gt; syntax&amp;nbsp;knowledge&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Knowledge&amp;nbsp;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Understanding of Docker images, containers, and&amp;nbsp;ports&lt;/li&gt;
&lt;li&gt;Familiarity with reverse proxies and &lt;span class="caps"&gt;TLS&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Basic Linux file&amp;nbsp;permissions&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Basic Web Application&amp;nbsp;Stack&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Deploy a simple web application with a database and reverse&amp;nbsp;proxy.&lt;/p&gt;
&lt;h3&gt;docker-compose.yml&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;mariadb:10.6&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;app-db&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_ROOT_PASSWORD=***      - MYSQL_DATABASE=app&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_USER=app&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;MYSQL_PASSWORD=***    volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;db_data:/var/lib/mysql&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nginx:alpine&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;app-web&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8080:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./html:/usr/share/nginx/html:ro&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;db&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;db_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Deploy&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;logs&lt;span class="w"&gt; &lt;/span&gt;-f
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 2: Traefik Reverse Proxy with Automatic &lt;span class="caps"&gt;HTTPS&lt;/span&gt;&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Deploy Traefik as a central reverse proxy with Let&amp;#8217;s Encrypt and Docker service&amp;nbsp;discovery.&lt;/p&gt;
&lt;h3&gt;docker-compose.yml&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;traefik&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;traefik:v3.0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;traefik&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--api.dashboard=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--providers.docker=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--providers.docker.exposedbydefault=false&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--entrypoints.web.address=:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--entrypoints.websecure.address=:443&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--certificatesresolvers.letsencrypt.acme.tlschallenge=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--certificatesresolvers.letsencrypt.acme.email=you@example.com&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--entrypoints.web.http.redirections.entrypoint.to=websecure&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--entrypoints.web.http.redirections.entrypoint.scheme=https&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;80:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;443:443&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8080:8080&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/var/run/docker.sock:/var/run/docker.sock:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./letsencrypt:/letsencrypt&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.enable=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.traefik.rule=Host(`traefik.yourdomain.com`)&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.traefik.tls.certresolver=letsencrypt&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.traefik.service=api@internal&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.traefik.middlewares=auth&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.middlewares.auth.basicauth.users=admin:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8C/&amp;quot;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;whoami&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;traefik/whoami&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.enable=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.whoami.rule=Host(`whoami.yourdomain.com`)&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.whoami.tls.certresolver=letsencrypt&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 3: Monitoring Stack (Prometheus +&amp;nbsp;Grafana)&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Deploy a complete monitoring stack with metrics collection, storage, and&amp;nbsp;visualization.&lt;/p&gt;
&lt;h3&gt;docker-compose.yml&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;prometheus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;prom/prometheus:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;prometheus&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;9090:9090&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./prometheus.yml:/etc/prometheus/prometheus.yml:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;prometheus_data:/prometheus&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;grafana&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;grafana/grafana:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;grafana&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3000:3000&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;grafana_data:/var/lib/grafana&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;GF_SECURITY_ADMIN_USER=admin&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;GF_SECURITY_ADMIN_PASSWORD=***&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;node-exporter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;prom/node-exporter:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;node-exporter&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/proc:/host/proc:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/sys:/host/sys:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/:/rootfs:ro&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--path.procfs=/host/proc&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--path.sysfs=/host/sys&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--path.rootfs=/rootfs&amp;#39;&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;prometheus_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;grafana_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;prometheus.yml&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;global&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;scrape_interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;15s&lt;/span&gt;

&lt;span class="nt"&gt;scrape_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;prometheus&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;localhost:9090&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;node&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;node-exporter:9100&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 4: Nextcloud with PostgreSQL and&amp;nbsp;Redis&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Deploy a production-ready Nextcloud stack with a high-performance database and memory&amp;nbsp;caching.&lt;/p&gt;
&lt;h3&gt;docker-compose.yml&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud:apache&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8080:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud:/var/www/html&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;POSTGRES_HOST=db&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;POSTGRES_DB=nextcloud&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;POSTGRES_USER=nextcloud&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;POSTGRES_PASSWORD=***      - NEXTCLOUD_ADMIN_USER=admin&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;NEXTCLOUD_ADMIN_PASSWORD=***      - NEXTCLOUD_TRUSTED_DOMAINS=cloud.yourdomain.com&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;REDIS_HOST=redis&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;db&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;postgres:15-alpine&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud-db&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;db:/var/lib/postgresql/data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;POSTGRES_DB=nextcloud&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;POSTGRES_USER=nextcloud&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;POSTGRES_PASSWORD=***&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis:alpine&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud-redis&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;cron&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud:apache&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud:/var/www/html:ro&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;entrypoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/cron.sh&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;db&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;nextcloud&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 5: Pi-hole with&amp;nbsp;Unbound&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Deploy a network-wide ad blocker with a recursive &lt;span class="caps"&gt;DNS&lt;/span&gt; resolver for maximum&amp;nbsp;privacy.&lt;/p&gt;
&lt;h3&gt;docker-compose.yml&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;pihole&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pihole/pihole:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pihole&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;53:53/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;53:53/udp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;80:80/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TZ=Asia/Singapore&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;WEBPASSWORD=***      - FTLCONF_LOCAL_IPV4=192.168.1.10&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./etc-pihole:/etc/pihole&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./etc-dnsmasq.d:/etc/dnsmasq.d&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;cap_add&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;NET_ADMIN&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;dns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;127.0.0.1&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1.1.1.1&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;unbound&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;mvance/unbound:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unbound&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;5335:53/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;5335:53/udp&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In Pi-hole, set &lt;strong&gt;Custom &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/strong&gt;&amp;nbsp;to &lt;code&gt;127.0.0.1#5335&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Use .env Files for&amp;nbsp;Secrets&lt;/h3&gt;
&lt;p&gt;Never commit secrets to your Compose file. Use&amp;nbsp;a &lt;code&gt;.env&lt;/code&gt; file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;DB_PASSWORD=supersecret
DOMAIN=yourdomain.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And reference variables in&amp;nbsp;Compose:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_PASSWORD=${DB_PASSWORD}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Add &lt;code&gt;.env&lt;/code&gt; to &lt;code&gt;.gitignore&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Tip 2: Health Checks and Restart&amp;nbsp;Policies&lt;/h3&gt;
&lt;p&gt;Add health checks to ensure services recover&amp;nbsp;automatically:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;healthcheck&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;CMD&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;curl&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-f&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://localhost:80&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;30s&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;10s&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;retries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;3&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;start_period&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;40s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 3: Resource&amp;nbsp;Limits&lt;/h3&gt;
&lt;p&gt;Prevent a runaway container from consuming all &lt;span class="caps"&gt;RAM&lt;/span&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;cpus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;1.0&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;512M&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;reservations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;cpus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;0.25&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;128M&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 4: Named Volumes vs Bind&amp;nbsp;Mounts&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Named volumes&lt;/strong&gt;: Managed by Docker, portable, best for&amp;nbsp;databases&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bind mounts&lt;/strong&gt;: Direct host filesystem mapping, best for config files and&amp;nbsp;media&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Troubleshooting Common&amp;nbsp;Issues&lt;/h2&gt;
&lt;h3&gt;Problem 1: Port Already in&amp;nbsp;Use&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Find the process using the port&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;ss&lt;span class="w"&gt; &lt;/span&gt;-tlnp&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;:80

&lt;span class="c1"&gt;# Kill or reconfigure the conflicting service&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Problem 2: Permission Denied on Bind&amp;nbsp;Mounts&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Fix ownership&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;chown&lt;span class="w"&gt; &lt;/span&gt;-R&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;:1000&lt;span class="w"&gt; &lt;/span&gt;./data

&lt;span class="c1"&gt;# Or use Docker user namespaces&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Problem 3: Container Exits&amp;nbsp;Immediately&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Check logs&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;logs&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;service_name&amp;gt;

&lt;span class="c1"&gt;# Inspect the container&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;inspect&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;container_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Docker Compose is the backbone of modern homelab infrastructure. It turns complex multi-service applications into declarative, reproducible configurations. The examples in this guide cover the most common patterns: reverse proxying, monitoring, cloud storage, and &lt;span class="caps"&gt;DNS&lt;/span&gt; filtering. With these templates, you can deploy a full homelab stack in&amp;nbsp;minutes.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Version-control your Compose files in&amp;nbsp;Git&lt;/li&gt;
&lt;li&gt;Add health checks and resource limits to all&amp;nbsp;services&lt;/li&gt;
&lt;li&gt;Configure automated backups for named&amp;nbsp;volumes&lt;/li&gt;
&lt;li&gt;Experiment with Docker Swarm for multi-node&amp;nbsp;orchestration&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;prerequisites&lt;/strong&gt;: hosting — &lt;span class="caps"&gt;VPS&lt;/span&gt; for remote Compose&amp;nbsp;stacks&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;step-1&lt;/strong&gt;: tool — Docker Hub subscriptions, JetBrains&amp;nbsp;IDEs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;pro-tips&lt;/strong&gt;: service — Cloudflare, S3-compatible&amp;nbsp;storage&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;what-is&lt;/code&gt; → related_comparison: &lt;a href="https://steadypub.com/2026/06/docker-compose-vs-podman/"&gt;Docker Compose vs&amp;nbsp;Podman&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prerequisites&lt;/code&gt; → setup_guide: &lt;a href="https://steadypub.com/2026/06/docker-compose-for-beginners/"&gt;Docker Compose for&amp;nbsp;beginners&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → next_steps: &lt;a href="https://steadypub.com/2026/06/portainer-docker-management/"&gt;Portainer Docker management&amp;nbsp;guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] Which Compose stack is your favorite? Share your custom&amp;nbsp;configurations.&lt;/li&gt;
&lt;li&gt;[newsletter] Get weekly Docker and homelab deployment&amp;nbsp;guides.&lt;/li&gt;
&lt;li&gt;[internal_link] Next: learn &lt;a href="https://steadypub.com/2026/06/docker-compose-for-beginners/"&gt;Docker Compose for&amp;nbsp;beginners&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Tutorials"/><category term="docker compose"/><category term="docker"/><category term="homelab"/><category term="yaml"/><category term="examples"/><category term="self-hosted"/></entry><entry><title>Docker Monitoring with Grafana and Prometheus: A Complete Homelab Guide</title><link href="https://steadypub.com/2026/06/docker-monitoring-grafana-prometheus/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T10:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/docker-monitoring-grafana-prometheus/</id><summary type="html">&lt;p&gt;Deploy Prometheus and Grafana to monitor Docker containers, host metrics, and application health. Includes Docker Compose setup, exporters, alerting, and dashboard&amp;nbsp;templates.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~16 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab and self-hosting&amp;nbsp;enthusiasts&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is Prometheus and&amp;nbsp;Grafana?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Prometheus is an open-source monitoring and alerting toolkit designed for reliability and scalability. It scrapes metrics from endpoints (exporters) using &lt;span class="caps"&gt;HTTP&lt;/span&gt; pulls, stores them in a time-series database, and evaluates alerting rules. Grafana is a visualization platform that queries Prometheus (and other data sources) to create dashboards, alerts, and annotations. Together, they form the de facto standard for cloud-native monitoring and are the backbone of most homelab observability&amp;nbsp;stacks.&lt;/p&gt;
&lt;h3&gt;Why Use Them for Docker&amp;nbsp;Monitoring?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Container Awareness&lt;/strong&gt;: cAdvisor exports per-container &lt;span class="caps"&gt;CPU&lt;/span&gt;, memory, network, and filesystem&amp;nbsp;metrics&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Service Discovery&lt;/strong&gt;: Prometheus automatically discovers new containers via Docker&amp;nbsp;labels&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flexible Queries&lt;/strong&gt;: PromQL allows complex aggregations (e.g., &amp;#8220;top 5 containers by memory&amp;nbsp;usage&amp;#8221;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Alerting&lt;/strong&gt;: Alertmanager routes alerts to Slack, Telegram, PagerDuty, or&amp;nbsp;email&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Visual Dashboards&lt;/strong&gt;: Grafana provides pre-built Docker and Node Exporter&amp;nbsp;dashboards&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Why Monitor Your Docker&amp;nbsp;Homelab?&lt;/h2&gt;
&lt;h3&gt;Prevent Resource&amp;nbsp;Exhaustion&lt;/h3&gt;
&lt;p&gt;A runaway container or memory leak can crash the host. Monitoring reveals trends before they become outages. In a homelab, this means your Plex server stays online during a movie&amp;nbsp;night.&lt;/p&gt;
&lt;h3&gt;Capacity&amp;nbsp;Planning&lt;/h3&gt;
&lt;p&gt;Metrics show whether your current hardware is sufficient. If &lt;span class="caps"&gt;CPU&lt;/span&gt; usage is consistently above 80%, it is time to upgrade or consolidate&amp;nbsp;services.&lt;/p&gt;
&lt;h3&gt;Troubleshooting&lt;/h3&gt;
&lt;p&gt;When a service slows down, dashboards reveal whether the bottleneck is &lt;span class="caps"&gt;CPU&lt;/span&gt;, disk I/O, or network latency. This replaces guesswork with&amp;nbsp;data.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;h3&gt;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Docker and Docker&amp;nbsp;Compose&lt;/li&gt;
&lt;li&gt;A Linux server (2+ cores, 4 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;Port 3000 (Grafana), 9090 (Prometheus), and 9093 (Alertmanager)&amp;nbsp;available&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Method 1: Docker Compose&amp;nbsp;(Recommended)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;monitoring&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;bridge&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;prometheus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;prom/prometheus:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;prometheus&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;9090:9090&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./prometheus.yml:/etc/prometheus/prometheus.yml:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;prometheus_data:/prometheus&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--config.file=/etc/prometheus/prometheus.yml&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--storage.tsdb.path=/prometheus&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--web.console.libraries=/etc/prometheus/console_libraries&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--web.console.templates=/etc/prometheus/consoles&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--storage.tsdb.retention.time=30d&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--web.enable-lifecycle&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;monitoring&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;grafana&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;grafana/grafana:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;grafana&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3000:3000&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;grafana_data:/var/lib/grafana&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./grafana/provisioning:/etc/grafana/provisioning&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;GF_SECURITY_ADMIN_USER=admin&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;GF_SECURITY_ADMIN_PASSWORD=***    networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;monitoring&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;node-exporter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;prom/node-exporter:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;node-exporter&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/proc:/host/proc:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/sys:/host/sys:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/:/rootfs:ro&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--path.procfs=/host/proc&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--path.sysfs=/host/sys&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--path.rootfs=/rootfs&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;monitoring&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;cadvisor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;gcr.io/cadvisor/cadvisor:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;cadvisor&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/:/rootfs:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/var/run:/var/run:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/sys:/sys:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/var/lib/docker/:/var/lib/docker:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/dev/disk/:/dev/disk:ro&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;privileged&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;monitoring&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;alertmanager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;prom/alertmanager:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;alertmanager&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;9093:9093&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;alertmanager_data:/alertmanager&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;monitoring&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;prometheus_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;grafana_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;alertmanager_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;prometheus.yml&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;global&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;scrape_interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;15s&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;evaluation_interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;15s&lt;/span&gt;

&lt;span class="nt"&gt;alerting&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;alertmanagers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;alertmanager:9093&lt;/span&gt;

&lt;span class="nt"&gt;rule_files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/etc/prometheus/rules/*.yml&lt;/span&gt;

&lt;span class="nt"&gt;scrape_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;prometheus&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;localhost:9090&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;node-exporter&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;node-exporter:9100&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;cadvisor&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;cadvisor:8080&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;alertmanager.yml&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;global&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;smtp_smarthost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;smtp.gmail.com:587&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;smtp_from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;alerts@example.com&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;smtp_auth_username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;alerts@example.com&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;smtp_auth_password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;***&lt;/span&gt;

&lt;span class="s"&gt;route:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s"&gt;receiver:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;default&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;group_by&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;alertname&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;group_wait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;30s&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;group_interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;5m&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;repeat_interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;4h&lt;/span&gt;

&lt;span class="nt"&gt;receivers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;default&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;email_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;admin@example.com&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;Homelab&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Alert:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;.GroupLabels.alertname&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;|&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="no"&gt;{{ range .Alerts }}&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="no"&gt;Alert: {{ .Annotations.summary }}&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="no"&gt;Description: {{ .Annotations.description }}&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="no"&gt;{{ end }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Deploy:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Basic Setup and&amp;nbsp;Configuration&lt;/h2&gt;
&lt;h3&gt;Step 1: Add Prometheus as a Grafana Data&amp;nbsp;Source&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Open Grafana&amp;nbsp;at &lt;code&gt;http://your-server:3000&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Go to &lt;strong&gt;Connections&lt;/strong&gt; → &lt;strong&gt;Data Sources&lt;/strong&gt; → &lt;strong&gt;Add data&amp;nbsp;source&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Prometheus&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;URL&lt;/span&gt;: &lt;code&gt;http://prometheus:9090&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Save &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;Test&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Step 2: Import Pre-Built&amp;nbsp;Dashboards&lt;/h3&gt;
&lt;p&gt;Grafana&amp;#8217;s dashboard library has thousands of templates. Recommended&amp;nbsp;dashboards:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Node Exporter Full&lt;/strong&gt;: &lt;span class="caps"&gt;ID&lt;/span&gt;&amp;nbsp;1860&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Docker and Host Monitoring&lt;/strong&gt;: &lt;span class="caps"&gt;ID&lt;/span&gt;&amp;nbsp;179&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;cAdvisor Exporter&lt;/strong&gt;: &lt;span class="caps"&gt;ID&lt;/span&gt;&amp;nbsp;14282&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Import via &lt;strong&gt;Dashboards&lt;/strong&gt; → &lt;strong&gt;Import&lt;/strong&gt; → enter the &lt;span class="caps"&gt;ID&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;Step 3: Verify&amp;nbsp;Metrics&lt;/h3&gt;
&lt;p&gt;In Prometheus&amp;nbsp;(&lt;code&gt;http://your-server:9090&lt;/code&gt;), go to &lt;strong&gt;Graph&lt;/strong&gt; and&amp;nbsp;query:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;up
node_cpu_seconds_total
container_cpu_usage_seconds_total
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You should see time-series data.&amp;nbsp;If &lt;code&gt;up&lt;/code&gt; is 0 for a target, check the exporter&amp;#8217;s&amp;nbsp;connectivity.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Advanced&amp;nbsp;Features&lt;/h2&gt;
&lt;h3&gt;Recording&amp;nbsp;Rules&lt;/h3&gt;
&lt;p&gt;Recording rules pre-compute expensive queries.&amp;nbsp;Create &lt;code&gt;/etc/prometheus/rules/rules.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;docker_rules&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;30s&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;record&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;container:memory_usage_bytes:rate5m&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;rate(container_memory_usage_bytes[5m])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Alert&amp;nbsp;Rules&lt;/h3&gt;
&lt;p&gt;Create &lt;code&gt;/etc/prometheus/rules/alerts.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;docker_alerts&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;HighMemoryUsage&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;(container_memory_usage_bytes / container_spec_memory_limit_bytes) &amp;gt; 0.85&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;5m&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;severity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;warning&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;annotations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Container&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;$labels.name&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;high&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;memory&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;usage&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Memory&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;usage&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;is&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;above&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;85%&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;more&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;than&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;5&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;minutes.&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Grafana&amp;nbsp;Annotations&lt;/h3&gt;
&lt;p&gt;Annotate dashboards with deployment events. Use the Grafana &lt;span class="caps"&gt;API&lt;/span&gt; or webhooks to mark when a container is&amp;nbsp;updated:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-H&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Content-Type: application/json&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-X&lt;span class="w"&gt; &lt;/span&gt;POST&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;http://admin:admin@grafana:3000/api/annotations&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;{&amp;quot;dashboardId&amp;quot;: 1, &amp;quot;text&amp;quot;: &amp;quot;Deployed Nextcloud v28&amp;quot;}&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Integrating with Your&amp;nbsp;Homelab&lt;/h2&gt;
&lt;h3&gt;Reverse&amp;nbsp;Proxy&lt;/h3&gt;
&lt;p&gt;Expose Grafana via &lt;span class="caps"&gt;HTTPS&lt;/span&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.enable=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.grafana.rule=Host(`grafana.yourdomain.com`)&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.grafana.tls.certresolver=letsencrypt&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.services.grafana.loadbalancer.server.port=3000&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Loki&amp;nbsp;Integration&lt;/h3&gt;
&lt;p&gt;Add Grafana Loki as a second data source for log correlation. See our &lt;a href="https://steadypub.com/2026/06/grafana-loki-logs/"&gt;Grafana Loki guide&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Backup&lt;/h3&gt;
&lt;p&gt;Back up Grafana dashboards and Prometheus&amp;nbsp;data:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Grafana dashboards&lt;/span&gt;
mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;./grafana-dashboards
curl&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;http://admin:admin@localhost:3000/api/search&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;jq&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;.[].uri&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;read&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;uri&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;http://admin:admin@localhost:3000/api/dashboards/&lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;./grafana-dashboards/&lt;span class="k"&gt;$(&lt;/span&gt;basename&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;.json
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;done&lt;/span&gt;

&lt;span class="c1"&gt;# Prometheus data&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;tar&lt;span class="w"&gt; &lt;/span&gt;czf&lt;span class="w"&gt; &lt;/span&gt;prometheus-backup.tar.gz&lt;span class="w"&gt; &lt;/span&gt;/var/lib/docker/volumes/monitoring_prometheus_data/_data
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Alternatives to&amp;nbsp;Consider&lt;/h2&gt;
&lt;h3&gt;InfluxDB +&amp;nbsp;Telegraf&lt;/h3&gt;
&lt;p&gt;InfluxDB is a purpose-built time-series database with a &lt;span class="caps"&gt;SQL&lt;/span&gt;-like query language (InfluxQL/Flux). Telegraf is a powerful agent with hundreds of input plugins. This stack is excellent if you prefer &lt;span class="caps"&gt;SQL&lt;/span&gt;-like queries or need to integrate with industrial&amp;nbsp;sensors.&lt;/p&gt;
&lt;h3&gt;Zabbix&lt;/h3&gt;
&lt;p&gt;Zabbix is an enterprise monitoring platform with auto-discovery, agent-based monitoring, and native alerting. It is more complex than Prometheus but has a built-in dashboard and no separate Grafana requirement. Good for homelab operators who want an all-in-one&amp;nbsp;solution.&lt;/p&gt;
&lt;h3&gt;Netdata&lt;/h3&gt;
&lt;p&gt;Netdata provides real-time, per-second metrics with minimal configuration. It is ideal for quick troubleshooting but has limited long-term storage and query capabilities compared to&amp;nbsp;Prometheus.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;Query Language&lt;/th&gt;
&lt;th&gt;Alerting&lt;/th&gt;
&lt;th&gt;Long-Term Storage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Prometheus + Grafana&lt;/td&gt;
&lt;td&gt;Cloud-native, Docker&lt;/td&gt;
&lt;td&gt;PromQL&lt;/td&gt;
&lt;td&gt;Alertmanager&lt;/td&gt;
&lt;td&gt;Yes (&lt;span class="caps"&gt;TSDB&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;InfluxDB + Telegraf&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;SQL&lt;/span&gt;-like queries, IoT&lt;/td&gt;
&lt;td&gt;InfluxQL/Flux&lt;/td&gt;
&lt;td&gt;Native&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Zabbix&lt;/td&gt;
&lt;td&gt;Enterprise all-in-one&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;SQL&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Netdata&lt;/td&gt;
&lt;td&gt;Real-time troubleshooting&lt;/td&gt;
&lt;td&gt;Web &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Frequently Asked&amp;nbsp;Questions&lt;/h2&gt;
&lt;h3&gt;How much &lt;span class="caps"&gt;RAM&lt;/span&gt; does Prometheus&amp;nbsp;use?&lt;/h3&gt;
&lt;p&gt;Prometheus memory usage correlates with the number of time-series. A homelab with 1,000 series uses ~500 &lt;span class="caps"&gt;MB&lt;/span&gt;. Limit cardinality by dropping unused labels and reducing scrape&amp;nbsp;frequency.&lt;/p&gt;
&lt;h3&gt;Can I monitor remote&amp;nbsp;servers?&lt;/h3&gt;
&lt;p&gt;Yes. Install Node Exporter on each remote server and add it&amp;nbsp;to &lt;code&gt;prometheus.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;remote-server&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;192.168.1.20:9100&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;How do I update&amp;nbsp;Prometheus?&lt;/h3&gt;
&lt;p&gt;Update the Docker image and recreate the container. Prometheus data persists in the named&amp;nbsp;volume.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;pull&lt;span class="w"&gt; &lt;/span&gt;prom/prometheus:latest
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;prometheus
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Does Prometheus support push&amp;nbsp;metrics?&lt;/h3&gt;
&lt;p&gt;Yes, via the Pushgateway. However, pulls are preferred. Use Pushgateway only for batch jobs or ephemeral containers that cannot expose a scrape&amp;nbsp;endpoint.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Prometheus and Grafana are the gold standard for monitoring Docker-based homelabs. They provide per-container metrics, host health, alerting, and beautiful dashboards — all without cost. With Docker Compose, the entire stack deploys in minutes. With Alertmanager, you are notified before a problem becomes an&amp;nbsp;outage.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Add the Loki data source for log&amp;nbsp;correlation&lt;/li&gt;
&lt;li&gt;Create custom dashboards for your specific&amp;nbsp;services&lt;/li&gt;
&lt;li&gt;Configure recording rules for frequently used&amp;nbsp;queries&lt;/li&gt;
&lt;li&gt;Set up multi-channel alerting (Slack +&amp;nbsp;email)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;installation&lt;/strong&gt;: hosting — &lt;span class="caps"&gt;VPS&lt;/span&gt; for remote&amp;nbsp;monitoring&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;integration&lt;/strong&gt;: tool — Grafana Cloud for managed&amp;nbsp;hosting&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;alternatives&lt;/strong&gt;: tool — InfluxDB Cloud or&amp;nbsp;Datadog&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;installation&lt;/code&gt; → setup_guide: &lt;a href="https://steadypub.com/2026/06/docker-compose-for-beginners/"&gt;Docker Compose for&amp;nbsp;beginners&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;integration&lt;/code&gt; → related_guide: &lt;a href="https://steadypub.com/2026/06/grafana-loki-logs/"&gt;Grafana Loki log&amp;nbsp;aggregation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;alternatives&lt;/code&gt; → comparison: &lt;a href="https://steadypub.com/2026/06/prometheus-vs-influxdb/"&gt;Prometheus vs&amp;nbsp;InfluxDB&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] What metrics do you track in your homelab? Share your dashboard&amp;nbsp;screenshots.&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for weekly observability and monitoring&amp;nbsp;guides.&lt;/li&gt;
&lt;li&gt;[internal_link] Next: set up &lt;a href="https://steadypub.com/2026/06/prometheus-alertmanager-setup/"&gt;Prometheus&amp;nbsp;Alertmanager&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Monitoring"/><category term="docker"/><category term="grafana"/><category term="prometheus"/><category term="monitoring"/><category term="homelab"/><category term="metrics"/></entry><entry><title>Grafana Dashboard for Homelab: Build, Customize, and Monitor Everything</title><link href="https://steadypub.com/2026/06/grafana-dashboard-homelab/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T06:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/grafana-dashboard-homelab/</id><summary type="html">&lt;p&gt;Build a Grafana dashboard for your homelab with real panels for &lt;span class="caps"&gt;CPU&lt;/span&gt;, memory, disk, network, Docker, and Proxmox. Includes dashboard &lt;span class="caps"&gt;JSON&lt;/span&gt; and provisioning&amp;nbsp;tips.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~14 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelabbers who want a single pane of glass for their&amp;nbsp;infrastructure&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is a Grafana Dashboard for Your&amp;nbsp;Homelab?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Grafana is the open-source visualization platform that turns time-series data into beautiful, actionable dashboards. In a homelab, Grafana is the single pane of glass: &lt;span class="caps"&gt;CPU&lt;/span&gt; load, memory pressure, disk usage, network throughput, container health, and even &lt;span class="caps"&gt;UPS&lt;/span&gt; battery status—all in one&amp;nbsp;place.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why Grafana for homelabs:&lt;/strong&gt;
- &lt;strong&gt;Free and open source:&lt;/strong&gt; AGPLv3. No feature limits.
- &lt;strong&gt;Data source agnostic:&lt;/strong&gt; Prometheus, InfluxDB, Loki, MySQL, PostgreSQL, Zabbix, and 100+ others.
- &lt;strong&gt;Community dashboards:&lt;/strong&gt; Import pre-built dashboards for Node Exporter, cAdvisor, Proxmox, Pi-hole, and more.
- &lt;strong&gt;Alerting:&lt;/strong&gt; Native alerting rules with email, Slack, Telegram, and webhook support.
- &lt;strong&gt;Mobile-friendly:&lt;/strong&gt; Responsive web &lt;span class="caps"&gt;UI&lt;/span&gt; works on tablets and&amp;nbsp;phones.&lt;/p&gt;
&lt;h3&gt;Key&amp;nbsp;Benefits&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Proactive maintenance:&lt;/strong&gt; See disk fill-up before it&amp;nbsp;happens&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Performance tuning:&lt;/strong&gt; Identify which &lt;span class="caps"&gt;VM&lt;/span&gt; is consuming &lt;span class="caps"&gt;RAM&lt;/span&gt; or &lt;span class="caps"&gt;IOPS&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Capacity planning:&lt;/strong&gt; Track 30-day trends to know when to&amp;nbsp;upgrade&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Troubleshooting:&lt;/strong&gt; Correlate events across multiple systems in one&amp;nbsp;timeline&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Show off:&lt;/strong&gt; A well-built Grafana dashboard is the homelab equivalent of a trophy&amp;nbsp;case&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;h3&gt;Hardware&amp;nbsp;Requirements&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Minimum&lt;/th&gt;
&lt;th&gt;Recommended&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1 core&lt;/td&gt;
&lt;td&gt;2 cores&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;512 &lt;span class="caps"&gt;MB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;1 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;5 &lt;span class="caps"&gt;GB&lt;/span&gt; (for dashboard &lt;span class="caps"&gt;JSON&lt;/span&gt; and logs)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network&lt;/td&gt;
&lt;td&gt;1 GbE&lt;/td&gt;
&lt;td&gt;1 GbE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Software&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Docker and Docker&amp;nbsp;Compose&lt;/li&gt;
&lt;li&gt;A data source (Prometheus, InfluxDB, or&amp;nbsp;both)&lt;/li&gt;
&lt;li&gt;Node Exporter and cAdvisor running on monitored&amp;nbsp;hosts&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Knowledge&amp;nbsp;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Basic Prometheus query language (PromQL) or&amp;nbsp;InfluxQL&lt;/li&gt;
&lt;li&gt;Understanding of time-series&amp;nbsp;data&lt;/li&gt;
&lt;li&gt;Familiarity with Docker&amp;nbsp;networking&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Deploy Grafana with Docker&amp;nbsp;Compose&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Run Grafana as a container with persistent storage and pre-configured data&amp;nbsp;sources.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Create a directory for&amp;nbsp;Grafana:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;~/grafana/config
&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/grafana
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Create &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;grafana&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;grafana/grafana:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;grafana&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3000:3000&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;GF_SECURITY_ADMIN_USER=admin&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;GF_SECURITY_ADMIN_PASSWORD=***      - GF_USERS_ALLOW_SIGN_UP=false&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;GF_SERVER_ROOT_URL=https://grafana.yourdomain.com&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;GF_INSTALL_PLUGINS=grafana-clock-panel,grafana-simple-json-datasource&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;grafana-data:/var/lib/grafana&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./config/datasources.yml:/etc/grafana/provisioning/datasources/datasources.yml&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./config/dashboards.yml:/etc/grafana/provisioning/dashboards/dashboards.yml&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./dashboards:/var/lib/grafana/dashboards&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;grafana-data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Create &lt;code&gt;config/datasources.yml&lt;/code&gt; to auto-provision&amp;nbsp;Prometheus:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1&lt;/span&gt;

&lt;span class="nt"&gt;datasources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Prometheus&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;prometheus&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;access&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;proxy&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;http://prometheus:9090&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;isDefault&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;editable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;false&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;InfluxDB&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;influxdb&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;access&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;proxy&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;http://influxdb:8086&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;database&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;homelab&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;editable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Create &lt;code&gt;config/dashboards.yml&lt;/code&gt; to auto-provision dashboard&amp;nbsp;files:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1&lt;/span&gt;

&lt;span class="nt"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;homelab&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;orgId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;folder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;Homelab&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;file&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;disableDeletion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;false&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;updateIntervalSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;10&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;allowUiUpdates&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/var/lib/grafana/dashboards&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Start the&amp;nbsp;container:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Access Grafana&amp;nbsp;at &lt;code&gt;http://your-server-ip:3000&lt;/code&gt; (login: admin / password from&amp;nbsp;env)&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Step 2: Build the &amp;#8220;Homelab Overview&amp;#8221;&amp;nbsp;Dashboard&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Create a dashboard with panels for system metrics, Docker containers, and&amp;nbsp;network.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;In Grafana, click &lt;strong&gt;+&lt;/strong&gt; &amp;gt; &lt;strong&gt;New Dashboard&lt;/strong&gt; &amp;gt; &lt;strong&gt;Add&amp;nbsp;visualization&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Panel 1: &lt;span class="caps"&gt;CPU&lt;/span&gt; Usage&amp;nbsp;(Stat)&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Data source:&amp;nbsp;Prometheus&lt;/li&gt;
&lt;li&gt;Query: &lt;code&gt;100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Visualization:&amp;nbsp;Stat&lt;/li&gt;
&lt;li&gt;Thresholds: Green &amp;lt; 60, Yellow &amp;lt; 80, Red &amp;gt;&amp;nbsp;80&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Title: &amp;#8220;&lt;span class="caps"&gt;CPU&lt;/span&gt;&amp;nbsp;Usage&amp;#8221;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Panel 2: Memory Usage&amp;nbsp;(Gauge)&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Data source:&amp;nbsp;Prometheus&lt;/li&gt;
&lt;li&gt;Query: &lt;code&gt;100 * (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes))&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Visualization:&amp;nbsp;Gauge&lt;/li&gt;
&lt;li&gt;Thresholds: Green &amp;lt; 70, Yellow &amp;lt; 85, Red &amp;gt;&amp;nbsp;85&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Title: &amp;#8220;Memory&amp;nbsp;Usage&amp;#8221;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Panel 3: Disk Usage&amp;nbsp;(Table)&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Data source:&amp;nbsp;Prometheus&lt;/li&gt;
&lt;li&gt;Query: &lt;code&gt;100 * (1 - node_filesystem_avail_bytes{fstype!="tmpfs"} / node_filesystem_size_bytes)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Visualization:&amp;nbsp;Table&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Title: &amp;#8220;Disk Usage by&amp;nbsp;Mount&amp;#8221;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Panel 4: Network Traffic (Time&amp;nbsp;Series)&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Data source:&amp;nbsp;Prometheus&lt;/li&gt;
&lt;li&gt;Query A (&lt;span class="caps"&gt;RX&lt;/span&gt;): &lt;code&gt;irate(node_network_receive_bytes_total{device!="lo"}[5m])&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Query B (&lt;span class="caps"&gt;TX&lt;/span&gt;): &lt;code&gt;irate(node_network_transmit_bytes_total{device!="lo"}[5m])&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Visualization: Time&amp;nbsp;Series&lt;/li&gt;
&lt;li&gt;Unit: bytes/sec (&lt;span class="caps"&gt;IEC&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Title: &amp;#8220;Network&amp;nbsp;Traffic&amp;#8221;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Panel 5: Top 5 Containers by &lt;span class="caps"&gt;CPU&lt;/span&gt; (Bar&amp;nbsp;Chart)&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Data source:&amp;nbsp;Prometheus&lt;/li&gt;
&lt;li&gt;Query: &lt;code&gt;topk(5, rate(container_cpu_usage_seconds_total{name!=""}[5m]))&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Visualization: Bar&amp;nbsp;Chart&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Title: &amp;#8220;Top Containers by &lt;span class="caps"&gt;CPU&lt;/span&gt;&amp;#8221;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Panel 6: Docker Container Health&amp;nbsp;(Stat)&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Data source:&amp;nbsp;Prometheus&lt;/li&gt;
&lt;li&gt;Query: &lt;code&gt;count(container_last_seen{name!=""})&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Visualization:&amp;nbsp;Stat&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Title: &amp;#8220;Active&amp;nbsp;Containers&amp;#8221;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Save the dashboard&amp;nbsp;as &lt;code&gt;homelab-overview.json&lt;/code&gt; in&amp;nbsp;the &lt;code&gt;dashboards/&lt;/code&gt; folder. Grafana will auto-load&amp;nbsp;it.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Step 3: Import Community&amp;nbsp;Dashboards&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Import battle-tested dashboards for common homelab&amp;nbsp;tools.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;In Grafana, click &lt;strong&gt;+&lt;/strong&gt; &amp;gt; &lt;strong&gt;Import&amp;nbsp;Dashboard&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Enter the dashboard &lt;span class="caps"&gt;ID&lt;/span&gt; and click &lt;strong&gt;Load&lt;/strong&gt;:&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Dashboard &lt;span class="caps"&gt;ID&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Node Exporter&lt;/td&gt;
&lt;td&gt;1860&lt;/td&gt;
&lt;td&gt;Node Exporter Full&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cAdvisor&lt;/td&gt;
&lt;td&gt;14282&lt;/td&gt;
&lt;td&gt;Docker and System Monitoring&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Proxmox&lt;/td&gt;
&lt;td&gt;10347&lt;/td&gt;
&lt;td&gt;Proxmox via Prometheus&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pi-hole&lt;/td&gt;
&lt;td&gt;10176&lt;/td&gt;
&lt;td&gt;Pi-hole Exporter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AdGuard Home&lt;/td&gt;
&lt;td&gt;14400&lt;/td&gt;
&lt;td&gt;AdGuard Home&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unifi&lt;/td&gt;
&lt;td&gt;11306&lt;/td&gt;
&lt;td&gt;UniFi Poller&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pfSense&lt;/td&gt;
&lt;td&gt;11694&lt;/td&gt;
&lt;td&gt;pfSense Telegraf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Speedtest&lt;/td&gt;
&lt;td&gt;13665&lt;/td&gt;
&lt;td&gt;Speedtest Tracker&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ol&gt;
&lt;li&gt;Select your Prometheus data&amp;nbsp;source&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Import&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Step 4: Customize Panels and&amp;nbsp;Variables&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Add template variables so one dashboard serves multiple&amp;nbsp;hosts.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;In your dashboard, click &lt;strong&gt;Settings&lt;/strong&gt; &amp;gt; &lt;strong&gt;Variables&lt;/strong&gt; &amp;gt; &lt;strong&gt;New&amp;nbsp;Variable&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a variable&amp;nbsp;named &lt;code&gt;node&lt;/code&gt;:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Data source:&amp;nbsp;Prometheus&lt;/li&gt;
&lt;li&gt;Query: &lt;code&gt;label_values(node_uname_info, nodename)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Refresh: On Dashboard&amp;nbsp;Load&lt;/li&gt;
&lt;li&gt;Multi-value:&amp;nbsp;Yes&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Include All option:&amp;nbsp;Yes&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Update your queries to use the&amp;nbsp;variable:&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Before&lt;/span&gt;
&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;avg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;by&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;irate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;node_cpu_seconds_total&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;quot;&lt;/span&gt;&lt;span class="s"&gt;idle&lt;/span&gt;&lt;span class="p"&gt;&amp;quot;}[&lt;/span&gt;&lt;span class="s"&gt;5m&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# After&lt;/span&gt;
&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;avg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;by&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;irate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;node_cpu_seconds_total&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;quot;&lt;/span&gt;&lt;span class="s"&gt;idle&lt;/span&gt;&lt;span class="p"&gt;&amp;quot;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;nodename&lt;/span&gt;&lt;span class="o"&gt;=~&lt;/span&gt;&lt;span class="p"&gt;&amp;quot;&lt;/span&gt;&lt;span class="s"&gt;$node&lt;/span&gt;&lt;span class="p"&gt;&amp;quot;}[&lt;/span&gt;&lt;span class="s"&gt;5m&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Now you can select specific hosts or &amp;#8220;All&amp;#8221; from a dropdown at the top of the&amp;nbsp;dashboard.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Step 5: Set Up Alerts in&amp;nbsp;Grafana&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Create alerting rules directly in Grafana (separate from&amp;nbsp;Alertmanager).&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Go to &lt;strong&gt;Alerting&lt;/strong&gt; &amp;gt; &lt;strong&gt;Alert Rules&lt;/strong&gt; &amp;gt; &lt;strong&gt;New Alert&amp;nbsp;Rule&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a rule for disk&amp;nbsp;space:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Query: &lt;code&gt;100 * (1 - node_filesystem_avail_bytes / node_filesystem_size_bytes) &amp;gt; 90&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Evaluation: Every 1m for&amp;nbsp;5m&lt;/li&gt;
&lt;li&gt;Labels: &lt;code&gt;severity=critical&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Contact point: Telegram or&amp;nbsp;Slack&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a rule for high&amp;nbsp;memory:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Query: &lt;code&gt;100 * (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) &amp;gt; 85&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Evaluation: Every 1m for&amp;nbsp;5m&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Labels: &lt;code&gt;severity=warning&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Test the alert by temporarily lowering the&amp;nbsp;threshold.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Use Row Panels for&amp;nbsp;Organization&lt;/h3&gt;
&lt;p&gt;Group related panels into collapsible rows. Common rows for a homelab dashboard:
- &lt;strong&gt;Overview:&lt;/strong&gt; &lt;span class="caps"&gt;CPU&lt;/span&gt;, memory, disk, uptime
- &lt;strong&gt;Network:&lt;/strong&gt; Traffic, errors, top talkers
- &lt;strong&gt;Containers:&lt;/strong&gt; &lt;span class="caps"&gt;CPU&lt;/span&gt;, memory, restart count
- &lt;strong&gt;Storage:&lt;/strong&gt; &lt;span class="caps"&gt;ZFS&lt;/span&gt; pool health, disk temperatures, &lt;span class="caps"&gt;IOPS&lt;/span&gt;
- &lt;strong&gt;Services:&lt;/strong&gt; Per-service panels (Nextcloud, Plex,&amp;nbsp;Jellyfin)&lt;/p&gt;
&lt;h3&gt;Tip 2: Add Annotations for&amp;nbsp;Events&lt;/h3&gt;
&lt;p&gt;Grafana annotations mark events on the timeline. Use the &lt;span class="caps"&gt;API&lt;/span&gt; to add annotations for deployments, reboots, or&amp;nbsp;backups:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-X&lt;span class="w"&gt; &lt;/span&gt;POST&lt;span class="w"&gt; &lt;/span&gt;http://grafana:3000/api/annotations&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-H&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Content-Type: application/json&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-H&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Authorization: Bearer YOUR_API_KEY&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;{&lt;/span&gt;
&lt;span class="s1"&gt;    &amp;quot;dashboardId&amp;quot;: 1,&lt;/span&gt;
&lt;span class="s1"&gt;    &amp;quot;panelId&amp;quot;: 1,&lt;/span&gt;
&lt;span class="s1"&gt;    &amp;quot;time&amp;quot;: &amp;#39;&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;date&lt;span class="w"&gt; &lt;/span&gt;+%s&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;000&amp;quot;&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;,&lt;/span&gt;
&lt;span class="s1"&gt;    &amp;quot;tags&amp;quot;: [&amp;quot;deployment&amp;quot;, &amp;quot;nextcloud&amp;quot;],&lt;/span&gt;
&lt;span class="s1"&gt;    &amp;quot;text&amp;quot;: &amp;quot;Deployed Nextcloud 30.0.1&amp;quot;&lt;/span&gt;
&lt;span class="s1"&gt;  }&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 3: Export and Version Control Your&amp;nbsp;Dashboards&lt;/h3&gt;
&lt;p&gt;Dashboard &lt;span class="caps"&gt;JSON&lt;/span&gt; should be in Git. Export via &lt;strong&gt;Share&lt;/strong&gt; &amp;gt; &lt;strong&gt;Export&lt;/strong&gt; &amp;gt; &lt;strong&gt;Save to file&lt;/strong&gt;. Commit to a repo and use Grafana provisioning to auto-deploy. This prevents losing work and makes migrations&amp;nbsp;trivial.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Troubleshooting Common&amp;nbsp;Issues&lt;/h2&gt;
&lt;h3&gt;Problem 1: &amp;#8220;No Data&amp;#8221; in&amp;nbsp;Panels&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Check:&lt;/strong&gt; Ensure Prometheus is scraping the target. Go to &lt;strong&gt;Explore&lt;/strong&gt; in Grafana and run the query manually. If no data, check the target in Prometheus&amp;nbsp;(&lt;code&gt;http://prometheus:9090/targets&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Common causes: wrong job name, container not on the same Docker network, or firewall blocking port&amp;nbsp;9100.&lt;/p&gt;
&lt;h3&gt;Problem 2: Dashboard Variables Not&amp;nbsp;Working&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Check:&lt;/strong&gt; Verify the variable query returns values in &lt;strong&gt;Explore&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; If the variable is empty, the label name may be wrong.&amp;nbsp;Use &lt;code&gt;label_values(node_uname_info)&lt;/code&gt; to see all available&amp;nbsp;labels.&lt;/p&gt;
&lt;h3&gt;Problem 3: Slow Dashboard&amp;nbsp;Loading&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Check:&lt;/strong&gt; Complex queries with high cardinality (many unique label combinations) can slow&amp;nbsp;Grafana.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Add aggregation. Instead&amp;nbsp;of &lt;code&gt;container_cpu_usage_seconds_total&lt;/code&gt;,&amp;nbsp;use &lt;code&gt;sum by(name) (container_cpu_usage_seconds_total)&lt;/code&gt;. Limit time ranges. Use recording rules in Prometheus for expensive&amp;nbsp;queries.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Grafana is the visualization layer that makes your Prometheus data actionable. A well-built homelab dashboard gives you proactive insight into &lt;span class="caps"&gt;CPU&lt;/span&gt;, memory, disk, network, and container health. Community dashboards provide a fast starting point; custom panels and variables tailor the experience to your&amp;nbsp;infrastructure.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Import the Node Exporter Full dashboard (&lt;span class="caps"&gt;ID&lt;/span&gt;&amp;nbsp;1860)&lt;/li&gt;
&lt;li&gt;Build a custom &amp;#8220;Homelab Overview&amp;#8221; dashboard with your top 6&amp;nbsp;metrics&lt;/li&gt;
&lt;li&gt;Add template variables for multi-host&amp;nbsp;monitoring&lt;/li&gt;
&lt;li&gt;Set up Grafana alerting for disk space and memory&amp;nbsp;pressure&lt;/li&gt;
&lt;li&gt;Export your dashboards to &lt;span class="caps"&gt;JSON&lt;/span&gt; and commit them to&amp;nbsp;Git&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mini PCs for Grafana:&lt;/strong&gt; Minisforum, Beelink&amp;nbsp;(Amazon)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Displays:&lt;/strong&gt; Wall-mounted tablets for dashboard kiosks&amp;nbsp;(Amazon)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt;:&lt;/strong&gt; Hetzner for offsite Grafana&amp;nbsp;(referral)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;prometheus-setup&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;prometheus-monitoring-homelab.md&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;alertmanager&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;prometheus-alertmanager-setup.md&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker-monitoring&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;docker-monitoring-grafana-prometheus.md&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;node-exporter&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;prometheus-monitoring-homelab.md&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] Share a screenshot of your Grafana dashboard! What panels are essential for your&amp;nbsp;homelab?&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for our dashboard &lt;span class="caps"&gt;JSON&lt;/span&gt; packs and monitoring stack&amp;nbsp;updates.&lt;/li&gt;
&lt;li&gt;[internal_link] Need to set up Prometheus first? Read our &lt;a href="https://steadypub.com/2026/06/prometheus-monitoring-homelab/"&gt;Prometheus monitoring guide&lt;/a&gt;&amp;nbsp;next.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Tutorials"/><category term="grafana dashboard homelab"/><category term="homelab"/><category term="self-hosted"/><category term="monitoring"/></entry><entry><title>Grafana Loki Logs: The Ultimate Self-Hosted Guide for 2026</title><link href="https://steadypub.com/2026/06/grafana-loki-logs/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T10:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/grafana-loki-logs/</id><summary type="html">&lt;p&gt;A practical guide to deploying Grafana Loki for log aggregation in your homelab. Covers Docker Compose setup, Promtail configuration, LogQL queries, and integration with Grafana&amp;nbsp;dashboards.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~14 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab and self-hosting&amp;nbsp;enthusiasts&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is Grafana&amp;nbsp;Loki?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Grafana Loki is a horizontally scalable, highly available, multi-tenant log aggregation system inspired by Prometheus. Unlike traditional &lt;span class="caps"&gt;ELK&lt;/span&gt; stacks (Elasticsearch, Logstash, Kibana), Loki indexes only the metadata (labels) of logs and leaves the log content unindexed. This makes it dramatically cheaper to run and easier to operate on homelab hardware. You store logs in object storage or local filesystems, and query them with LogQL, a Prometheus-style query&amp;nbsp;language.&lt;/p&gt;
&lt;h3&gt;A Brief&amp;nbsp;History&lt;/h3&gt;
&lt;p&gt;Loki was created by Grafana Labs and first announced in 2018. It was designed to solve the operational complexity and cost of running Elasticsearch at scale. Version 1.0 arrived in 2019. Since then, Loki has gained features like recording rules, alerting, structured metadata, and a native Helm chart. For homelab use, Loki&amp;#8217;s &amp;#8220;single binary&amp;#8221; mode is sufficient — no need for distributed&amp;nbsp;microservices.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why Use Loki in Your&amp;nbsp;Homelab?&lt;/h2&gt;
&lt;h3&gt;Lower Resource Footprint Than &lt;span class="caps"&gt;ELK&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Elasticsearch requires significant &lt;span class="caps"&gt;RAM&lt;/span&gt; (&lt;span class="caps"&gt;JVM&lt;/span&gt; heap) and &lt;span class="caps"&gt;CPU&lt;/span&gt; for indexing. Loki, in contrast, can run comfortably on a Raspberry Pi 4 or a small &lt;span class="caps"&gt;VPS&lt;/span&gt;. The core Loki container in single-binary mode uses under 200 &lt;span class="caps"&gt;MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;. For a homelab with limited hardware, this is the difference between running a log stack and not running&amp;nbsp;one.&lt;/p&gt;
&lt;h3&gt;Native Prometheus-Style&amp;nbsp;Labeling&lt;/h3&gt;
&lt;p&gt;If you already run Prometheus, Loki feels familiar. You label logs&amp;nbsp;with &lt;code&gt;job&lt;/code&gt;, &lt;code&gt;instance&lt;/code&gt;, &lt;code&gt;container&lt;/code&gt;, and custom labels. You query with LogQL, which uses a similar syntax to PromQL. This reduces cognitive load when switching between metrics and&amp;nbsp;logs.&lt;/p&gt;
&lt;h3&gt;Deep Integration with&amp;nbsp;Grafana&lt;/h3&gt;
&lt;p&gt;Grafana has a native Loki data source. You can plot log volume over time, jump from a metric alert to the logs of the affected container, and use &amp;#8220;derived fields&amp;#8221; to link log lines to traces or external systems. This is the same stack used in Grafana Cloud, just&amp;nbsp;self-hosted.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;h3&gt;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Docker and Docker Compose&amp;nbsp;installed&lt;/li&gt;
&lt;li&gt;Grafana already running (or deploy it alongside&amp;nbsp;Loki)&lt;/li&gt;
&lt;li&gt;At least 1 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; available for the Loki + Promtail&amp;nbsp;stack&lt;/li&gt;
&lt;li&gt;A directory for persistent log&amp;nbsp;storage&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Method 1: Docker Compose with Local&amp;nbsp;Storage&lt;/h3&gt;
&lt;p&gt;This is the recommended homelab setup. It runs Loki, Promtail, and Grafana in a single Compose&amp;nbsp;stack.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;monitoring&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;bridge&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;loki&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;grafana/loki:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;loki&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3100:3100&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./loki-config.yaml:/etc/loki/local-config.yaml&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;loki-data:/loki&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;-config.file=/etc/loki/local-config.yaml&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;monitoring&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;promtail&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;grafana/promtail:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;promtail&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/var/log:/var/log:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/var/lib/docker/containers:/var/lib/docker/containers:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/var/run/docker.sock:/var/run/docker.sock:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./promtail-config.yaml:/etc/promtail/config.yml&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;-config.file=/etc/promtail/config.yml&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;monitoring&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;grafana&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;grafana/grafana:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;grafana&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3000:3000&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;grafana-data:/var/lib/grafana&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;GF_SECURITY_ADMIN_USER=admin&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;GF_SECURITY_ADMIN_PASSWORD=admin&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;monitoring&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;loki-data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;grafana-data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Create &lt;code&gt;loki-config.yaml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;auth_enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;false&lt;/span&gt;

&lt;span class="nt"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;http_listen_port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;3100&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;grpc_listen_port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;9096&lt;/span&gt;

&lt;span class="nt"&gt;common&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;path_prefix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/loki&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;filesystem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;chunks_directory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/loki/chunks&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;rules_directory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/loki/rules&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;replication_factor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;ring&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;instance_addr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;127.0.0.1&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;kvstore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;store&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;inmemory&lt;/span&gt;

&lt;span class="nt"&gt;schema_config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;2020-10-24&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;store&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;tsdb&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;object_store&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;filesystem&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;v13&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;index_&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;period&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;24h&lt;/span&gt;

&lt;span class="nt"&gt;limits_config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;retention_period&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;720h&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# 30 days&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Create &lt;code&gt;promtail-config.yaml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;http_listen_port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;9080&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;grpc_listen_port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;0&lt;/span&gt;

&lt;span class="nt"&gt;positions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/tmp/positions.yaml&lt;/span&gt;

&lt;span class="nt"&gt;clients&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;http://loki:3100/loki/api/v1/push&lt;/span&gt;

&lt;span class="nt"&gt;scrape_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;containers&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;localhost&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;job&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;containerlogs&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;__path__&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/var/lib/docker/containers/*/*.log&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;system&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;localhost&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;job&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;varlogs&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;__path__&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/var/log/*.log&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Deploy:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Method 2: Docker Swarm&amp;nbsp;Service&lt;/h3&gt;
&lt;p&gt;If you run Docker Swarm, deploy Loki as a global&amp;nbsp;service:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;service&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;loki&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--publish&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3100&lt;/span&gt;:3100&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--mount&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;bind,source&lt;span class="o"&gt;=&lt;/span&gt;/var/log,destination&lt;span class="o"&gt;=&lt;/span&gt;/var/log,readonly&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--mount&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;bind,source&lt;span class="o"&gt;=&lt;/span&gt;/var/lib/docker/containers,destination&lt;span class="o"&gt;=&lt;/span&gt;/var/lib/docker/containers,readonly&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--mount&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;bind,source&lt;span class="o"&gt;=&lt;/span&gt;/path/to/loki-config.yaml,destination&lt;span class="o"&gt;=&lt;/span&gt;/etc/loki/local-config.yaml,readonly&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--mode&lt;span class="w"&gt; &lt;/span&gt;replicated&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--replicas&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;grafana/loki:latest&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-config.file&lt;span class="o"&gt;=&lt;/span&gt;/etc/loki/local-config.yaml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Basic Setup and&amp;nbsp;Configuration&lt;/h2&gt;
&lt;h3&gt;Step 1: Add Loki as a Grafana Data&amp;nbsp;Source&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Open Grafana&amp;nbsp;at &lt;code&gt;http://your-server:3000&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Go to &lt;strong&gt;Connections&lt;/strong&gt; → &lt;strong&gt;Data Sources&lt;/strong&gt; → &lt;strong&gt;Add data&amp;nbsp;source&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Loki&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;URL&lt;/span&gt;: &lt;code&gt;http://loki:3100&lt;/code&gt; (if in the same network)&amp;nbsp;or &lt;code&gt;http://your-server-ip:3100&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Save &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;Test&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Step 2: Query Logs with&amp;nbsp;LogQL&lt;/h3&gt;
&lt;p&gt;LogQL queries have the&amp;nbsp;form:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="x"&gt;{label=&amp;quot;value&amp;quot;} |= &amp;quot;search string&amp;quot; | json | line_format &amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;.field&lt;/span&gt;&lt;span class="cp"&gt;}}&lt;/span&gt;&lt;span class="x"&gt;&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Examples:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;# All container logs
{job=&amp;quot;containerlogs&amp;quot;}

# Logs from a specific container
{job=&amp;quot;containerlogs&amp;quot;} |= &amp;quot;nginx&amp;quot;

# Parse JSON logs and extract a field
{job=&amp;quot;containerlogs&amp;quot;} | json | level=&amp;quot;error&amp;quot;

# Logs in the last 5 minutes
{job=&amp;quot;containerlogs&amp;quot;} |= &amp;quot;error&amp;quot; [5m]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Step 3: Build a&amp;nbsp;Dashboard&lt;/h3&gt;
&lt;p&gt;In Grafana, create a dashboard with a &lt;strong&gt;Logs&lt;/strong&gt; panel. Use the&amp;nbsp;query &lt;code&gt;{job="containerlogs"}&lt;/code&gt; and set the refresh interval to 5s. You now have a live tail of all Docker containers. Add a &lt;strong&gt;Time series&lt;/strong&gt; panel&amp;nbsp;with &lt;code&gt;rate({job="containerlogs"} |= "error" [1m])&lt;/code&gt; to visualize error&amp;nbsp;frequency.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Advanced&amp;nbsp;Features&lt;/h2&gt;
&lt;h3&gt;Recording Rules and&amp;nbsp;Alerting&lt;/h3&gt;
&lt;p&gt;Loki supports recording rules and alerting via the Ruler component. In single-binary mode, enable the ruler&amp;nbsp;in &lt;code&gt;loki-config.yaml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;ruler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;alertmanager_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;http://alertmanager:9093&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;ring&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;kvstore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;store&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;inmemory&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;rule_path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/loki/rules&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;local&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;local&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/loki/rules&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Create a rule&amp;nbsp;file &lt;code&gt;/loki/rules/fake/error-rate.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;container_errors&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1m&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;HighErrorRate&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;|&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="no"&gt;rate({job=&amp;quot;containerlogs&amp;quot;} |= &amp;quot;error&amp;quot; [5m]) &amp;gt; 1&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;5m&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;severity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;warning&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;annotations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;High&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;rate&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;detected&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Structured Metadata (&lt;span class="caps"&gt;JSON&lt;/span&gt;&amp;nbsp;Logging)&lt;/h3&gt;
&lt;p&gt;Modern applications emit structured &lt;span class="caps"&gt;JSON&lt;/span&gt; logs. Promtail can parse these automatically with&amp;nbsp;the &lt;code&gt;json&lt;/code&gt; stage:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;scrape_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;app&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;localhost&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;job&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;myapp&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;__path__&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/var/log/myapp.log&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;pipeline_stages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;json&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;expressions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;level&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;level&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;message&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;level&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This creates&amp;nbsp;a &lt;code&gt;level&lt;/code&gt; label in Loki, allowing you to&amp;nbsp;query &lt;code&gt;{job="myapp", level="error"}&lt;/code&gt; directly.&lt;/p&gt;
&lt;h3&gt;Multi-Tenant and&amp;nbsp;Retention&lt;/h3&gt;
&lt;p&gt;For a shared homelab or family setup, you can enable multi-tenancy by&amp;nbsp;setting &lt;code&gt;auth_enabled: true&lt;/code&gt; and&amp;nbsp;passing &lt;code&gt;X-Scope-OrgID&lt;/code&gt; headers. In single-tenant mode, control retention&amp;nbsp;with &lt;code&gt;limits_config.retention_period&lt;/code&gt; (e.g., &lt;code&gt;720h&lt;/code&gt; for 30 days). Old chunks are automatically&amp;nbsp;deleted.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Integrating with Your&amp;nbsp;Homelab&lt;/h2&gt;
&lt;h3&gt;Docker Driver&amp;nbsp;Plugin&lt;/h3&gt;
&lt;p&gt;Instead of Promtail, you can send logs directly from Docker to Loki using&amp;nbsp;the &lt;code&gt;loki-docker-driver&lt;/code&gt; plugin:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;plugin&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;grafana/loki-docker-driver:latest&lt;span class="w"&gt; &lt;/span&gt;--alias&lt;span class="w"&gt; &lt;/span&gt;loki&lt;span class="w"&gt; &lt;/span&gt;--grant-all-permissions
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then add&amp;nbsp;to &lt;code&gt;/etc/docker/daemon.json&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;log-driver&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;loki&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;log-opts&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;loki-url&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;http://localhost:3100/loki/api/v1/push&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;loki-batch-size&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;400&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Restart Docker. All containers now log to Loki&amp;nbsp;automatically.&lt;/p&gt;
&lt;h3&gt;Alertmanager&amp;nbsp;Integration&lt;/h3&gt;
&lt;p&gt;Route Loki alerts to Alertmanager, then to PagerDuty, Slack, or a simple webhook. In a homelab, a Slack webhook or Matrix notification is often&amp;nbsp;sufficient.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# alertmanager.yml&lt;/span&gt;
&lt;span class="nt"&gt;route&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;receiver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;slack&amp;quot;&lt;/span&gt;
&lt;span class="nt"&gt;receivers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;slack&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;slack_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;api_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;https://hooks.slack.com/services/YOUR/WEBHOOK/URL&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#homelab-alerts&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Homelab&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Alert&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;.CommonAnnotations.summary&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Alternatives to&amp;nbsp;Consider&lt;/h2&gt;
&lt;h3&gt;&lt;span class="caps"&gt;ELK&lt;/span&gt; Stack (Elasticsearch, Logstash,&amp;nbsp;Kibana)&lt;/h3&gt;
&lt;p&gt;The &lt;span class="caps"&gt;ELK&lt;/span&gt; stack is the most mature log platform. It offers full-text search, powerful aggregation, and a massive plugin ecosystem. However, it requires 4+ &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; and significant tuning. Use &lt;span class="caps"&gt;ELK&lt;/span&gt; if you need complex full-text search or if you already have Elasticsearch&amp;nbsp;expertise.&lt;/p&gt;
&lt;h3&gt;Vector&lt;/h3&gt;
&lt;p&gt;Vector (by Datadog) is a modern log and metrics pipeline. It can replace both Promtail and Logstash. It has a more expressive transform language (&lt;span class="caps"&gt;VRL&lt;/span&gt;) and better performance. If you want a single binary for all telemetry, consider Vector + Loki as&amp;nbsp;sinks.&lt;/p&gt;
&lt;h3&gt;syslog-ng /&amp;nbsp;rsyslog&lt;/h3&gt;
&lt;p&gt;For simple, low-volume log aggregation, a traditional syslog daemon forwarding to a central server may be enough. You lose the query power of LogQL but gain simplicity and zero container&amp;nbsp;overhead.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;Resource Use&lt;/th&gt;
&lt;th&gt;Query Power&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Loki&lt;/td&gt;
&lt;td&gt;Homelab, cloud-native, Docker&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Medium (LogQL)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;ELK&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Enterprise, full-text search&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Very High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vector&lt;/td&gt;
&lt;td&gt;Modern pipelines, &lt;span class="caps"&gt;VRL&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;High (&lt;span class="caps"&gt;VRL&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;syslog-ng&lt;/td&gt;
&lt;td&gt;Simple forwarding, legacy&lt;/td&gt;
&lt;td&gt;Very Low&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Frequently Asked&amp;nbsp;Questions&lt;/h2&gt;
&lt;h3&gt;How much storage does Loki&amp;nbsp;need?&lt;/h3&gt;
&lt;p&gt;This depends entirely on log volume. A homelab generating 100 &lt;span class="caps"&gt;MB&lt;/span&gt;/day of logs will use ~3 &lt;span class="caps"&gt;GB&lt;/span&gt;/month. Loki&amp;#8217;s filesystem storage with compression is efficient. For longer retention, switch to S3-compatible object storage (MinIO, Wasabi, Hetzner Object&amp;nbsp;Storage).&lt;/p&gt;
&lt;h3&gt;Can I run Loki without&amp;nbsp;Docker?&lt;/h3&gt;
&lt;p&gt;Yes. Grafana publishes binary releases for Linux, Windows, and macOS. Download the binary and&amp;nbsp;run &lt;code&gt;./loki -config.file=loki-config.yaml&lt;/code&gt;. However, Docker is strongly recommended for homelab use because it simplifies networking and&amp;nbsp;updates.&lt;/p&gt;
&lt;h3&gt;How do I forward logs from remote&amp;nbsp;servers?&lt;/h3&gt;
&lt;p&gt;Install Promtail on each remote server and point it to your central Loki instance. Ensure the Loki port (3100) is accessible over the network or via a &lt;span class="caps"&gt;VPN&lt;/span&gt; tunnel. For untrusted networks, place Loki behind a reverse proxy with &lt;span class="caps"&gt;TLS&lt;/span&gt; or use a WireGuard&amp;nbsp;tunnel.&lt;/p&gt;
&lt;h3&gt;Does Loki support&amp;nbsp;alerting?&lt;/h3&gt;
&lt;p&gt;Yes, via the Ruler component. You can define LogQL-based alert rules and send them to any Alertmanager-compatible receiver. For homelab use, alerting on error rates and container crashes is the most common&amp;nbsp;pattern.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Grafana Loki is the optimal log aggregation solution for homelab environments. It provides Prometheus-style labeling, deep Grafana integration, and a resource footprint that fits on a mini &lt;span class="caps"&gt;PC&lt;/span&gt; or Raspberry Pi. With Promtail, you can ingest Docker container logs, system logs, and application logs from multiple hosts. With LogQL and recording rules, you can query, alert, and visualize your infrastructure&amp;#8217;s&amp;nbsp;narrative.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Add the Loki data source to your existing Grafana&amp;nbsp;instance&lt;/li&gt;
&lt;li&gt;Configure Promtail to read application logs from specific&amp;nbsp;directories&lt;/li&gt;
&lt;li&gt;Create a Grafana dashboard showing error rate&amp;nbsp;trends&lt;/li&gt;
&lt;li&gt;Set up Alertmanager for critical log-based&amp;nbsp;alerts&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;installation&lt;/strong&gt;: hosting — &lt;span class="caps"&gt;VPS&lt;/span&gt; for offsite log aggregation or S3-compatible&amp;nbsp;storage&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;integration&lt;/strong&gt;: tool — Grafana Cloud subscription for managed Loki&amp;nbsp;hosting&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;alternatives&lt;/strong&gt;: tool — Datadog Vector or enterprise log&amp;nbsp;platforms&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;installation&lt;/code&gt; → setup_guide: &lt;a href="https://steadypub.com/2026/06/docker-compose-for-beginners/"&gt;Docker Compose for&amp;nbsp;beginners&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;integration&lt;/code&gt; → related_guide: &lt;a href="https://steadypub.com/2026/06/docker-monitoring-grafana-prometheus/"&gt;Prometheus + Grafana monitoring&amp;nbsp;setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;alternatives&lt;/code&gt; → comparison: &lt;a href="https://steadypub.com/2026/06/prometheus-vs-influxdb/"&gt;Prometheus vs&amp;nbsp;InfluxDB&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] What log stack do you run in your homelab? Loki, &lt;span class="caps"&gt;ELK&lt;/span&gt;, or something else? Let us&amp;nbsp;know.&lt;/li&gt;
&lt;li&gt;[newsletter] Get weekly monitoring, logging, and observability guides for&amp;nbsp;self-hosters.&lt;/li&gt;
&lt;li&gt;[internal_link] Next: learn how to &lt;a href="https://steadypub.com/2026/06/prometheus-alertmanager-setup/"&gt;set up Prometheus Alertmanager&lt;/a&gt; for your&amp;nbsp;homelab&lt;/li&gt;
&lt;/ul&gt;</content><category term="Monitoring"/><category term="grafana"/><category term="loki"/><category term="logs"/><category term="monitoring"/><category term="homelab"/><category term="self-hosted"/></entry><entry><title>Grafana + Prometheus Setup for Homelab: Complete Monitoring Stack</title><link href="https://steadypub.com/2026/06/grafana-prometheus-setup/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T06:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/grafana-prometheus-setup/</id><summary type="html">&lt;p&gt;Deploy the complete Grafana + Prometheus + Node Exporter + cAdvisor monitoring stack in Docker Compose. Includes scrape configs, dashboard provisioning, and&amp;nbsp;alerting.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~15 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelabbers building a monitoring stack from&amp;nbsp;scratch&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is Grafana +&amp;nbsp;Prometheus?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Grafana + Prometheus is the de facto standard for cloud-native monitoring. Prometheus collects metrics via &lt;span class="caps"&gt;HTTP&lt;/span&gt; scraping. Grafana visualizes them. Together, they provide a complete observability platform for your homelab: server health, container performance, network traffic, and application&amp;nbsp;metrics.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stack components:&lt;/strong&gt;
- &lt;strong&gt;Prometheus:&lt;/strong&gt; Time-series database and scraper
- &lt;strong&gt;Grafana:&lt;/strong&gt; Visualization and alerting &lt;span class="caps"&gt;UI&lt;/span&gt;
- &lt;strong&gt;Node Exporter:&lt;/strong&gt; Exposes Linux hardware and &lt;span class="caps"&gt;OS&lt;/span&gt; metrics
- &lt;strong&gt;cAdvisor:&lt;/strong&gt; Exposes Docker container metrics
- &lt;strong&gt;Alertmanager:&lt;/strong&gt; Routes fired alerts to&amp;nbsp;notifications&lt;/p&gt;
&lt;h3&gt;Why This Stack in&amp;nbsp;2026&lt;/h3&gt;
&lt;p&gt;The Prometheus ecosystem is larger than ever. Every major homelab tool (Proxmox, TrueNAS, Pi-hole, AdGuard Home, Syncthing) has a Prometheus exporter. Grafana&amp;#8217;s dashboard library (grafana.com/dashboards) has 10,000+ pre-built dashboards. The stack is mature, well-documented, and completely&amp;nbsp;free.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;h3&gt;Hardware&amp;nbsp;Requirements&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Minimum&lt;/th&gt;
&lt;th&gt;Recommended&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;2 cores&lt;/td&gt;
&lt;td&gt;4 cores&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;2 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;4 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;20 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;50 &lt;span class="caps"&gt;GB&lt;/span&gt; (for 15-day retention)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network&lt;/td&gt;
&lt;td&gt;1 GbE&lt;/td&gt;
&lt;td&gt;1 GbE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Software&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Docker Engine 24.0+ and Docker Compose&amp;nbsp;v2+&lt;/li&gt;
&lt;li&gt;A Linux host (Debian, Ubuntu, or Proxmox &lt;span class="caps"&gt;VM&lt;/span&gt;/&lt;span class="caps"&gt;LXC&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;Basic command-line&amp;nbsp;knowledge&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Knowledge&amp;nbsp;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Docker networking&amp;nbsp;concepts&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;YAML&lt;/span&gt;&amp;nbsp;syntax&lt;/li&gt;
&lt;li&gt;Basic Prometheus query language&amp;nbsp;(PromQL)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Create the Docker Compose&amp;nbsp;Stack&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Deploy Prometheus, Grafana, Node Exporter, and cAdvisor with a&amp;nbsp;single &lt;code&gt;docker-compose.yml&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Create a project&amp;nbsp;directory:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;~/monitoring/&lt;span class="o"&gt;{&lt;/span&gt;prometheus,grafana/config&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/monitoring
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Create &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;prometheus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;prom/prometheus:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;prometheus&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;9090:9090&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./prometheus:/etc/prometheus&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;prometheus-data:/prometheus&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--config.file=/etc/prometheus/prometheus.yml&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--storage.tsdb.path=/prometheus&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--storage.tsdb.retention.time=15d&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--web.console.libraries=/etc/prometheus/console_libraries&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--web.console.templates=/etc/prometheus/consoles&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--web.enable-lifecycle&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;monitoring&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;grafana&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;grafana/grafana:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;grafana&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3000:3000&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;GF_SECURITY_ADMIN_USER=admin&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;GF_SECURITY_ADMIN_PASSWORD=***      - GF_USERS_ALLOW_SIGN_UP=false&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;grafana-data:/var/lib/grafana&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./grafana/config/datasources.yml:/etc/grafana/provisioning/datasources/datasources.yml&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;prometheus&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;monitoring&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;node-exporter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;prom/node-exporter:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;node-exporter&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/proc:/host/proc:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/sys:/host/sys:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/:/rootfs:ro&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--path.procfs=/host/proc&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--path.rootfs=/rootfs&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--path.sysfs=/host/sys&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;monitoring&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;cadvisor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;gcr.io/cadvisor/cadvisor:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;cadvisor&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;privileged&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/:/rootfs:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/var/run:/var/run:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/sys:/sys:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/var/lib/docker:/var/lib/docker:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/dev/disk:/dev/disk:ro&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;devices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/dev/kmsg&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;monitoring&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;prometheus-data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;grafana-data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;monitoring&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;bridge&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Create &lt;code&gt;prometheus/prometheus.yml&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;global&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;scrape_interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;15s&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;evaluation_interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;15s&lt;/span&gt;

&lt;span class="nt"&gt;alerting&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;alertmanagers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[]&lt;/span&gt;

&lt;span class="nt"&gt;rule_files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/etc/prometheus/rules/*.yml&lt;/span&gt;

&lt;span class="nt"&gt;scrape_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;prometheus&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;localhost:9090&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;node-exporter&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;node-exporter:9100&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;cadvisor&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;cadvisor:8080&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;docker&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;cadvisor:8080&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Create &lt;code&gt;grafana/config/datasources.yml&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1&lt;/span&gt;

&lt;span class="nt"&gt;datasources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Prometheus&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;prometheus&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;access&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;proxy&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;http://prometheus:9090&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;isDefault&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;editable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Start the&amp;nbsp;stack:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Verify&amp;nbsp;services:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;ps
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Access Prometheus&amp;nbsp;at &lt;code&gt;http://your-server:9090&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Access Grafana&amp;nbsp;at &lt;code&gt;http://your-server:3000&lt;/code&gt; (admin / your&amp;nbsp;password)&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Step 2: Add Alerting&amp;nbsp;Rules&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Create Prometheus alerting rules for common homelab&amp;nbsp;scenarios.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Create &lt;code&gt;prometheus/rules/homelab.yml&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;homelab-alerts&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;30s&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;NodeDown&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;up{job=&amp;quot;node-exporter&amp;quot;} == 0&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1m&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;severity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;critical&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;annotations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Node&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;$labels.instance&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;is&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;down&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Prometheus&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;cannot&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;scrape&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;node-exporter&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;on&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;$labels.instance&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}.&amp;quot;&lt;/span&gt;

&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;HighCPUUsage&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;100 - (avg by(instance) (irate(node_cpu_seconds_total{mode=&amp;quot;idle&amp;quot;}[5m])) * 100) &amp;gt; 80&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;5m&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;severity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;warning&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;annotations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;High&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;CPU&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;usage&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;on&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;$labels.instance&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;CPU&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;usage&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;is&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;above&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;80%&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;more&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;than&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;5&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;minutes.&amp;quot;&lt;/span&gt;

&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;DiskSpaceLow&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;(node_filesystem_avail_bytes / node_filesystem_size_bytes) &amp;lt; 0.1&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;5m&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;severity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;critical&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;annotations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Disk&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;space&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;low&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;on&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;$labels.instance&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Less&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;than&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;10%&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;free&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;on&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;$labels.device&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}.&amp;quot;&lt;/span&gt;

&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MemoryHigh&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) &amp;gt; 0.85&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;5m&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;severity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;warning&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;annotations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;High&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;memory&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;usage&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;on&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;$labels.instance&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Memory&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;usage&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;is&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;above&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;85%.&amp;quot;&lt;/span&gt;

&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ContainerDown&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;absent(container_last_seen{name=~&amp;quot;nextcloud|jellyfin|plex|immich&amp;quot;})&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1m&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;severity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;critical&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;annotations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Critical&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;container&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;is&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;down&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;A&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;critical&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;container&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;is&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;not&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;running.&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Reload Prometheus&amp;nbsp;configuration:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-X&lt;span class="w"&gt; &lt;/span&gt;POST&lt;span class="w"&gt; &lt;/span&gt;http://localhost:9090/-/reload
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Check rules in Prometheus &lt;span class="caps"&gt;UI&lt;/span&gt;: &lt;strong&gt;Status&lt;/strong&gt; &amp;gt; &lt;strong&gt;Rules&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Step 3: Import&amp;nbsp;Dashboards&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Import pre-built dashboards for Node Exporter and&amp;nbsp;cAdvisor.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;In Grafana, click &lt;strong&gt;+&lt;/strong&gt; &amp;gt; &lt;strong&gt;Import&amp;nbsp;Dashboard&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Enter &lt;span class="caps"&gt;ID&lt;/span&gt; &lt;code&gt;1860&lt;/code&gt; (Node Exporter Full) and click &lt;strong&gt;Load&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Select the Prometheus data source and click &lt;strong&gt;Import&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Repeat for &lt;span class="caps"&gt;ID&lt;/span&gt; &lt;code&gt;14282&lt;/code&gt; (Docker and System&amp;nbsp;Monitoring)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Other useful dashboard&amp;nbsp;IDs:&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dashboard&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;ID&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Node Exporter Full&lt;/td&gt;
&lt;td&gt;1860&lt;/td&gt;
&lt;td&gt;Comprehensive Linux metrics&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Docker and System&lt;/td&gt;
&lt;td&gt;14282&lt;/td&gt;
&lt;td&gt;Container + host metrics&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Proxmox&lt;/td&gt;
&lt;td&gt;10347&lt;/td&gt;
&lt;td&gt;Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; metrics via Prometheus&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pi-hole&lt;/td&gt;
&lt;td&gt;10176&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt; query statistics&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AdGuard Home&lt;/td&gt;
&lt;td&gt;14400&lt;/td&gt;
&lt;td&gt;AdGuard Home metrics&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Speedtest&lt;/td&gt;
&lt;td&gt;13665&lt;/td&gt;
&lt;td&gt;Internet speed tracking&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Step 4: Add Additional&amp;nbsp;Exporters&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Monitor services that do not expose Prometheus metrics&amp;nbsp;natively.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Pi-hole&amp;nbsp;Exporter:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;pihole-exporter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ekofr/pihole-exporter:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pihole-exporter&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;PIHOLE_HOSTNAME=192.168.1.10&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;PIHOLE_API_TOKEN=***    ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;9617:9617&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;monitoring&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Add&amp;nbsp;to &lt;code&gt;prometheus.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;pihole&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;pihole-exporter:9617&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;&amp;nbsp;Exporter:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;proxmox-exporter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;prompve/prometheus-pve-exporter:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;proxmox-exporter&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;PVE_USER=root@pam&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;PVE_PASSWORD=***      - PVE_HOST=192.168.1.5&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;9221:9221&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;monitoring&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Add&amp;nbsp;to &lt;code&gt;prometheus.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;proxmox&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;proxmox-exporter:9221&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 5: Secure the&amp;nbsp;Stack&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Expose Grafana and Prometheus securely via reverse&amp;nbsp;proxy.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Add Traefik or Nginx Proxy Manager to the compose file, or use an existing reverse&amp;nbsp;proxy.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Nginx Proxy Manager&amp;nbsp;configuration:&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Add proxy&amp;nbsp;host: &lt;code&gt;grafana.yourdomain.com&lt;/code&gt; → &lt;code&gt;http://grafana:3000&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Add proxy&amp;nbsp;host: &lt;code&gt;prometheus.yourdomain.com&lt;/code&gt; → &lt;code&gt;http://prometheus:9090&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Request &lt;span class="caps"&gt;SSL&lt;/span&gt; certificates via Let&amp;#8217;s&amp;nbsp;Encrypt&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Restrict Prometheus&amp;nbsp;access:&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Do not expose Prometheus directly to the&amp;nbsp;internet&lt;/li&gt;
&lt;li&gt;Use a &lt;span class="caps"&gt;VPN&lt;/span&gt; or internal network for Prometheus&amp;nbsp;access&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Grafana can proxy Prometheus queries&amp;nbsp;safely&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Enable Grafana &lt;span class="caps"&gt;HTTPS&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;GF_SERVER_PROTOCOL=https&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;GF_SERVER_CERT_FILE=/etc/grafana/cert.pem&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;GF_SERVER_CERT_KEY=/etc/grafana/key.pem&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Use Recording Rules for Expensive&amp;nbsp;Queries&lt;/h3&gt;
&lt;p&gt;Queries that aggregate over large time ranges can be slow. Pre-compute them with recording&amp;nbsp;rules:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# prometheus/rules/recordings.yml&lt;/span&gt;
&lt;span class="nt"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;recordings&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;60s&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;record&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;instance:node_cpu:rate5m&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;avg by(instance) (irate(node_cpu_seconds_total{mode!=&amp;quot;idle&amp;quot;}[5m]))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 2: Separate Data&amp;nbsp;Retention&lt;/h3&gt;
&lt;p&gt;Prometheus defaults to 15 days. For long-term storage, use remote_write to VictoriaMetrics or&amp;nbsp;InfluxDB:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# prometheus.yml&lt;/span&gt;
&lt;span class="nt"&gt;remote_write&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;http://victoriametrics:8428/api/v1/write&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 3: Backup Your Grafana&amp;nbsp;Dashboards&lt;/h3&gt;
&lt;p&gt;Dashboards live in the Grafana database. Export them&amp;nbsp;regularly:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Export all dashboards&lt;/span&gt;
curl&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;-H&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Authorization: Bearer *** http://grafana:3000/api/search | \&lt;/span&gt;
&lt;span class="s2"&gt;  jq -r &amp;#39;.[].uri&amp;#39; | \&lt;/span&gt;
&lt;span class="s2"&gt;  while read uri; do&lt;/span&gt;
&lt;span class="s2"&gt;    curl -s -H &amp;quot;&lt;/span&gt;Authorization:&lt;span class="w"&gt; &lt;/span&gt;Bearer&lt;span class="w"&gt; &lt;/span&gt;***&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;http://grafana:3000/api/dashboards/&lt;/span&gt;&lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;//&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="p"&gt;/_&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.json&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Troubleshooting Common&amp;nbsp;Issues&lt;/h2&gt;
&lt;h3&gt;Problem 1: Prometheus Targets Show &amp;#8220;&lt;span class="caps"&gt;DOWN&lt;/span&gt;&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Check:&lt;/strong&gt; &lt;code&gt;http://prometheus:9090/targets&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;
- Ensure the target container is on&amp;nbsp;the &lt;code&gt;monitoring&lt;/code&gt; network
- Check firewall rules on the host
- Verify the scrape &lt;span class="caps"&gt;URL&lt;/span&gt; and port are&amp;nbsp;correct&lt;/p&gt;
&lt;h3&gt;Problem 2: cAdvisor Shows No&amp;nbsp;Containers&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Check:&lt;/strong&gt;&amp;nbsp;Run &lt;code&gt;docker logs cadvisor&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; cAdvisor requires privileged mode and access&amp;nbsp;to &lt;code&gt;/var/lib/docker&lt;/code&gt;. On Docker rootless, cAdvisor may not work. Use a non-rootless Docker setup or switch to the Docker daemon metrics&amp;nbsp;endpoint.&lt;/p&gt;
&lt;h3&gt;Problem 3: Grafana &amp;#8220;No Data&amp;#8221; for Some&amp;nbsp;Panels&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Check:&lt;/strong&gt; Open the panel in edit mode and run the query in &lt;strong&gt;Explore&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; The dashboard may use metric names that differ from your exporter version. Update the query or import a newer dashboard&amp;nbsp;version.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Grafana + Prometheus is the most powerful, flexible, and well-supported monitoring stack for homelabs. With Node Exporter for hardware metrics, cAdvisor for containers, and community dashboards for every tool, you can build a professional-grade observability platform in under an&amp;nbsp;hour.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Deploy the stack on your Proxmox host or a dedicated monitoring &lt;span class="caps"&gt;VM&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Import the Node Exporter Full and Docker&amp;nbsp;dashboards&lt;/li&gt;
&lt;li&gt;Add exporters for your critical services (Pi-hole, Proxmox,&amp;nbsp;TrueNAS)&lt;/li&gt;
&lt;li&gt;Set up Alertmanager for Slack/Telegram&amp;nbsp;notifications&lt;/li&gt;
&lt;li&gt;Backup your Grafana dashboards and Prometheus configuration to&amp;nbsp;Git&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mini PCs for monitoring:&lt;/strong&gt; Intel N100 with 16 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&amp;nbsp;(Amazon)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt;:&lt;/strong&gt; Hetzner for offsite monitoring&amp;nbsp;(referral)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Displays:&lt;/strong&gt; Wall-mounted tablets for Grafana kiosks&amp;nbsp;(Amazon)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;alertmanager&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;prometheus-alertmanager-setup.md&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dashboards&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;grafana-dashboard-homelab.md&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker-monitoring&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;docker-monitoring-grafana-prometheus.md&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;proxmox-exporter&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;proxmox-monitoring-guide.md&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] What does your monitoring stack look like? Share your Grafana screenshot&amp;nbsp;below.&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for our monitoring stack templates and exporter&amp;nbsp;updates.&lt;/li&gt;
&lt;li&gt;[internal_link] Ready to set up alerting? Read our &lt;a href="https://steadypub.com/2026/06/prometheus-alertmanager-setup/"&gt;Alertmanager setup guide&lt;/a&gt;&amp;nbsp;next.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Tutorials"/><category term="grafana prometheus setup"/><category term="homelab"/><category term="self-hosted"/><category term="monitoring"/></entry><entry><title>Home Server Docker Setup: Build a Self-Hosted Container Platform for 2026</title><link href="https://steadypub.com/2026/06/home-server-docker-setup/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T10:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/home-server-docker-setup/</id><summary type="html">&lt;p&gt;A step-by-step guide to building a Docker-based home server. Covers &lt;span class="caps"&gt;OS&lt;/span&gt; selection, Docker installation, storage, networking, and security&amp;nbsp;hardening.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~16 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab and self-hosting&amp;nbsp;enthusiasts&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is a Home Server Docker&amp;nbsp;Setup?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;A home server Docker setup is a dedicated machine — typically a mini &lt;span class="caps"&gt;PC&lt;/span&gt;, old desktop, or &lt;span class="caps"&gt;NAS&lt;/span&gt; — running Linux and Docker Engine to host self-hosted applications. Unlike running apps directly on the host &lt;span class="caps"&gt;OS&lt;/span&gt;, Docker containers encapsulate each service with its dependencies, enabling consistent deployment, easy updates, and rapid rollback. This is the dominant architecture in modern homelabs because it is portable, reproducible, and&amp;nbsp;resource-efficient.&lt;/p&gt;
&lt;h3&gt;Why Docker for a Home&amp;nbsp;Server?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Isolation&lt;/strong&gt;: A crashing application does not affect the host or other&amp;nbsp;services&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dependency Management&lt;/strong&gt;: Each container ships with its own libraries and&amp;nbsp;runtime&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reproducibility&lt;/strong&gt;:&amp;nbsp;A &lt;code&gt;docker-compose.yml&lt;/code&gt; file defines the entire stack; deploy it on any&amp;nbsp;machine&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Efficiency&lt;/strong&gt;: Containers share the host kernel, using less &lt;span class="caps"&gt;RAM&lt;/span&gt; and &lt;span class="caps"&gt;CPU&lt;/span&gt; than&amp;nbsp;VMs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ecosystem&lt;/strong&gt;: Thousands of pre-built images for homelab apps (Nextcloud, Plex, Pi-hole,&amp;nbsp;etc.)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;h3&gt;Hardware&amp;nbsp;Requirements&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Minimum&lt;/th&gt;
&lt;th&gt;Recommended&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;2 cores&lt;/td&gt;
&lt;td&gt;4+ cores&lt;/td&gt;
&lt;td&gt;Intel N100, i3, or Ryzen 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;4 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;8–16 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;More &lt;span class="caps"&gt;RAM&lt;/span&gt; = more containers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;128 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1 &lt;span class="caps"&gt;TB&lt;/span&gt; NVMe &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Containers are I/O-heavy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network&lt;/td&gt;
&lt;td&gt;1 Gbps&lt;/td&gt;
&lt;td&gt;2.5 Gbps&lt;/td&gt;
&lt;td&gt;For &lt;span class="caps"&gt;NAS&lt;/span&gt; or media streaming&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Power&lt;/td&gt;
&lt;td&gt;~15W&lt;/td&gt;
&lt;td&gt;35–65W&lt;/td&gt;
&lt;td&gt;Mini PCs are ideal&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Recommended hardware: Intel N100 mini &lt;span class="caps"&gt;PC&lt;/span&gt; (Beelink U59 Pro, Minisforum &lt;span class="caps"&gt;UN100&lt;/span&gt;), used ThinkCentre M720q, or a refurbished Dell&amp;nbsp;OptiPlex.&lt;/p&gt;
&lt;h3&gt;Software&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Ubuntu Server 22.04/24.04 &lt;span class="caps"&gt;LTS&lt;/span&gt;, Debian 12, or Proxmox (with an &lt;span class="caps"&gt;LXC&lt;/span&gt;&amp;nbsp;container)&lt;/li&gt;
&lt;li&gt;Docker Engine&amp;nbsp;24.0+&lt;/li&gt;
&lt;li&gt;Docker Compose plugin&amp;nbsp;v2.x&lt;/li&gt;
&lt;li&gt;A router with &lt;span class="caps"&gt;DHCP&lt;/span&gt; reservation or static &lt;span class="caps"&gt;IP&lt;/span&gt;&amp;nbsp;support&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Install the Operating&amp;nbsp;System&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Prepare a minimal, stable Linux base for&amp;nbsp;Docker.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Download Ubuntu Server 24.04 &lt;span class="caps"&gt;LTS&lt;/span&gt; from&amp;nbsp;ubuntu.com&lt;/li&gt;
&lt;li&gt;Flash it to a &lt;span class="caps"&gt;USB&lt;/span&gt; drive with Ventoy or&amp;nbsp;Rufus&lt;/li&gt;
&lt;li&gt;Install on the server&amp;nbsp;with:&lt;/li&gt;
&lt;li&gt;Minimal packages (no &lt;span class="caps"&gt;GUI&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;OpenSSH&amp;nbsp;enabled&lt;/li&gt;
&lt;li&gt;A static &lt;span class="caps"&gt;IP&lt;/span&gt; or &lt;span class="caps"&gt;DHCP&lt;/span&gt;&amp;nbsp;reservation&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# After first boot, update the system&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;upgrade&lt;span class="w"&gt; &lt;/span&gt;-y

&lt;span class="c1"&gt;# Install essential tools&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;wget&lt;span class="w"&gt; &lt;/span&gt;vim&lt;span class="w"&gt; &lt;/span&gt;htop&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;ufw
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 2: Install Docker&amp;nbsp;Engine&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Install the official Docker repository, not the outdated distro&amp;nbsp;package.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Remove old versions&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pkg&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;docker.io&lt;span class="w"&gt; &lt;/span&gt;docker-doc&lt;span class="w"&gt; &lt;/span&gt;docker-compose&lt;span class="w"&gt; &lt;/span&gt;docker-compose-v2&lt;span class="w"&gt; &lt;/span&gt;podman-docker&lt;span class="w"&gt; &lt;/span&gt;containerd&lt;span class="w"&gt; &lt;/span&gt;runc&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;remove&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$pkg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;done&lt;/span&gt;

&lt;span class="c1"&gt;# Add Docker&amp;#39;s official GPG key&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;update
sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;ca-certificates&lt;span class="w"&gt; &lt;/span&gt;curl
sudo&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0755&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;/etc/apt/keyrings
sudo&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-fsSL&lt;span class="w"&gt; &lt;/span&gt;https://download.docker.com/linux/ubuntu/gpg&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;/etc/apt/keyrings/docker.asc
sudo&lt;span class="w"&gt; &lt;/span&gt;chmod&lt;span class="w"&gt; &lt;/span&gt;a+r&lt;span class="w"&gt; &lt;/span&gt;/etc/apt/keyrings/docker.asc

&lt;span class="c1"&gt;# Add the repository&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;deb [arch=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;dpkg&lt;span class="w"&gt; &lt;/span&gt;--print-architecture&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;/etc/os-release&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$VERSION_CODENAME&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; stable&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;tee&lt;span class="w"&gt; &lt;/span&gt;/etc/apt/sources.list.d/docker.list&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/dev/null

&lt;span class="c1"&gt;# Install Docker&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;update
sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;docker-ce&lt;span class="w"&gt; &lt;/span&gt;docker-ce-cli&lt;span class="w"&gt; &lt;/span&gt;containerd.io&lt;span class="w"&gt; &lt;/span&gt;docker-buildx-plugin&lt;span class="w"&gt; &lt;/span&gt;docker-compose-plugin

&lt;span class="c1"&gt;# Add user to docker group&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;usermod&lt;span class="w"&gt; &lt;/span&gt;-aG&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$USER&lt;/span&gt;
newgrp&lt;span class="w"&gt; &lt;/span&gt;docker

&lt;span class="c1"&gt;# Verify&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;hello-world
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 3: Configure&amp;nbsp;Storage&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Set up persistent storage for container data with proper performance and backup&amp;nbsp;considerations.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Create a directory structure for your homelab&lt;/span&gt;
mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;~/homelab/&lt;span class="o"&gt;{&lt;/span&gt;stacks,backups,media,configs&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# For large media libraries, mount an external drive or NAS&lt;/span&gt;
&lt;span class="c1"&gt;# Example: mount a TrueNAS NFS share&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;nfs-common
sudo&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;/mnt/nas-media
sudo&lt;span class="w"&gt; &lt;/span&gt;mount&lt;span class="w"&gt; &lt;/span&gt;-t&lt;span class="w"&gt; &lt;/span&gt;nfs&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.1.10:/mnt/tank/media&lt;span class="w"&gt; &lt;/span&gt;/mnt/nas-media

&lt;span class="c1"&gt;# Add to /etc/fstab for persistence&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;192.168.1.10:/mnt/tank/media /mnt/nas-media nfs defaults 0 0&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;tee&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;/etc/fstab

&lt;span class="c1"&gt;# For databases, use a fast local SSD&lt;/span&gt;
mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;~/homelab/stacks/db
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 4: Harden the&amp;nbsp;Server&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Apply basic security hardening before exposing any&amp;nbsp;services.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Configure UFW&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;ufw&lt;span class="w"&gt; &lt;/span&gt;default&lt;span class="w"&gt; &lt;/span&gt;deny&lt;span class="w"&gt; &lt;/span&gt;incoming
sudo&lt;span class="w"&gt; &lt;/span&gt;ufw&lt;span class="w"&gt; &lt;/span&gt;default&lt;span class="w"&gt; &lt;/span&gt;allow&lt;span class="w"&gt; &lt;/span&gt;outgoing
sudo&lt;span class="w"&gt; &lt;/span&gt;ufw&lt;span class="w"&gt; &lt;/span&gt;allow&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;22&lt;/span&gt;/tcp&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# SSH&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;ufw&lt;span class="w"&gt; &lt;/span&gt;allow&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;/tcp&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# HTTP&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;ufw&lt;span class="w"&gt; &lt;/span&gt;allow&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;443&lt;/span&gt;/tcp&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;# HTTPS&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;ufw&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;enable&lt;/span&gt;

&lt;span class="c1"&gt;# Harden SSH&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;sed&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;s/#PermitRootLogin prohibit-password/PermitRootLogin no/&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/ssh/sshd_config
sudo&lt;span class="w"&gt; &lt;/span&gt;sed&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;s/#PasswordAuthentication yes/PasswordAuthentication no/&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/ssh/sshd_config
sudo&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;restart&lt;span class="w"&gt; &lt;/span&gt;sshd

&lt;span class="c1"&gt;# Enable automatic updates&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;unattended-upgrades
sudo&lt;span class="w"&gt; &lt;/span&gt;dpkg-reconfigure&lt;span class="w"&gt; &lt;/span&gt;-plow&lt;span class="w"&gt; &lt;/span&gt;unattended-upgrades

&lt;span class="c1"&gt;# Configure Docker daemon for security&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;tee&lt;span class="w"&gt; &lt;/span&gt;/etc/docker/daemon.json&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&amp;lt;EOF&lt;/span&gt;
&lt;span class="s"&gt;{&lt;/span&gt;
&lt;span class="s"&gt;  &amp;quot;live-restore&amp;quot;: true,&lt;/span&gt;
&lt;span class="s"&gt;  &amp;quot;log-driver&amp;quot;: &amp;quot;json-file&amp;quot;,&lt;/span&gt;
&lt;span class="s"&gt;  &amp;quot;log-opts&amp;quot;: {&lt;/span&gt;
&lt;span class="s"&gt;    &amp;quot;max-size&amp;quot;: &amp;quot;10m&amp;quot;,&lt;/span&gt;
&lt;span class="s"&gt;    &amp;quot;max-file&amp;quot;: &amp;quot;3&amp;quot;&lt;/span&gt;
&lt;span class="s"&gt;  },&lt;/span&gt;
&lt;span class="s"&gt;  &amp;quot;no-new-privileges&amp;quot;: true,&lt;/span&gt;
&lt;span class="s"&gt;  &amp;quot;userland-proxy&amp;quot;: false&lt;/span&gt;
&lt;span class="s"&gt;}&lt;/span&gt;
&lt;span class="s"&gt;EOF&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;restart&lt;span class="w"&gt; &lt;/span&gt;docker
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 5: Deploy Your First&amp;nbsp;Stack&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Deploy a foundational stack: a reverse proxy, a dashboard, and a monitoring&amp;nbsp;agent.&lt;/p&gt;
&lt;h3&gt;docker-compose.yml&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;traefik&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;traefik:v3.0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;traefik&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--api.dashboard=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--providers.docker=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--providers.docker.exposedbydefault=false&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--entrypoints.web.address=:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--entrypoints.websecure.address=:443&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--certificatesresolvers.letsencrypt.acme.tlschallenge=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--certificatesresolvers.letsencrypt.acme.email=you@example.com&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;80:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;443:443&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/var/run/docker.sock:/var/run/docker.sock:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./letsencrypt:/letsencrypt&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.enable=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.traefik.rule=Host(`traefik.local`)&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.traefik.service=api@internal&amp;quot;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;whoami&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;traefik/whoami&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.enable=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.whoami.rule=Host(`whoami.local`)&amp;quot;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;portainer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;portainer/portainer-ce:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;portainer&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;9000:9000&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/var/run/docker.sock:/var/run/docker.sock&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;portainer_data:/data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.enable=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.portainer.rule=Host(`portainer.local`)&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;portainer_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Deploy&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/homelab/stacks
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Use a Reverse Proxy from Day&amp;nbsp;One&lt;/h3&gt;
&lt;p&gt;Even for internal services, a reverse proxy (Traefik or Nginx Proxy Manager) provides clean URLs, automatic &lt;span class="caps"&gt;HTTPS&lt;/span&gt;, and centralized access control. Do not expose raw&amp;nbsp;ports.&lt;/p&gt;
&lt;h3&gt;Tip 2: Version-Control Your Compose&amp;nbsp;Files&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/homelab
&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;init
&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt; &lt;/span&gt;.
&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;commit&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Initial homelab stack&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This creates a recoverable history. If a change breaks a&amp;nbsp;service, &lt;code&gt;git checkout&lt;/code&gt; the previous&amp;nbsp;version.&lt;/p&gt;
&lt;h3&gt;Tip 3: Backup Named&amp;nbsp;Volumes&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Backup all named volumes&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;volume&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-q&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;read&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;vol&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;--rm&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$vol&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;:/data&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;~/homelab/backups:/backup&lt;span class="w"&gt; &lt;/span&gt;alpine&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;tar&lt;span class="w"&gt; &lt;/span&gt;czf&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/backup/&lt;/span&gt;&lt;span class="nv"&gt;$vol&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;date&lt;span class="w"&gt; &lt;/span&gt;+%F&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;.tar.gz&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-C&lt;span class="w"&gt; &lt;/span&gt;/data&lt;span class="w"&gt; &lt;/span&gt;.
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Automate with&amp;nbsp;cron.&lt;/p&gt;
&lt;h3&gt;Tip 4: Monitor Resource&amp;nbsp;Usage&lt;/h3&gt;
&lt;p&gt;Install &lt;code&gt;ctop&lt;/code&gt; for real-time container&amp;nbsp;stats:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;--rm&lt;span class="w"&gt; &lt;/span&gt;-ti&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--name&lt;span class="o"&gt;=&lt;/span&gt;ctop&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--volume&lt;span class="w"&gt; &lt;/span&gt;/var/run/docker.sock:/var/run/docker.sock:ro&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;quay.io/vektorlab/ctop:latest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Troubleshooting Common&amp;nbsp;Issues&lt;/h2&gt;
&lt;h3&gt;Problem 1: Docker Service Fails to&amp;nbsp;Start&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Check logs&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;journalctl&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="w"&gt; &lt;/span&gt;docker.service

&lt;span class="c1"&gt;# Verify daemon.json syntax&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;python3&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;json.tool&lt;span class="w"&gt; &lt;/span&gt;/etc/docker/daemon.json
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Problem 2: Container Cannot Reach the&amp;nbsp;Internet&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Check if Docker&amp;#39;s iptables rules are present&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;iptables&lt;span class="w"&gt; &lt;/span&gt;-L&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;DOCKER

&lt;span class="c1"&gt;# Restart Docker to recreate rules&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;restart&lt;span class="w"&gt; &lt;/span&gt;docker
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Problem 3: Permission Denied on&amp;nbsp;Volumes&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Check container user ID&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;container&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;id

&lt;span class="c1"&gt;# Fix host permissions&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;chown&lt;span class="w"&gt; &lt;/span&gt;-R&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;:1000&lt;span class="w"&gt; &lt;/span&gt;~/homelab/stacks/&amp;lt;service&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;A home server running Docker is the most flexible, efficient, and maintainable homelab architecture. With a minimal Linux base, official Docker packages, proper storage, and basic hardening, you can host a dozen services on a $150 mini &lt;span class="caps"&gt;PC&lt;/span&gt;. The key to success is declarative configuration (Compose files), version control, and automated&amp;nbsp;backups.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Deploy additional services (Nextcloud, Immich,&amp;nbsp;Pi-hole)&lt;/li&gt;
&lt;li&gt;Set up a monitoring stack (Prometheus +&amp;nbsp;Grafana)&lt;/li&gt;
&lt;li&gt;Configure a &lt;span class="caps"&gt;VPN&lt;/span&gt; (WireGuard, Tailscale) for remote&amp;nbsp;access&lt;/li&gt;
&lt;li&gt;Explore Docker Swarm for multi-node&amp;nbsp;scaling&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;prerequisites&lt;/strong&gt;: hardware — Mini PCs, SSDs, &lt;span class="caps"&gt;NAS&lt;/span&gt;&amp;nbsp;devices&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;step-1&lt;/strong&gt;: tool — Proxmox, Ubuntu Pro&amp;nbsp;subscriptions&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;pro-tips&lt;/strong&gt;: service — &lt;span class="caps"&gt;VPN&lt;/span&gt; services, cloud backup&amp;nbsp;providers&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;what-is&lt;/code&gt; → related_comparison: &lt;a href="https://steadypub.com/2026/06/proxmox-vs-virtualbox-for-beginners/"&gt;Proxmox vs&amp;nbsp;VirtualBox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prerequisites&lt;/code&gt; → setup_guide: &lt;a href="https://steadypub.com/2026/06/intel-n100-mini-pc-homelab/"&gt;Intel N100 mini &lt;span class="caps"&gt;PC&lt;/span&gt;&amp;nbsp;homelab&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → next_steps: &lt;a href="https://steadypub.com/2026/06/docker-compose-tutorial/"&gt;Docker Compose&amp;nbsp;tutorial&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] What hardware runs your home server? Share your specs and power&amp;nbsp;draw.&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for weekly home server and Docker deployment&amp;nbsp;guides.&lt;/li&gt;
&lt;li&gt;[internal_link] Next: learn &lt;a href="https://steadypub.com/2026/06/docker-compose-tutorial/"&gt;Docker Compose from&amp;nbsp;scratch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Tutorials"/><category term="home server"/><category term="docker"/><category term="homelab"/><category term="self-hosted"/><category term="containerization"/></entry><entry><title>Homelab Ethernet Cabling: A Complete Guide for Self-Hosters</title><link href="https://steadypub.com/2026/06/homelab-ethernet-cabling/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T06:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/homelab-ethernet-cabling/</id><summary type="html">&lt;p&gt;Real cable specs, tools, termination techniques, and layout planning for homelab Ethernet networks from 1 GbE to 10&amp;nbsp;GbE.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~12 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelabbers building or upgrading their physical&amp;nbsp;network&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is Homelab Ethernet&amp;nbsp;Cabling?&lt;/h2&gt;
&lt;h3&gt;What Exactly Is&amp;nbsp;It?&lt;/h3&gt;
&lt;p&gt;Ethernet cabling is the physical layer of your homelab network. While Wi-Fi is convenient for phones and laptops, a reliable homelab runs on wired connections: servers, &lt;span class="caps"&gt;NAS&lt;/span&gt; devices, switches, routers, and access points all need Cat5e, Cat6, or Cat6a cables to move data at gigabit speeds and beyond. Good cabling is invisible when it works and a nightmare when it&amp;nbsp;fails.&lt;/p&gt;
&lt;h3&gt;A Brief&amp;nbsp;History&lt;/h3&gt;
&lt;p&gt;Category-rated twisted-pair cabling has been the standard for Ethernet since the 1990s:
- &lt;strong&gt;Cat5&lt;/strong&gt; (1995): 100 MHz, up to 100 Mbps. Obsolete.
- &lt;strong&gt;Cat5e&lt;/strong&gt; (2001): 100 MHz, up to 1 Gbps. Still viable for most homelabs.
- &lt;strong&gt;Cat6&lt;/strong&gt; (2002): 250 MHz, up to 1 Gbps at 100m, 10 Gbps at 55m. The modern default.
- &lt;strong&gt;Cat6a&lt;/strong&gt; (2008): 500 MHz, up to 10 Gbps at 100m. Required for 10GbE over copper.
- &lt;strong&gt;Cat7/Cat8&lt;/strong&gt; (2010/2013): Shielded, 600–2000 MHz, 25–40 Gbps. Overkill for homelabs but&amp;nbsp;future-proof.&lt;/p&gt;
&lt;h3&gt;Why It Matters&amp;nbsp;Today&lt;/h3&gt;
&lt;p&gt;In 2026, 2.5 GbE and 10 GbE are mainstream in homelabs. A single 4K Plex stream consumes ~25 Mbps; 10 GbE backups between a &lt;span class="caps"&gt;NAS&lt;/span&gt; and a server can saturate a link. Cheap Cat5e will not reliably carry 10 Gbps. The cabling you install today will outlive the devices you plug into&amp;nbsp;it.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why Proper Cabling&amp;nbsp;Matters&lt;/h2&gt;
&lt;h3&gt;Benefit 1: Stability Over&amp;nbsp;Wi-Fi&lt;/h3&gt;
&lt;p&gt;Wi-Fi is shared spectrum. Neighbors, microwaves, baby monitors, and Bluetooth all interfere. A wired Ethernet connection provides deterministic latency, zero jitter, and full duplex bandwidth. For Proxmox clusters, iSCSI storage, and &lt;span class="caps"&gt;SMB&lt;/span&gt; file transfers, Wi-Fi is not an&amp;nbsp;option.&lt;/p&gt;
&lt;h3&gt;Benefit 2: PoE Power&amp;nbsp;Delivery&lt;/h3&gt;
&lt;p&gt;Power over Ethernet (PoE) eliminates wall adapters for access points, cameras, and IoT devices. A single Cat6 cable can carry 1 Gbps of data + 15–90 W of power. A centrally located PoE switch (like a &lt;span class="caps"&gt;TP&lt;/span&gt;-Link Omada or Ubiquiti UniFi switch) simplifies cable management and power&amp;nbsp;distribution.&lt;/p&gt;
&lt;h3&gt;Benefit 3:&amp;nbsp;Future-Proofing&lt;/h3&gt;
&lt;p&gt;Running a cable is 90% labor. The copper is cheap. Installing Cat6a instead of Cat5e costs ~20% more in materials but adds a 10-year runway for 10 GbE upgrades without&amp;nbsp;rewiring.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Core&amp;nbsp;Principles&lt;/h2&gt;
&lt;h3&gt;Principle 1: Use the Right Category for the&amp;nbsp;Speed&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Speed&lt;/th&gt;
&lt;th&gt;Cable Required&lt;/th&gt;
&lt;th&gt;Max Distance&lt;/th&gt;
&lt;th&gt;Typical Use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;100 Mbps&lt;/td&gt;
&lt;td&gt;Cat5e&lt;/td&gt;
&lt;td&gt;100m&lt;/td&gt;
&lt;td&gt;Legacy IoT, &lt;span class="caps"&gt;IP&lt;/span&gt; cameras&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1 Gbps&lt;/td&gt;
&lt;td&gt;Cat5e / Cat6&lt;/td&gt;
&lt;td&gt;100m&lt;/td&gt;
&lt;td&gt;General homelab, servers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2.5 Gbps&lt;/td&gt;
&lt;td&gt;Cat5e (good quality) / Cat6&lt;/td&gt;
&lt;td&gt;100m&lt;/td&gt;
&lt;td&gt;Modern &lt;span class="caps"&gt;NAS&lt;/span&gt;, mini PCs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5 Gbps&lt;/td&gt;
&lt;td&gt;Cat6&lt;/td&gt;
&lt;td&gt;100m&lt;/td&gt;
&lt;td&gt;High-end workstations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10 Gbps&lt;/td&gt;
&lt;td&gt;Cat6a / Cat7&lt;/td&gt;
&lt;td&gt;100m&lt;/td&gt;
&lt;td&gt;Server interconnects, 10GbE switches&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;25 Gbps+&lt;/td&gt;
&lt;td&gt;Cat8 / fiber&lt;/td&gt;
&lt;td&gt;30m&lt;/td&gt;
&lt;td&gt;Data center, not homelab&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Rule of thumb:&lt;/strong&gt; For new installations in 2026, use &lt;strong&gt;Cat6&lt;/strong&gt; for runs under 55m and &lt;strong&gt;Cat6a&lt;/strong&gt; for runs over 55m or where 10 GbE is planned. Cat5e is acceptable for existing runs but do not install new&amp;nbsp;Cat5e.&lt;/p&gt;
&lt;h3&gt;Principle 2: Terminate&amp;nbsp;Properly&lt;/h3&gt;
&lt;p&gt;A bad crimp is the #1 cause of &amp;#8220;intermittent&amp;#8221; network issues. Poor contact between the copper and the &lt;span class="caps"&gt;RJ45&lt;/span&gt; pin creates resistance, which increases with temperature and&amp;nbsp;vibration.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tools you need:&lt;/strong&gt;
- &lt;strong&gt;Cable tester:&lt;/strong&gt; A $15 wire mapper or a $60 Klein Tools &lt;span class="caps"&gt;LAN&lt;/span&gt; tester. Test every cable after termination.
- &lt;strong&gt;Crimp tool:&lt;/strong&gt; Ratchet-style &lt;span class="caps"&gt;RJ45&lt;/span&gt; crimpers are ~$20. Pass-through connectors make the job easier for beginners.
- &lt;strong&gt;Cable stripper:&lt;/strong&gt; A rotary stripper ($10) prevents nicking the inner conductors.
- &lt;strong&gt;Punch-down tool:&lt;/strong&gt; For keystone jacks and patch panels. $15 for a basic impact&amp;nbsp;tool.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Wiring standards:&lt;/strong&gt; Use &lt;strong&gt;&lt;span class="caps"&gt;T568B&lt;/span&gt;&lt;/strong&gt; for all terminations. It is the dominant standard in North America and most of the world. &lt;span class="caps"&gt;T568A&lt;/span&gt; is electrically identical but less common. Mixing A and B on the same cable creates a crossover cable, which modern Auto-&lt;span class="caps"&gt;MDIX&lt;/span&gt; handles but should be avoided&amp;nbsp;intentionally.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pin&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;T568B&lt;/span&gt; Color&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;T568A&lt;/span&gt; Color&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;White/Orange&lt;/td&gt;
&lt;td&gt;White/Green&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Orange&lt;/td&gt;
&lt;td&gt;Green&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;White/Green&lt;/td&gt;
&lt;td&gt;White/Orange&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Blue&lt;/td&gt;
&lt;td&gt;Blue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;White/Blue&lt;/td&gt;
&lt;td&gt;White/Blue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Green&lt;/td&gt;
&lt;td&gt;Orange&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;White/Brown&lt;/td&gt;
&lt;td&gt;White/Brown&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;Brown&lt;/td&gt;
&lt;td&gt;Brown&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Principle 3: Plan Your Cable&amp;nbsp;Runs&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;The &amp;#8220;home run&amp;#8221; model:&lt;/strong&gt; Every cable runs from a central location (network rack or patch panel) to an endpoint. No daisy-chaining. This gives you maximum flexibility for reconfiguring VLANs and&amp;nbsp;troubleshooting.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Planning checklist:&lt;/strong&gt;
1. Measure each run with a string, then add 10% for service loops.
2. Avoid running parallel to electrical wiring within 12 inches. If you must cross, do it at 90 degrees.
3. Use J-hooks or cable trays in unfinished spaces. Do not staple cables tight—twisted pair needs some slack to maintain its geometry.
4. Label both ends of every cable. A $10 label maker pays for itself in frustration saved.
5. Leave a 3-foot service loop at each end for&amp;nbsp;re-termination.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Applying This to Your&amp;nbsp;Homelab&lt;/h2&gt;
&lt;h3&gt;Homelab Setup Example: Apartment&amp;nbsp;Lab&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Constraints:&lt;/strong&gt; No permanent modifications, rented space, limited&amp;nbsp;closet.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Use flat Cat6 cables along baseboards, under doors, and behind furniture. They are ~3mm thick, paintable, and do not require drilling. A 10-pack of 10-foot flat Cat6 cables costs $15. Use command strips to attach them to&amp;nbsp;walls.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Layout:&lt;/strong&gt;
- 1x cable from router to central mini &lt;span class="caps"&gt;PC&lt;/span&gt; (Proxmox host)
- 1x cable from router to &lt;span class="caps"&gt;NAS&lt;/span&gt;
- 1x cable from router to desk workstation
- 1x cable from router to living room &lt;span class="caps"&gt;TV&lt;/span&gt; (for Plex/shield)
- 1x cable from PoE switch to ceiling-mounted access&amp;nbsp;point&lt;/p&gt;
&lt;h3&gt;Homelab Setup Example: Rack&amp;nbsp;Lab&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Constraints:&lt;/strong&gt; Dedicated rack, permanent installation, future 10&amp;nbsp;GbE.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Install a 24-port patch panel at the top of the rack. Run Cat6a from the patch panel to wall jacks in adjacent rooms. Use color-coded patch cables (red = management, blue = production, yellow = IoT) in the&amp;nbsp;rack.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rack cable management:&lt;/strong&gt;
- Horizontal cable managers (1U) keep patch cables orderly.
- Velcro straps (not zip ties) allow easy reconfiguration.
- 6-inch patch cables for switch-to-patch-panel connections minimize clutter.
- A brush panel (1U) at the rear allows cable entry without dust&amp;nbsp;intrusion.&lt;/p&gt;
&lt;h3&gt;Practical Steps: Making Your First&amp;nbsp;Cable&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Measure and cut:&lt;/strong&gt; Cut cable to length + 2&amp;nbsp;inches.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Strip:&lt;/strong&gt; Use the rotary stripper to remove 1.5 inches of jacket. Do not nick the&amp;nbsp;pairs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Untwist:&lt;/strong&gt; Untwist the pairs and arrange them in &lt;span class="caps"&gt;T568B&lt;/span&gt;&amp;nbsp;order.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Trim:&lt;/strong&gt; Align the wires and trim them to 0.5 inches from the&amp;nbsp;jacket.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Insert:&lt;/strong&gt; Push the wires into the &lt;span class="caps"&gt;RJ45&lt;/span&gt; connector until you see the copper tips in the clear&amp;nbsp;plastic.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Crimp:&lt;/strong&gt; Use the ratchet crimper. One firm squeeze until the ratchet&amp;nbsp;releases.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Test:&lt;/strong&gt; Plug both ends into a cable tester. Verify all 8 pins light up in&amp;nbsp;order.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# On Linux, verify link speed after plugging in&lt;/span&gt;
ethtool&lt;span class="w"&gt; &lt;/span&gt;eth0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-E&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Speed|Duplex&amp;quot;&lt;/span&gt;
&lt;span class="c1"&gt;# Expected: Speed: 10000Mb/s, Duplex: Full&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Common Mistakes to&amp;nbsp;Avoid&lt;/h2&gt;
&lt;h3&gt;Mistake 1: Mixing Shielded and Unshielded&amp;nbsp;Cable&lt;/h3&gt;
&lt;p&gt;Shielded (&lt;span class="caps"&gt;STP&lt;/span&gt;/&lt;span class="caps"&gt;FTP&lt;/span&gt;) cable requires shielded connectors, shielded patch panels, and proper grounding. If any component in the chain is unshielded, the shielding is worse than useless—it becomes an antenna. For most homelabs, unshielded (&lt;span class="caps"&gt;UTP&lt;/span&gt;) Cat6 is perfectly adequate. Use shielded only if you have industrial &lt;span class="caps"&gt;EMI&lt;/span&gt; sources (welding equipment, large motors)&amp;nbsp;nearby.&lt;/p&gt;
&lt;h3&gt;Mistake 2: Bending Radius&amp;nbsp;Violations&lt;/h3&gt;
&lt;p&gt;Ethernet cable has a minimum bend radius: roughly 4x the cable diameter. For standard Cat6, that is ~1 inch (25mm). A sharp 90-degree bend inside a wall box or rack can damage the internal twisted pairs and degrade performance. Use bend radius control clips or&amp;nbsp;D-rings.&lt;/p&gt;
&lt;h3&gt;Mistake 3: Using &lt;span class="caps"&gt;CCA&lt;/span&gt; (Copper-Clad Aluminum)&amp;nbsp;Cable&lt;/h3&gt;
&lt;p&gt;&lt;span class="caps"&gt;CCA&lt;/span&gt; cable is aluminum with a thin copper coating. It is cheaper and lighter but has higher resistance and is brittle. It does not meet &lt;span class="caps"&gt;ANSI&lt;/span&gt;/&lt;span class="caps"&gt;TIA&lt;/span&gt; standards. It will overheat under PoE load and may not certify for gigabit. Always buy pure copper cable (look for &amp;#8220;solid bare copper&amp;#8221; or &amp;#8220;&lt;span class="caps"&gt;BC&lt;/span&gt;&amp;#8221; in the&amp;nbsp;spec).&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Ethernet cabling is the foundation of every reliable homelab. In 2026, Cat6 is the safe default for new installations, with Cat6a reserved for 10 GbE runs. Proper termination, testing, and cable management prevent the intermittent failures that ruin weekends. Spend the extra $20 on a cable tester and pure copper&amp;nbsp;cable.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Inventory your existing cables and identify Cat5e runs that need&amp;nbsp;upgrading.&lt;/li&gt;
&lt;li&gt;Buy a cable tester, crimp tool, and a box of Cat6&amp;nbsp;cable.&lt;/li&gt;
&lt;li&gt;Draw a floor plan and plan your home runs to a central patch&amp;nbsp;panel.&lt;/li&gt;
&lt;li&gt;Label everything. Future-you will thank&amp;nbsp;present-you.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cable tools:&lt;/strong&gt; Klein Tools, TRENDnet cable testers&amp;nbsp;(Amazon)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bulk cable:&lt;/strong&gt; Monoprice, trueCABLE, Cable Matters&amp;nbsp;(Amazon)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Patch panels:&lt;/strong&gt; Cable Matters, TRENDnet 24-port panels&amp;nbsp;(Amazon)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Network racks:&lt;/strong&gt; StarTech, NavePoint&amp;nbsp;(Amazon)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;cable-planning&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;homelab-networking-basics.md&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rack-setup&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;homelab-rack-setup.md&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;speed-categories&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;managed-switch-homelab.md&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;poe&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;tp-link-omada-vs-unifi.md&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] What&amp;#8217;s the longest cable run in your homelab? Share your wiring horror stories&amp;nbsp;below.&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for our network infrastructure deep-dives and seasonal gear&amp;nbsp;recommendations.&lt;/li&gt;
&lt;li&gt;[internal_link] Ready to choose a switch? Read our &lt;a href="https://steadypub.com/2026/06/managed-switch-homelab/"&gt;managed switch guide&lt;/a&gt;&amp;nbsp;next.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Concepts"/><category term="homelab ethernet cabling"/><category term="self-hosted"/><category term="homelab"/><category term="networking"/></entry><entry><title>Best Network Switches for Homelab in 2026: 1GbE to 10GbE</title><link href="https://steadypub.com/2026/06/homelab-network-switch-recommendations/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T10:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/homelab-network-switch-recommendations/</id><summary type="html">&lt;p&gt;The best Ethernet switches for homelab networking. Compare managed, unmanaged, 1GbE, 2.5GbE, and 10GbE options from UniFi, &lt;span class="caps"&gt;TP&lt;/span&gt;-Link, MikroTik, and&amp;nbsp;Netgear.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~12 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelabbers upgrading their network&amp;nbsp;infrastructure&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why Switch Selection&amp;nbsp;Matters&lt;/h2&gt;
&lt;p&gt;Your network switch is the backbone of your homelab. The right switch&amp;nbsp;provides:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;VLAN&lt;/span&gt; segmentation&lt;/strong&gt; (isolate IoT, guests,&amp;nbsp;servers)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Link aggregation&lt;/strong&gt; (&lt;span class="caps"&gt;LACP&lt;/span&gt; for 2–8Gbps to &lt;span class="caps"&gt;NAS&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PoE&lt;/strong&gt; (power cameras, APs, Raspberry&amp;nbsp;Pi)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;10GbE&lt;/strong&gt; (fast &lt;span class="caps"&gt;VM&lt;/span&gt; migration, &lt;span class="caps"&gt;NAS&lt;/span&gt;&amp;nbsp;backups)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Jumbo frames&lt;/strong&gt; (&lt;span class="caps"&gt;MTU&lt;/span&gt; 9000 for iSCSI/&lt;span class="caps"&gt;NFS&lt;/span&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Top Switch Recommendations by&amp;nbsp;Category&lt;/h2&gt;
&lt;h3&gt;1. Best Budget 1GbE: &lt;span class="caps"&gt;TP&lt;/span&gt;-Link &lt;span class="caps"&gt;TL&lt;/span&gt;-&lt;span class="caps"&gt;SG108E&lt;/span&gt;&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ports&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;8x 1GbE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Managed&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Web-smart (basic &lt;span class="caps"&gt;VLAN&lt;/span&gt;, QoS)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PoE&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;SFP&lt;/span&gt;+&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Price&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~$30&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Power&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;3W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Noise&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fanless&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Beginners wanting basic VLANs on a&amp;nbsp;budget.&lt;/p&gt;
&lt;h3&gt;2. Best Managed 1GbE: UniFi Switch Lite 8&amp;nbsp;PoE&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ports&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;8x 1GbE (4x PoE+)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Managed&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Full UniFi controller&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PoE&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;52W total&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;SFP&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1x &lt;span class="caps"&gt;SFP&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Price&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~$110&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Power&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;12W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Noise&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fanless&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; UniFi ecosystem users, PoE&amp;nbsp;cameras/APs.&lt;/p&gt;
&lt;h3&gt;3. Best 2.5GbE: &lt;span class="caps"&gt;TP&lt;/span&gt;-Link &lt;span class="caps"&gt;TL&lt;/span&gt;-&lt;span class="caps"&gt;SG3210XHP&lt;/span&gt;-M2&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ports&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;8x 2.5GbE + 2x 10GbE &lt;span class="caps"&gt;SFP&lt;/span&gt;+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Managed&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Omada &lt;span class="caps"&gt;SDN&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PoE&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;240W (802.3at/at++)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;SFP&lt;/span&gt;+&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2x 10GbE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Price&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~$350&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Power&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;30W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Noise&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Low fan&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; 2.5GbE &lt;span class="caps"&gt;NAS&lt;/span&gt; and modern mini PCs with multi-gig&amp;nbsp;NICs.&lt;/p&gt;
&lt;h3&gt;4. Best 10GbE Entry: MikroTik &lt;span class="caps"&gt;CRS312&lt;/span&gt;-4C+&lt;span class="caps"&gt;8XG&lt;/span&gt;&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ports&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;12x 10GbE (&lt;span class="caps"&gt;RJ45&lt;/span&gt;/&lt;span class="caps"&gt;SFP&lt;/span&gt;+ combo)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Managed&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;RouterOS / SwOS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PoE&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;SFP&lt;/span&gt;+&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;12x (combo)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Price&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~$350&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Power&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;25W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Noise&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fanless&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; 10GbE on a budget. MikroTik learning curve but unbeatable&amp;nbsp;price/port.&lt;/p&gt;
&lt;h3&gt;5. Best All-Rounder: UniFi Switch Pro 24&amp;nbsp;PoE&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ports&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;24x 1GbE (PoE+) + 2x 10GbE &lt;span class="caps"&gt;SFP&lt;/span&gt;+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Managed&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;UniFi controller&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PoE&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;400W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;SFP&lt;/span&gt;+&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2x 10GbE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Price&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~$450&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Power&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;50W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Noise&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1x fan (quiet)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Medium homelabs with 10+ devices, UniFi&amp;nbsp;ecosystem.&lt;/p&gt;
&lt;h3&gt;6. Best 10GbE Core: Netgear &lt;span class="caps"&gt;GS110EMX&lt;/span&gt;&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ports&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;8x 1GbE + 2x 10GbE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Managed&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Web-smart (&lt;span class="caps"&gt;VLAN&lt;/span&gt;, QoS)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PoE&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;SFP&lt;/span&gt;+&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2x 10GbE (&lt;span class="caps"&gt;RJ45&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Price&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~$200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Power&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;15W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Noise&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fanless&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; 10GbE uplink to &lt;span class="caps"&gt;NAS&lt;/span&gt; or core switch without full managed&amp;nbsp;complexity.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Comparison&amp;nbsp;Matrix&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Switch&lt;/th&gt;
&lt;th&gt;Ports&lt;/th&gt;
&lt;th&gt;Speed&lt;/th&gt;
&lt;th&gt;PoE&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;SFP&lt;/span&gt;+&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;th&gt;Noise&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;TP&lt;/span&gt;-Link &lt;span class="caps"&gt;TL&lt;/span&gt;-&lt;span class="caps"&gt;SG108E&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;1GbE&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;$30&lt;/td&gt;
&lt;td&gt;Silent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UniFi Lite 8 PoE&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;1GbE&lt;/td&gt;
&lt;td&gt;52W&lt;/td&gt;
&lt;td&gt;1x &lt;span class="caps"&gt;SFP&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$110&lt;/td&gt;
&lt;td&gt;Silent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;TP&lt;/span&gt;-Link &lt;span class="caps"&gt;SG3210XHP&lt;/span&gt;-M2&lt;/td&gt;
&lt;td&gt;8+2&lt;/td&gt;
&lt;td&gt;2.5GbE&lt;/td&gt;
&lt;td&gt;240W&lt;/td&gt;
&lt;td&gt;2x &lt;span class="caps"&gt;SFP&lt;/span&gt;+&lt;/td&gt;
&lt;td&gt;$350&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MikroTik &lt;span class="caps"&gt;CRS312&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;10GbE&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;12x&lt;/td&gt;
&lt;td&gt;$350&lt;/td&gt;
&lt;td&gt;Silent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UniFi Pro 24 PoE&lt;/td&gt;
&lt;td&gt;24+2&lt;/td&gt;
&lt;td&gt;1GbE&lt;/td&gt;
&lt;td&gt;400W&lt;/td&gt;
&lt;td&gt;2x &lt;span class="caps"&gt;SFP&lt;/span&gt;+&lt;/td&gt;
&lt;td&gt;$450&lt;/td&gt;
&lt;td&gt;Quiet&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Netgear &lt;span class="caps"&gt;GS110EMX&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;8+2&lt;/td&gt;
&lt;td&gt;1GbE+10GbE&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;2x &lt;span class="caps"&gt;RJ45&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$200&lt;/td&gt;
&lt;td&gt;Silent&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Managed vs.&amp;nbsp;Unmanaged&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Unmanaged&lt;/th&gt;
&lt;th&gt;Web-Smart&lt;/th&gt;
&lt;th&gt;Full Managed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;VLANs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Basic&lt;/td&gt;
&lt;td&gt;Full 802.1Q&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;QoS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Basic&lt;/td&gt;
&lt;td&gt;Advanced&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;STP&lt;/span&gt;/&lt;span class="caps"&gt;RSTP&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;LACP&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Monitoring&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Basic&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;SNMP&lt;/span&gt;, sFlow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Price&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$20–50&lt;/td&gt;
&lt;td&gt;$50–150&lt;/td&gt;
&lt;td&gt;$150–$500+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Simple setups&lt;/td&gt;
&lt;td&gt;Basic segmentation&lt;/td&gt;
&lt;td&gt;Advanced homelabs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Recommendation:&lt;/strong&gt; Buy at least web-smart for &lt;span class="caps"&gt;VLAN&lt;/span&gt; support. Full managed is worth it for &lt;span class="caps"&gt;LACP&lt;/span&gt; and advanced&amp;nbsp;monitoring.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;10GbE: Is It Worth&amp;nbsp;It?&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;1GbE&lt;/th&gt;
&lt;th&gt;2.5GbE&lt;/th&gt;
&lt;th&gt;10GbE&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;General browsing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;File sharing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;4K streaming&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;VM&lt;/span&gt; storage (iSCSI)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;VM&lt;/span&gt; migration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;NAS&lt;/span&gt; backups&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Multi-user &lt;span class="caps"&gt;NAS&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Recommendation:&lt;/strong&gt; 2.5GbE is the sweet spot for 2026. 10GbE for &lt;span class="caps"&gt;NAS&lt;/span&gt;-heavy or multi-user&amp;nbsp;environments.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;&lt;span class="caps"&gt;VLAN&lt;/span&gt; Setup Example&amp;nbsp;(UniFi)&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Networks:
  - VLAN 1: Management (192.168.1.0/24)
  - VLAN 10: Servers (192.168.10.0/24)
  - VLAN 20: IoT (192.168.20.0/24)
  - VLAN 30: Guests (192.168.30.0/24)

Port Profiles:
  - Port 1: Trunk (all VLANs)
  - Port 2-8: VLAN 10 (servers)
  - Port 9-16: VLAN 20 (IoT)
  - Port 17-24: VLAN 30 (guests)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;For most homelabs, a &lt;strong&gt;web-smart 1GbE or 2.5GbE switch&lt;/strong&gt; with &lt;span class="caps"&gt;VLAN&lt;/span&gt; support is sufficient. Upgrade to &lt;strong&gt;10GbE&lt;/strong&gt; only if you have a &lt;span class="caps"&gt;NAS&lt;/span&gt; with SSDs or run multiple VMs with heavy storage&amp;nbsp;traffic.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Count your devices&lt;/strong&gt; and plan 2x ports for&amp;nbsp;growth&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Decide if you need PoE&lt;/strong&gt; (cameras, APs,&amp;nbsp;phones)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Choose UniFi&lt;/strong&gt; for ecosystem integration, &lt;strong&gt;MikroTik&lt;/strong&gt; for price, &lt;strong&gt;&lt;span class="caps"&gt;TP&lt;/span&gt;-Link&lt;/strong&gt; for&amp;nbsp;value&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configure VLANs&lt;/strong&gt; to isolate IoT and&amp;nbsp;guests&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;UniFi:&lt;/strong&gt; Ubiquiti store,&amp;nbsp;Amazon&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;TP&lt;/span&gt;-Link:&lt;/strong&gt; Amazon,&amp;nbsp;B&amp;amp;H&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MikroTik:&lt;/strong&gt; Official distributors,&amp;nbsp;Amazon&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cables:&lt;/strong&gt; Monoprice, AmazonBasics&amp;nbsp;Cat6a&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;SFP&lt;/span&gt;+ &lt;span class="caps"&gt;DAC&lt;/span&gt;:&lt;/strong&gt; 10Gtek, &lt;span class="caps"&gt;FS&lt;/span&gt;.com&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal&amp;nbsp;Linking&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;networking&lt;/code&gt; → &lt;code&gt;homelab-networking-basics.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;vlan&lt;/code&gt; → &lt;code&gt;vlan-setup-guide.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;wifi&lt;/code&gt; → &lt;code&gt;tp-link-omada-vs-unifi.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nas&lt;/code&gt; → &lt;code&gt;self-hosted-cloud-storage-nextcloud.md&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Which switch powers your homelab?&lt;/strong&gt; UniFi, MikroTik, or &lt;span class="caps"&gt;TP&lt;/span&gt;-Link?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subscribe&lt;/strong&gt; for networking and infrastructure&amp;nbsp;guides.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Reviews"/><category term="homelab network switch recommendations"/><category term="10gbe switch"/><category term="managed switch homelab"/><category term="unifi"/><category term="tp-link omada"/><category term="mikrotik"/></entry><entry><title>Homelab Rack Setup: A Complete Guide for Building a Server Rack in 2026</title><link href="https://steadypub.com/2026/06/homelab-rack-setup/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T10:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/homelab-rack-setup/</id><summary type="html">&lt;p&gt;A step-by-step guide to planning, assembling, and wiring a homelab server rack. Covers rack sizes, power, cooling, cable management, and noise&amp;nbsp;reduction.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~16 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab and self-hosting&amp;nbsp;enthusiasts&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is a Homelab&amp;nbsp;Rack?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;A homelab rack is a standardized frame (typically 19 inches wide) that houses servers, network equipment, storage, and power distribution. Racks are measured in &amp;#8220;U&amp;#8221; units (1U = 1.75 inches / 44.45 mm). A full-size rack is 42U (~6 feet tall), while compact homelab racks range from 6U to 15U. A rack provides organization, cooling efficiency, and a professional aesthetic that turns a cluttered pile of hardware into a maintainable&amp;nbsp;infrastructure.&lt;/p&gt;
&lt;h3&gt;Why Build a&amp;nbsp;Rack?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Organization&lt;/strong&gt;: Everything has a defined place; no more loose machines on a&amp;nbsp;shelf&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cooling&lt;/strong&gt;: Rack-mounted equipment uses front-to-back airflow; a rack with blanking panels and fans creates a controlled thermal&amp;nbsp;environment&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scalability&lt;/strong&gt;: Add a new server by sliding it into an empty U&amp;nbsp;space&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Noise Management&lt;/strong&gt;: Rack enclosures with sound-dampening panels reduce the noise escaping into your living&amp;nbsp;space&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;h3&gt;Hardware&amp;nbsp;Requirements&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Minimum&lt;/th&gt;
&lt;th&gt;Recommended&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Rack&lt;/td&gt;
&lt;td&gt;6U wall-mount&lt;/td&gt;
&lt;td&gt;12U–15U floor-standing&lt;/td&gt;
&lt;td&gt;Start small; upgrade later&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Power&lt;/td&gt;
&lt;td&gt;Basic &lt;span class="caps"&gt;PDU&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Metered &lt;span class="caps"&gt;PDU&lt;/span&gt; with surge protection&lt;/td&gt;
&lt;td&gt;Consider a &lt;span class="caps"&gt;UPS&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cooling&lt;/td&gt;
&lt;td&gt;Room &lt;span class="caps"&gt;AC&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Rack-mounted exhaust fans&lt;/td&gt;
&lt;td&gt;Hot air must leave the rack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cabling&lt;/td&gt;
&lt;td&gt;Cat5e&lt;/td&gt;
&lt;td&gt;Cat6 or Cat6a&lt;/td&gt;
&lt;td&gt;10GbE-ready&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Shelves&lt;/td&gt;
&lt;td&gt;1x shelf for non-rack gear&lt;/td&gt;
&lt;td&gt;2x shelves + cable management&lt;/td&gt;
&lt;td&gt;Mini PCs, &lt;span class="caps"&gt;UPS&lt;/span&gt;, &lt;span class="caps"&gt;NAS&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Knowledge&amp;nbsp;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Basic woodworking or assembly (for &lt;span class="caps"&gt;DIY&lt;/span&gt;&amp;nbsp;racks)&lt;/li&gt;
&lt;li&gt;Electrical safety (&lt;span class="caps"&gt;PDU&lt;/span&gt; loading, &lt;span class="caps"&gt;UPS&lt;/span&gt;&amp;nbsp;sizing)&lt;/li&gt;
&lt;li&gt;Networking (patch panels, keystone&amp;nbsp;jacks)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Choose the Right&amp;nbsp;Rack&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Select a rack size and type that fits your space, budget, and expansion&amp;nbsp;plans.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Rack Type&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;Pros&lt;/th&gt;
&lt;th&gt;Cons&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Wall-mount (6–12U)&lt;/td&gt;
&lt;td&gt;Apartments, small rooms&lt;/td&gt;
&lt;td&gt;Saves floor space, cheap&lt;/td&gt;
&lt;td&gt;Limited depth, weight capacity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Open frame (12—25U)&lt;/td&gt;
&lt;td&gt;Garages, basements&lt;/td&gt;
&lt;td&gt;Cheap, excellent airflow&lt;/td&gt;
&lt;td&gt;No security, noisy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Enclosed cabinet (12–42U)&lt;/td&gt;
&lt;td&gt;Living spaces, offices&lt;/td&gt;
&lt;td&gt;Quiet, secure, looks professional&lt;/td&gt;
&lt;td&gt;Expensive, heavy, needs ventilation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;DIY&lt;/span&gt; LackRack (€7 &lt;span class="caps"&gt;IKEA&lt;/span&gt; table)&lt;/td&gt;
&lt;td&gt;Extreme budget&lt;/td&gt;
&lt;td&gt;Almost free&lt;/td&gt;
&lt;td&gt;Not durable, shallow depth&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Recommended homelab starter: &lt;strong&gt;Startech 12U wall-mount&lt;/strong&gt; or &lt;strong&gt;NavePoint 15U enclosed cabinet&lt;/strong&gt;. Measure your ceiling height and doorways before ordering. A 42U full rack is ~200 lbs empty and will not fit through standard interior&amp;nbsp;doors.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 2: Plan Power and &lt;span class="caps"&gt;UPS&lt;/span&gt;&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Calculate power draw and install a &lt;span class="caps"&gt;UPS&lt;/span&gt; and &lt;span class="caps"&gt;PDU&lt;/span&gt; for clean, protected&amp;nbsp;power.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Measure power draw&lt;/strong&gt;: Use a Kill-A-Watt meter to measure your current&amp;nbsp;gear&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Size the &lt;span class="caps"&gt;UPS&lt;/span&gt;&lt;/strong&gt;: Aim for 20–30% headroom above your measured load. A 600W load needs a 900W (&lt;span class="caps"&gt;1500VA&lt;/span&gt;) &lt;span class="caps"&gt;UPS&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Install a &lt;span class="caps"&gt;PDU&lt;/span&gt;&lt;/strong&gt;: Rack-mounted PDUs provide 8–12 outlets in a vertical strip. Get a metered &lt;span class="caps"&gt;PDU&lt;/span&gt; to see real-time&amp;nbsp;load&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Connect&lt;/strong&gt;: Wall → &lt;span class="caps"&gt;UPS&lt;/span&gt; → &lt;span class="caps"&gt;PDU&lt;/span&gt; →&amp;nbsp;Servers&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Example &lt;span class="caps"&gt;UPS&lt;/span&gt;&amp;nbsp;sizes:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Load&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;UPS&lt;/span&gt; &lt;span class="caps"&gt;VA&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;UPS&lt;/span&gt; Watt&lt;/th&gt;
&lt;th&gt;Runtime (half load)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;300W&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;600VA&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;360W&lt;/td&gt;
&lt;td&gt;~10 min&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;600W&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;1500VA&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;900W&lt;/td&gt;
&lt;td&gt;~15 min&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1000W&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;2200VA&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1500W&lt;/td&gt;
&lt;td&gt;~20 min&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# No CLI commands for hardware setup&lt;/span&gt;
&lt;span class="c1"&gt;# Use a Kill-A-Watt or smart PDU for measurement&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 3: Install Network&amp;nbsp;Equipment&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Mount the router, switch, and patch panel for a clean network&amp;nbsp;backbone.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Mount the patch panel&lt;/strong&gt; at the top of the rack (closest to cable&amp;nbsp;entry)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mount the switch&lt;/strong&gt; below the patch&amp;nbsp;panel&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mount the router/gateway&lt;/strong&gt; (e.g., &lt;span class="caps"&gt;UDM&lt;/span&gt; Pro) in a middle U&amp;nbsp;space&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use 6-inch patch cables&lt;/strong&gt; between the patch panel and switch; 1-foot cables are too long and create&amp;nbsp;clutter&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Cable color&amp;nbsp;coding:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Color&lt;/th&gt;
&lt;th&gt;Use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Blue&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;LAN&lt;/span&gt; / trusted devices&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Red&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;WAN&lt;/span&gt; / internet&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Yellow&lt;/td&gt;
&lt;td&gt;Management / iDRAC / &lt;span class="caps"&gt;IPMI&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Green&lt;/td&gt;
&lt;td&gt;VoIP / phones&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;White&lt;/td&gt;
&lt;td&gt;IoT / guest &lt;span class="caps"&gt;VLAN&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Step 4: Rack the Servers and&amp;nbsp;Storage&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Install servers, &lt;span class="caps"&gt;NAS&lt;/span&gt;, and shelves with proper airflow and weight&amp;nbsp;distribution.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Heaviest gear at the bottom&lt;/strong&gt;: &lt;span class="caps"&gt;UPS&lt;/span&gt;, &lt;span class="caps"&gt;NAS&lt;/span&gt;, and large servers go low to prevent&amp;nbsp;tipping&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use rail kits&lt;/strong&gt;: Dell, &lt;span class="caps"&gt;HP&lt;/span&gt;, and Supermicro servers need sliding rail kits. Generic rails exist for odd&amp;nbsp;sizes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Blanking panels&lt;/strong&gt;: Fill empty U spaces with plastic or metal blanks to maintain front-to-back&amp;nbsp;airflow&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cable arms&lt;/strong&gt;: Optional; they manage rear cables but can obstruct airflow in shallow&amp;nbsp;racks&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For non-rack gear (mini PCs, Raspberry Pi clusters, external drives), use a &lt;strong&gt;1U or 2U shelf&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 5: Cable Management and&amp;nbsp;Cooling&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Create a clean, maintainable, and thermally stable&amp;nbsp;environment.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Cable management:&lt;/strong&gt;
- Use velcro straps (not zip ties) for easy changes
- Route power cables on one side, network on the other
- Use horizontal and vertical cable managers (D-ring, brush-strip)
- Label both ends of every&amp;nbsp;cable&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cooling:&lt;/strong&gt;
- Install rack-mounted exhaust fans at the top (hot air rises)
- Ensure front-to-back airflow: intake at the front, exhaust at the rear
- If the rack is enclosed, add a vented door or active fan panel
- Keep ambient room temperature below 25°C&amp;nbsp;(77°F)&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Use a Rack Diagram&amp;nbsp;Tool&lt;/h3&gt;
&lt;p&gt;Before mounting anything, create a rack diagram in Excel, Visio, or RackTables. Assign U spaces and note power/network requirements. This prevents the &amp;#8220;I need one more U space&amp;#8221; problem after everything is&amp;nbsp;wired.&lt;/p&gt;
&lt;h3&gt;Tip 2: Sound&amp;nbsp;Dampening&lt;/h3&gt;
&lt;p&gt;If the rack is in a living space, line the doors with acoustic foam panels. Place the rack on a vibration-dampening mat. Use Noctua fans or low-&lt;span class="caps"&gt;RPM&lt;/span&gt; fans for &lt;span class="caps"&gt;DIY&lt;/span&gt; cooling. A 1U server is always louder than a 4U tower; choose depth and height over density for noise&amp;nbsp;control.&lt;/p&gt;
&lt;h3&gt;Tip 3: Document&amp;nbsp;Everything&lt;/h3&gt;
&lt;p&gt;Create a spreadsheet with:
- U position, device name, &lt;span class="caps"&gt;MAC&lt;/span&gt; address, &lt;span class="caps"&gt;IP&lt;/span&gt; address, power draw
- &lt;span class="caps"&gt;PDU&lt;/span&gt; port assignments
- Switch port assignments
- &lt;span class="caps"&gt;VLAN&lt;/span&gt;&amp;nbsp;table&lt;/p&gt;
&lt;p&gt;Update it every time you make a&amp;nbsp;change.&lt;/p&gt;
&lt;h3&gt;Tip 4:&amp;nbsp;Future-Proofing&lt;/h3&gt;
&lt;p&gt;Leave 20–30% of your rack empty. Run extra network cables to the patch panel (even if unused). Use a switch with 10GbE &lt;span class="caps"&gt;SFP&lt;/span&gt;+ ports even if you only use 1GbE now. The cost difference is small; the upgrade path is&amp;nbsp;huge.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Troubleshooting Common&amp;nbsp;Issues&lt;/h2&gt;
&lt;h3&gt;Problem 1: Rack Tips&amp;nbsp;Forward&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Ensure the rack is bolted to the floor or&amp;nbsp;wall&lt;/li&gt;
&lt;li&gt;Heavy equipment (&lt;span class="caps"&gt;UPS&lt;/span&gt;, &lt;span class="caps"&gt;NAS&lt;/span&gt;) must be at the&amp;nbsp;bottom&lt;/li&gt;
&lt;li&gt;Use a rack with adjustable leveling&amp;nbsp;feet&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Problem 2:&amp;nbsp;Overheating&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Check blanking panels; empty U spaces create hot air&amp;nbsp;recirculation&lt;/li&gt;
&lt;li&gt;Verify server fans are spinning (iDRAC/&lt;span class="caps"&gt;IPMI&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;Add exhaust fans or improve room&amp;nbsp;ventilation&lt;/li&gt;
&lt;li&gt;Consider a portable &lt;span class="caps"&gt;AC&lt;/span&gt; unit for summer&amp;nbsp;months&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Problem 3: Excessive&amp;nbsp;Noise&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Replace 40mm fans with Noctua redux or industrialPPC&amp;nbsp;models&lt;/li&gt;
&lt;li&gt;Use a sound-dampened enclosed&amp;nbsp;rack&lt;/li&gt;
&lt;li&gt;Relocate the rack to a basement, garage, or&amp;nbsp;closet&lt;/li&gt;
&lt;li&gt;Use a long &lt;span class="caps"&gt;HDMI&lt;/span&gt;/&lt;span class="caps"&gt;USB&lt;/span&gt; cable to access machines from a quiet&amp;nbsp;room&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;A homelab rack transforms scattered hardware into a professional, maintainable, and scalable infrastructure. By choosing the right rack size, planning power and cooling, and implementing disciplined cable management, you create a foundation that grows with your ambitions. Whether you start with a 6U wall mount or a 42U enclosed cabinet, the principles remain the same: airflow, organization, and&amp;nbsp;documentation.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Create a rack diagram and assign U&amp;nbsp;spaces&lt;/li&gt;
&lt;li&gt;Measure total power draw and size a &lt;span class="caps"&gt;UPS&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Order cable management accessories (velcro, D-rings,&amp;nbsp;labels)&lt;/li&gt;
&lt;li&gt;Plan your 10GbE upgrade&amp;nbsp;path&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;prerequisites&lt;/strong&gt;: hardware — Rack cabinets, PDUs, &lt;span class="caps"&gt;UPS&lt;/span&gt; units,&amp;nbsp;shelving&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;step-1&lt;/strong&gt;: tool — Cable testers, Kill-A-Watt meters, label&amp;nbsp;makers&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;pro-tips&lt;/strong&gt;: service — Structured cabling installation, rack assembly&amp;nbsp;services&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;what-is&lt;/code&gt; → related_comparison: &lt;a href="https://steadypub.com/2026/06/mini-pc-vs-rack-server/"&gt;Mini &lt;span class="caps"&gt;PC&lt;/span&gt; vs rack&amp;nbsp;server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prerequisites&lt;/code&gt; → setup_guide: &lt;a href="https://steadypub.com/2026/06/best-rack-server-for-homelab/"&gt;Best rack server for&amp;nbsp;homelab&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → next_steps: &lt;a href="https://steadypub.com/2026/06/ubiquiti-homelab-setup/"&gt;Ubiquiti homelab networking&amp;nbsp;setup&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] Show us your rack! What size and brand did you&amp;nbsp;choose?&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for weekly homelab hardware and networking&amp;nbsp;guides.&lt;/li&gt;
&lt;li&gt;[internal_link] Next: &lt;a href="https://steadypub.com/2026/06/best-rack-server-for-homelab/"&gt;choose the best rack server for your&amp;nbsp;budget&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Tutorials"/><category term="homelab rack"/><category term="server rack"/><category term="hardware"/><category term="networking"/><category term="homelab"/></entry><entry><title>Homelab Security Monitoring: A Complete Guide for Self-Hosters</title><link href="https://steadypub.com/2026/06/homelab-security-monitoring/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T06:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/homelab-security-monitoring/</id><summary type="html">&lt;p&gt;Build a defense-in-depth security monitoring stack for your homelab. Covers Wazuh &lt;span class="caps"&gt;SIEM&lt;/span&gt;, network segmentation, intrusion detection, and actionable&amp;nbsp;alerting.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~14 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelabbers who want to know when they are being&amp;nbsp;attacked&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is Homelab Security&amp;nbsp;Monitoring?&lt;/h2&gt;
&lt;h3&gt;What Exactly Is&amp;nbsp;It?&lt;/h3&gt;
&lt;p&gt;Security monitoring is the practice of collecting, analyzing, and alerting on events that indicate unauthorized access, misconfiguration, or malicious activity in your self-hosted infrastructure. Unlike a corporate &lt;span class="caps"&gt;SOC&lt;/span&gt; (Security Operations Center), a homelab security stack is typically a single-person operation: you are the analyst, the responder, and the&amp;nbsp;administrator.&lt;/p&gt;
&lt;p&gt;A complete homelab security monitoring stack includes:
1. &lt;strong&gt;Log aggregation:&lt;/strong&gt; Centralizing syslog, audit logs, and application logs
2. &lt;strong&gt;Host intrusion detection:&lt;/strong&gt; File integrity monitoring (&lt;span class="caps"&gt;FIM&lt;/span&gt;), rootkit detection, and anomaly detection
3. &lt;strong&gt;Network intrusion detection:&lt;/strong&gt; Suricata or Zeek for packet analysis
4. &lt;strong&gt;Vulnerability detection:&lt;/strong&gt; Scanning for CVEs in containers and &lt;span class="caps"&gt;OS&lt;/span&gt; packages
5. &lt;strong&gt;Alerting:&lt;/strong&gt; Notifying you via Telegram, Slack, or email when something is&amp;nbsp;wrong&lt;/p&gt;
&lt;h3&gt;Why It Matters&amp;nbsp;Today&lt;/h3&gt;
&lt;p&gt;A self-hosted homelab is a public target. Every port forwarded, every exposed service, and every default password is a potential entry point. In 2026, automated scanners (Shodan, Censys, and private botnets) probe every IPv4 address continuously. If you run a public-facing service, you are being scanned right&amp;nbsp;now.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Real threats to homelabs:&lt;/strong&gt;
- &lt;strong&gt;Credential stuffing:&lt;/strong&gt; Attackers use leaked password databases against &lt;span class="caps"&gt;SSH&lt;/span&gt;, Nextcloud, and Jellyfin
- &lt;strong&gt;Container escape:&lt;/strong&gt; A vulnerable Docker image can grant host-level access
- &lt;strong&gt;Cryptojacking:&lt;/strong&gt; Compromised containers mine cryptocurrency using your electricity
- &lt;strong&gt;Ransomware:&lt;/strong&gt; Unpatched services (Confluence, Jenkins, etc.) are encrypted for Bitcoin&amp;nbsp;demands&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why It&amp;nbsp;Matters&lt;/h2&gt;
&lt;h3&gt;Benefit 1: You Cannot Defend What You Cannot&amp;nbsp;See&lt;/h3&gt;
&lt;p&gt;Without monitoring, a compromise is silent. An attacker can lurk for months, pivot between containers, and exfiltrate data before you notice a performance slowdown. Security monitoring turns the lights&amp;nbsp;on.&lt;/p&gt;
&lt;h3&gt;Benefit 2: Compliance and&amp;nbsp;Learning&lt;/h3&gt;
&lt;p&gt;If you are studying for security certifications (CompTIA Security+, &lt;span class="caps"&gt;CISSP&lt;/span&gt;, &lt;span class="caps"&gt;OSCP&lt;/span&gt;), a homelab &lt;span class="caps"&gt;SIEM&lt;/span&gt; is the best hands-on training ground. You can generate attack traffic, analyze logs, and write detection rules in a safe&amp;nbsp;environment.&lt;/p&gt;
&lt;h3&gt;Benefit 3: Insurance for Your&amp;nbsp;Data&lt;/h3&gt;
&lt;p&gt;You back up your data. Security monitoring is the &amp;#8220;backup&amp;#8221; for your infrastructure: it tells you when the restore point is&amp;nbsp;needed.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Core&amp;nbsp;Principles&lt;/h2&gt;
&lt;h3&gt;Principle 1: Defense in&amp;nbsp;Depth&lt;/h3&gt;
&lt;p&gt;No single tool catches everything. Layer your defenses:
- &lt;strong&gt;Perimeter:&lt;/strong&gt; Firewall (pfSense/OPNsense) blocks unwanted traffic
- &lt;strong&gt;Network:&lt;/strong&gt; VLANs isolate services by trust level
- &lt;strong&gt;Host:&lt;/strong&gt; Fail2Ban or CrowdSec blocks brute-force attempts
- &lt;strong&gt;Application:&lt;/strong&gt; Vaultwarden enforces strong passwords; &lt;span class="caps"&gt;2FA&lt;/span&gt; on every admin panel
- &lt;strong&gt;Monitoring:&lt;/strong&gt; Wazuh correlates events across all&amp;nbsp;layers&lt;/p&gt;
&lt;h3&gt;Principle 2: Log Everything, Alert on What&amp;nbsp;Matters&lt;/h3&gt;
&lt;p&gt;A &lt;span class="caps"&gt;SIEM&lt;/span&gt; that alerts on every failed &lt;span class="caps"&gt;SSH&lt;/span&gt; login will train you to ignore it. Tune your alerts to high-confidence indicators:
- File changes&amp;nbsp;in &lt;code&gt;/etc/&lt;/code&gt;, &lt;code&gt;/usr/bin/&lt;/code&gt;, and container image layers
- New listening ports or running processes
- Login attempts from non-standard geolocations (if you have a static &lt;span class="caps"&gt;IP&lt;/span&gt;)
- CVEs in running container&amp;nbsp;images&lt;/p&gt;
&lt;h3&gt;Principle 3: Assume&amp;nbsp;Breach&lt;/h3&gt;
&lt;p&gt;Design your monitoring as if an attacker is already inside. Monitor east-west traffic between containers, not just north-south traffic from the internet. If your Nextcloud container starts talking to a cryptocurrency mining pool, that is a high-fidelity&amp;nbsp;alert.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Applying This to Your&amp;nbsp;Homelab&lt;/h2&gt;
&lt;h3&gt;Homelab Setup Example: Wazuh-Based &lt;span class="caps"&gt;SIEM&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Architecture:&lt;/strong&gt;
- &lt;strong&gt;Wazuh Manager:&lt;/strong&gt; Central server (4 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, 2 cores, 50 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt;)
- &lt;strong&gt;Wazuh Indexer:&lt;/strong&gt; Elasticsearch fork for log storage (8 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; recommended)
- &lt;strong&gt;Wazuh Dashboard:&lt;/strong&gt; Kibana fork for visualization
- &lt;strong&gt;Agents:&lt;/strong&gt; One per monitored host (&lt;span class="caps"&gt;VM&lt;/span&gt;, &lt;span class="caps"&gt;LXC&lt;/span&gt;, or&amp;nbsp;physical)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What Wazuh monitors out of the box:&lt;/strong&gt;
- File integrity (&lt;span class="caps"&gt;FIM&lt;/span&gt;)&amp;nbsp;on &lt;code&gt;/bin&lt;/code&gt;, &lt;code&gt;/sbin&lt;/code&gt;, &lt;code&gt;/etc&lt;/code&gt;, &lt;code&gt;/var/www&lt;/code&gt;
- Rootkit detection (&lt;span class="caps"&gt;YARA&lt;/span&gt; rules + rootcheck)
- Active response (automatically blocks &lt;span class="caps"&gt;IP&lt;/span&gt; after 5 failed &lt;span class="caps"&gt;SSH&lt;/span&gt; attempts)
- Docker/container image scanning (&lt;span class="caps"&gt;CVE&lt;/span&gt; database)
- &lt;span class="caps"&gt;CIS&lt;/span&gt; benchmark compliance&amp;nbsp;checks&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Docker Compose&amp;nbsp;deployment:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;wazuh.manager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh/wazuh-manager:4.7.2&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh.manager&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1514:1514&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1515:1515&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;514:514/udp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;55000:55000&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh-api:/var/ossec/api/configuration&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh-etc:/var/ossec/etc&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh-logs:/var/ossec/logs&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh-queue:/var/ossec/queue&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh-var:/var/ossec/var&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh-share:/var/ossec/share&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh-active-response:/var/ossec/active-response/bin&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;wazuh.indexer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh/wazuh-indexer:4.7.2&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh.indexer&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;OPENSEARCH_JAVA_OPTS=-Xms1g&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-Xmx1g&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ulimits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;memlock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;soft&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;-1&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;hard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;-1&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;nofile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;soft&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;65536&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;hard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;65536&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh-indexer:/var/lib/wazuh-indexer&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;wazuh.dashboard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh/wazuh-dashboard:4.7.2&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh.dashboard&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;443:5601&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;WAZUH_INDEXER_URL=https://wazuh.indexer:9200&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;wazuh.indexer&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;wazuh-api&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;wazuh-etc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;wazuh-logs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;wazuh-queue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;wazuh-var&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;wazuh-share&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;wazuh-active-response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;wazuh-indexer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Agent installation (on a Debian/Ubuntu&amp;nbsp;host):&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Add Wazuh repository&lt;/span&gt;
curl&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;https://packages.wazuh.com/key/GPG-KEY-WAZUH&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;gpg&lt;span class="w"&gt; &lt;/span&gt;--no-default-keyring&lt;span class="w"&gt; &lt;/span&gt;--keyring&lt;span class="w"&gt; &lt;/span&gt;gnupg-ring:/usr/share/keyrings/wazuh.gpg&lt;span class="w"&gt; &lt;/span&gt;--import&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;chmod&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;644&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/usr/share/keyrings/wazuh.gpg
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;deb [signed-by=/usr/share/keyrings/wazuh.gpg] https://packages.wazuh.com/4.x/apt/ stable main&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;tee&lt;span class="w"&gt; &lt;/span&gt;/etc/apt/sources.list.d/wazuh.list

&lt;span class="c1"&gt;# Install agent&lt;/span&gt;
apt-get&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apt-get&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;wazuh-agent

&lt;span class="c1"&gt;# Register with manager&lt;/span&gt;
/var/ossec/bin/agent-auth&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;&amp;lt;WAZUH_MANAGER_IP&amp;gt;

&lt;span class="c1"&gt;# Start agent&lt;/span&gt;
systemctl&lt;span class="w"&gt; &lt;/span&gt;daemon-reload
systemctl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;wazuh-agent
systemctl&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;wazuh-agent
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Practical Steps: CrowdSec as a Lightweight&amp;nbsp;Alternative&lt;/h3&gt;
&lt;p&gt;If Wazuh is too heavy for your setup, &lt;strong&gt;CrowdSec&lt;/strong&gt; is a modern, community-driven &lt;span class="caps"&gt;IPS&lt;/span&gt;/&lt;span class="caps"&gt;IDS&lt;/span&gt; that is lighter and easier to&amp;nbsp;deploy:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Install CrowdSec&lt;/span&gt;
curl&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;https://packagecloud.io/install/repositories/crowdsec/crowdsec/script.deb.sh&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;bash
apt-get&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;crowdsec

&lt;span class="c1"&gt;# Install a collection (e.g., nginx logs)&lt;/span&gt;
cscli&lt;span class="w"&gt; &lt;/span&gt;collections&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;crowdsecurity/nginx

&lt;span class="c1"&gt;# Install a bouncer (e.g., firewall bouncer)&lt;/span&gt;
apt-get&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;crowdsec-firewall-bouncer

&lt;span class="c1"&gt;# View decisions&lt;/span&gt;
watch&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cscli&lt;span class="w"&gt; &lt;/span&gt;decisions&lt;span class="w"&gt; &lt;/span&gt;list
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;CrowdSec shares attack intelligence with a global community. If an &lt;span class="caps"&gt;IP&lt;/span&gt; attacks your server, it is automatically blocked on every other CrowdSec user&amp;#8217;s firewall. This is &amp;#8221; crowdsourced&amp;nbsp;defense.&amp;#8221;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Common Mistakes to&amp;nbsp;Avoid&lt;/h2&gt;
&lt;h3&gt;Mistake 1: Exposing Your &lt;span class="caps"&gt;SIEM&lt;/span&gt; to the&amp;nbsp;Internet&lt;/h3&gt;
&lt;p&gt;Wazuh Dashboard, Elasticsearch, and Grafana should never be public-facing. Use a &lt;span class="caps"&gt;VPN&lt;/span&gt; (Tailscale, WireGuard) or a reverse proxy with strong authentication to access them. If you must expose a dashboard, put it behind Cloudflare Access or&amp;nbsp;Authelia.&lt;/p&gt;
&lt;h3&gt;Mistake 2: Ignoring Container&amp;nbsp;Security&lt;/h3&gt;
&lt;p&gt;Docker containers are not inherently secure. A 2026 audit of Docker Hub images found that 60% of official images had known CVEs. Run Trivy or Wazuh&amp;#8217;s container scanning to audit your&amp;nbsp;images:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Scan a running container for CVEs&lt;/span&gt;
trivy&lt;span class="w"&gt; &lt;/span&gt;image&lt;span class="w"&gt; &lt;/span&gt;nextcloud:latest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Mistake 3: Alert&amp;nbsp;Fatigue&lt;/h3&gt;
&lt;p&gt;A &lt;span class="caps"&gt;SIEM&lt;/span&gt; that sends 50 emails per day is a &lt;span class="caps"&gt;SIEM&lt;/span&gt; that will be ignored. Tune your rules:
- Use thresholding: &amp;#8220;5 failed &lt;span class="caps"&gt;SSH&lt;/span&gt; logins in 10 minutes&amp;#8221; not &amp;#8220;1 failed &lt;span class="caps"&gt;SSH&lt;/span&gt; login&amp;#8221;
- Use suppression: &amp;#8220;Alert once per hour per source &lt;span class="caps"&gt;IP&lt;/span&gt;&amp;#8221;
- Use severity: Reserve email for &amp;#8220;Critical&amp;#8221; and &amp;#8220;High&amp;#8221;; send &amp;#8220;Low&amp;#8221; to a log&amp;nbsp;file&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Security monitoring is not optional for a public-facing homelab. Wazuh provides a complete &lt;span class="caps"&gt;SIEM&lt;/span&gt; experience with &lt;span class="caps"&gt;FIM&lt;/span&gt;, rootkit detection, and vulnerability scanning. CrowdSec offers a lightweight, community-driven alternative. The key principles are defense in depth, tuned alerting, and assuming&amp;nbsp;breach.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Deploy Wazuh or CrowdSec on a dedicated &lt;span class="caps"&gt;VM&lt;/span&gt; or &lt;span class="caps"&gt;LXC&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Install agents on every host that faces the&amp;nbsp;internet&lt;/li&gt;
&lt;li&gt;Enable &lt;span class="caps"&gt;FIM&lt;/span&gt;&amp;nbsp;on &lt;code&gt;/etc&lt;/code&gt;, &lt;code&gt;/usr/bin&lt;/code&gt;, and web root&amp;nbsp;directories&lt;/li&gt;
&lt;li&gt;Set up alerting to Telegram or&amp;nbsp;Slack&lt;/li&gt;
&lt;li&gt;Run a weekly Trivy scan on your Docker&amp;nbsp;images&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mini PCs for &lt;span class="caps"&gt;SIEM&lt;/span&gt;:&lt;/strong&gt; Intel N100/N305 with 16 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; (Amazon,&amp;nbsp;AliExpress)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Networking:&lt;/strong&gt; Ubiquiti, &lt;span class="caps"&gt;TP&lt;/span&gt;-Link Omada&amp;nbsp;(Amazon)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt;:&lt;/strong&gt; Hetzner, &lt;span class="caps"&gt;OVH&lt;/span&gt; for offsite log backup&amp;nbsp;(referral)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;wazuh-setup&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;wazuh-siem-setup.md&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker-security&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;docker-security-hardening.md&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;network-segmentation&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;homelab-networking-basics.md&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;vpn-access&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;tailscale-homelab-guide.md&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] What security tools do you run in your homelab? Share your &lt;span class="caps"&gt;SIEM&lt;/span&gt; stack&amp;nbsp;below.&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for our quarterly security hardening guides and &lt;span class="caps"&gt;CVE&lt;/span&gt;&amp;nbsp;roundups.&lt;/li&gt;
&lt;li&gt;[internal_link] Ready to deploy Wazuh? Read our &lt;a href="https://steadypub.com/2026/06/wazuh-siem-setup/"&gt;Wazuh &lt;span class="caps"&gt;SIEM&lt;/span&gt; setup guide&lt;/a&gt;&amp;nbsp;next.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Concepts"/><category term="self-hosted"/><category term="homelab"/><category term="homelab security monitoring"/><category term="siem"/><category term="wazuh"/></entry><entry><title>Set Up Wazuh SIEM in Your Homelab: Complete Security Monitoring Guide 2026</title><link href="https://steadypub.com/2026/06/homelab-siem-wazuh/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-17T00:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/homelab-siem-wazuh/</id><summary type="html">&lt;p&gt;Set up Wazuh &lt;span class="caps"&gt;SIEM&lt;/span&gt; in your homelab for real-time security monitoring, threat detection, and compliance auditing. A complete guide to deploying Wazuh for self-hosted&amp;nbsp;environments.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Wazuh is the leading open-source &lt;span class="caps"&gt;SIEM&lt;/span&gt; (Security Information and Event Management) and &lt;span class="caps"&gt;XDR&lt;/span&gt; (Extended Detection and Response) platform for homelabs. It provides log analysis, file integrity monitoring, vulnerability detection, and real-time alerting — all free and&amp;nbsp;self-hosted.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;For the comprehensive step-by-step deployment guide, see our &lt;a href="https://steadypub.com/2026/06/wazuh-docker-compose/"&gt;Wazuh Docker Compose Setup&lt;/a&gt;&lt;/strong&gt; — covers installation, agent enrollment, &lt;span class="caps"&gt;FIM&lt;/span&gt; configuration, vulnerability detection, &lt;span class="caps"&gt;CIS&lt;/span&gt; benchmarks, and&amp;nbsp;troubleshooting.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Why Wazuh for Your&amp;nbsp;Homelab?&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Capability&lt;/th&gt;
&lt;th&gt;Benefit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Log Analysis&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Collect and parse logs from all servers, containers, and endpoints&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;File Integrity Monitoring&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Detect unauthorized file changes in real time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Vulnerability Detection&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;CVE&lt;/span&gt; scanning for installed packages across all agents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Configuration Assessment&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;CIS&lt;/span&gt; benchmark compliance checks out of the box&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Malware Detection&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;YARA&lt;/span&gt;-based scanning and threat intelligence integration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Alerting&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Email, Slack, webhook, and syslog notifications for security events&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;Quick&amp;nbsp;Start&lt;/h2&gt;
&lt;p&gt;Deploy the full Wazuh stack (Manager, Indexer, Dashboard) in minutes with Docker&amp;nbsp;Compose:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;~/docker/wazuh&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/docker/wazuh
&lt;span class="c1"&gt;# See wazuh-docker-compose.md for the complete docker-compose.yml&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Access the dashboard&amp;nbsp;at &lt;code&gt;https://your-server-ip:5601&lt;/code&gt; (default: &lt;code&gt;admin&lt;/code&gt;/&lt;code&gt;admin&lt;/code&gt;).&lt;/p&gt;
&lt;h2&gt;Next&amp;nbsp;Steps&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Follow the &lt;a href="https://steadypub.com/2026/06/wazuh-docker-compose/"&gt;Wazuh Docker Compose Setup&lt;/a&gt; guide for full deployment&amp;nbsp;details&lt;/li&gt;
&lt;li&gt;Install agents on all homelab&amp;nbsp;endpoints&lt;/li&gt;
&lt;li&gt;Configure file integrity monitoring and vulnerability&amp;nbsp;detection&lt;/li&gt;
&lt;li&gt;Set up alerts for critical security&amp;nbsp;events&lt;/li&gt;
&lt;/ol&gt;</content><category term="Security"/><category term="wazuh"/><category term="siem"/><category term="security monitoring"/><category term="homelab"/><category term="xdr"/></entry><entry><title>Home Server Monitoring Dashboard: Build Your Own Observability Hub</title><link href="https://steadypub.com/2026/06/homeserver-monitoring-dashboard/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T10:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/homeserver-monitoring-dashboard/</id><summary type="html">&lt;p&gt;Build a home server monitoring dashboard using Grafana, Prometheus, and open-source exporters. Covers metrics, logs, alerting, and visualization best&amp;nbsp;practices.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~15 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab and self-hosting&amp;nbsp;enthusiasts&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Exactly Is&amp;nbsp;It?&lt;/h2&gt;
&lt;p&gt;A home server monitoring dashboard is a centralized visualization interface that displays the health, performance, and status of your homelab infrastructure. It aggregates metrics (&lt;span class="caps"&gt;CPU&lt;/span&gt;, memory, disk, network), logs (application and system events), and alerts (threshold breaches) into a single pane of glass. The most common stack is Grafana (visualization) + Prometheus (metrics) + Loki (logs), but alternatives like Zabbix, Netdata, and Uptime Kuma are also&amp;nbsp;popular.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;A Brief&amp;nbsp;History&lt;/h2&gt;
&lt;p&gt;Homelab monitoring evolved from&amp;nbsp;simple &lt;code&gt;htop&lt;/code&gt; and &lt;code&gt;df -h&lt;/code&gt; commands to full observability platforms. Early tools like Nagios and Cacti gave way to Prometheus (2015) and Grafana (2014), which introduced flexible querying and beautiful dashboards. Today, the &amp;#8220;modern observability stack&amp;#8221; — Prometheus, Grafana, Loki, and Alertmanager — is the standard for homelab operators who want cloud-native monitoring without cloud&amp;nbsp;costs.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why It Matters&amp;nbsp;Today&lt;/h2&gt;
&lt;h3&gt;Prevent&amp;nbsp;Downtime&lt;/h3&gt;
&lt;p&gt;A monitoring dashboard reveals problems before they cause outages. A disk filling up, a container crashing, or a network interface dropping packets are all visible in&amp;nbsp;real-time.&lt;/p&gt;
&lt;h3&gt;Capacity&amp;nbsp;Planning&lt;/h3&gt;
&lt;p&gt;Metrics show trends. If your &lt;span class="caps"&gt;NAS&lt;/span&gt; storage grows by 10% per month, you can plan an expansion before it fills. If your &lt;span class="caps"&gt;CPU&lt;/span&gt; is consistently at 90%, you know it is time to&amp;nbsp;upgrade.&lt;/p&gt;
&lt;h3&gt;Troubleshooting&lt;/h3&gt;
&lt;p&gt;When a service is slow, dashboards help identify the bottleneck. Is it &lt;span class="caps"&gt;CPU&lt;/span&gt;-bound? I/O-bound? Network-latency? Without data, you are&amp;nbsp;guessing.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Core&amp;nbsp;Components&lt;/h2&gt;
&lt;h3&gt;Metrics with&amp;nbsp;Prometheus&lt;/h3&gt;
&lt;p&gt;Prometheus scrapes time-series data from exporters. For a homelab, the essential exporters&amp;nbsp;are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Node Exporter&lt;/strong&gt;: Host metrics (&lt;span class="caps"&gt;CPU&lt;/span&gt;, memory, disk, network,&amp;nbsp;temperature)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;cAdvisor&lt;/strong&gt;: Container metrics (&lt;span class="caps"&gt;CPU&lt;/span&gt;, memory, I/O per&amp;nbsp;container)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Prometheus itself&lt;/strong&gt;: Monitoring the&amp;nbsp;monitor&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example scrape&amp;nbsp;configuration:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;scrape_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;node&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;node-exporter:9100&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;cadvisor&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;cadvisor:8080&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Visualization with&amp;nbsp;Grafana&lt;/h3&gt;
&lt;p&gt;Grafana queries Prometheus and renders dashboards. Key panels for a homelab&amp;nbsp;dashboard:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;System overview&lt;/strong&gt;: &lt;span class="caps"&gt;CPU&lt;/span&gt;, memory, disk usage,&amp;nbsp;uptime&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Container grid&lt;/strong&gt;: Per-container &lt;span class="caps"&gt;CPU&lt;/span&gt; and&amp;nbsp;memory&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Network traffic&lt;/strong&gt;: &lt;span class="caps"&gt;RX&lt;/span&gt;/&lt;span class="caps"&gt;TX&lt;/span&gt; per&amp;nbsp;interface&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Storage&lt;/strong&gt;: Disk usage trends, &lt;span class="caps"&gt;IOPS&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Temperature&lt;/strong&gt;: &lt;span class="caps"&gt;CPU&lt;/span&gt; and sensor temps (if&amp;nbsp;available)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Import dashboard &lt;span class="caps"&gt;ID&lt;/span&gt; &lt;strong&gt;1860&lt;/strong&gt; (Node Exporter Full) for a comprehensive starting&amp;nbsp;point.&lt;/p&gt;
&lt;h3&gt;Logs with&amp;nbsp;Loki&lt;/h3&gt;
&lt;p&gt;Loki aggregates logs from all containers and system services. Use LogQL to&amp;nbsp;query:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;containerlogs&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;error&amp;quot;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;varlogs&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;warn&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Alerting with&amp;nbsp;Alertmanager&lt;/h3&gt;
&lt;p&gt;Prometheus evaluates rules and sends alerts to Alertmanager, which routes them to Slack, Telegram, or email. Example&amp;nbsp;alert:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;DiskSpaceLow&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;(node_filesystem_avail_bytes / node_filesystem_size_bytes) &amp;lt; 0.1&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;5m&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;severity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;warning&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;annotations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Disk&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;space&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;low&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;on&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;$labels.instance&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Advanced&amp;nbsp;Features&lt;/h2&gt;
&lt;h3&gt;Uptime Kuma for Service&amp;nbsp;Monitoring&lt;/h3&gt;
&lt;p&gt;Uptime Kuma is a lightweight, self-hosted uptime monitor with a beautiful &lt;span class="caps"&gt;UI&lt;/span&gt;. It checks &lt;span class="caps"&gt;HTTP&lt;/span&gt;, &lt;span class="caps"&gt;TCP&lt;/span&gt;, ping, and &lt;span class="caps"&gt;DNS&lt;/span&gt; every minute. It is the perfect complement to Grafana for &amp;#8220;is the service up?&amp;#8221;&amp;nbsp;monitoring.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;uptime-kuma&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;louislam/uptime-kuma:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3001:3001&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;uptime-kuma:/app/data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Custom Dashboards for Specific&amp;nbsp;Services&lt;/h3&gt;
&lt;p&gt;Create per-service dashboards&amp;nbsp;for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Nextcloud&lt;/strong&gt;: Active users, file operations,&amp;nbsp;storage&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Jellyfin&lt;/strong&gt;: Active streams, transcode sessions,&amp;nbsp;bandwidth&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pi-hole&lt;/strong&gt;: Queries blocked, top clients, query&amp;nbsp;types&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Traefik&lt;/strong&gt;: Request rates, response codes,&amp;nbsp;latency&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Geolocation and Network&amp;nbsp;Maps&lt;/h3&gt;
&lt;p&gt;Use the Worldmap plugin or GeoIP data to visualize where your traffic originates. Useful for public-facing services and &lt;span class="caps"&gt;VPN&lt;/span&gt;&amp;nbsp;endpoints.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Integrating with Your&amp;nbsp;Homelab&lt;/h2&gt;
&lt;h3&gt;Reverse&amp;nbsp;Proxy&lt;/h3&gt;
&lt;p&gt;Expose Grafana via &lt;span class="caps"&gt;HTTPS&lt;/span&gt; with&amp;nbsp;Traefik:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.enable=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.grafana.rule=Host(`grafana.yourdomain.com`)&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.grafana.tls.certresolver=letsencrypt&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Backup&lt;/h3&gt;
&lt;p&gt;Back up Grafana dashboards and Prometheus&amp;nbsp;data:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Export all dashboards&lt;/span&gt;
mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;dashboards
&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;uid&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;http://admin:admin@localhost:3000/api/search&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;jq&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;.[].uid&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;http://admin:admin@localhost:3000/api/dashboards/uid/&lt;span class="nv"&gt;$uid&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;dashboards/&lt;span class="nv"&gt;$uid&lt;/span&gt;.json
&lt;span class="k"&gt;done&lt;/span&gt;

&lt;span class="c1"&gt;# Backup Prometheus data volume&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;--rm&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;prometheus_data:/data&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;:/backup&lt;span class="w"&gt; &lt;/span&gt;alpine&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;tar&lt;span class="w"&gt; &lt;/span&gt;czf&lt;span class="w"&gt; &lt;/span&gt;/backup/prometheus-backup.tar.gz&lt;span class="w"&gt; &lt;/span&gt;-C&lt;span class="w"&gt; &lt;/span&gt;/data&lt;span class="w"&gt; &lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Alternatives to&amp;nbsp;Consider&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;Complexity&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Grafana + Prometheus&lt;/td&gt;
&lt;td&gt;Full observability&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Zabbix&lt;/td&gt;
&lt;td&gt;All-in-one monitoring&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Netdata&lt;/td&gt;
&lt;td&gt;Real-time, per-second&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Uptime Kuma&lt;/td&gt;
&lt;td&gt;Uptime checks&lt;/td&gt;
&lt;td&gt;Very Low&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nagios&lt;/td&gt;
&lt;td&gt;Legacy enterprise&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Frequently Asked&amp;nbsp;Questions&lt;/h2&gt;
&lt;h3&gt;How much &lt;span class="caps"&gt;RAM&lt;/span&gt; does a monitoring stack&amp;nbsp;need?&lt;/h3&gt;
&lt;p&gt;Prometheus + Grafana + Loki use ~1 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; for a small homelab. Scale to 2–4 &lt;span class="caps"&gt;GB&lt;/span&gt; for 10+ hosts or long&amp;nbsp;retention.&lt;/p&gt;
&lt;h3&gt;Can I monitor Windows&amp;nbsp;machines?&lt;/h3&gt;
&lt;p&gt;Yes. Use the Windows Exporter for Prometheus. It exposes the same metrics as Node Exporter for Windows&amp;nbsp;hosts.&lt;/p&gt;
&lt;h3&gt;Do I need a dedicated monitoring&amp;nbsp;server?&lt;/h3&gt;
&lt;p&gt;No. Run the stack on your primary homelab server. If that server fails, you lose monitoring but not the services themselves. For critical infrastructure, run a lightweight monitoring node on a Raspberry&amp;nbsp;Pi.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;A home server monitoring dashboard is essential for any serious homelab. It transforms invisible infrastructure into visible, actionable data. With Prometheus, Grafana, and Loki, you gain the same observability used by cloud providers — on your own hardware, for&amp;nbsp;free.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Deploy the Prometheus + Grafana + Loki&amp;nbsp;stack&lt;/li&gt;
&lt;li&gt;Import Node Exporter and cAdvisor&amp;nbsp;dashboards&lt;/li&gt;
&lt;li&gt;Set up Alertmanager for critical&amp;nbsp;notifications&lt;/li&gt;
&lt;li&gt;Add Uptime Kuma for service-level&amp;nbsp;monitoring&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;installation&lt;/strong&gt;: hosting — &lt;span class="caps"&gt;VPS&lt;/span&gt; for remote&amp;nbsp;monitoring&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;integration&lt;/strong&gt;: tool — Grafana Cloud,&amp;nbsp;PagerDuty&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;alternatives&lt;/strong&gt;: tool — Datadog, New&amp;nbsp;Relic&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;installation&lt;/code&gt; → setup_guide: &lt;a href="https://steadypub.com/2026/06/docker-compose-for-beginners/"&gt;Docker Compose for&amp;nbsp;beginners&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;integration&lt;/code&gt; → related_guide: &lt;a href="https://steadypub.com/2026/06/grafana-loki-logs/"&gt;Grafana Loki log&amp;nbsp;aggregation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;alternatives&lt;/code&gt; → comparison: &lt;a href="https://steadypub.com/2026/06/prometheus-vs-influxdb/"&gt;Prometheus vs&amp;nbsp;InfluxDB&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] What does your monitoring stack look like? Share your dashboard&amp;nbsp;screenshots.&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for weekly observability and homelab monitoring&amp;nbsp;guides.&lt;/li&gt;
&lt;li&gt;[internal_link] Next: &lt;a href="https://steadypub.com/2026/06/prometheus-alertmanager-setup/"&gt;set up Prometheus&amp;nbsp;Alertmanager&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Monitoring"/><category term="monitoring"/><category term="dashboard"/><category term="homelab"/><category term="grafana"/><category term="prometheus"/><category term="docker"/></entry><entry><title>How to Install Proxmox VE on an Old PC: Turn E-Waste into a Homelab Powerhouse</title><link href="https://steadypub.com/2026/06/how-to-install-proxmox-on-old-pc/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T10:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/how-to-install-proxmox-on-old-pc/</id><summary type="html">&lt;p&gt;Transform an old desktop or laptop into a Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; server. Step-by-step installation, hardware requirements, &lt;span class="caps"&gt;BIOS&lt;/span&gt; settings, and first &lt;span class="caps"&gt;VM&lt;/span&gt;&amp;nbsp;creation.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~15 minutes&lt;br&gt;
&lt;strong&gt;Audience:&lt;/strong&gt; Beginners with spare hardware wanting to start a&amp;nbsp;homelab&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What You&amp;#8217;ll&amp;nbsp;Need&lt;/h2&gt;
&lt;h3&gt;Minimum&amp;nbsp;Hardware&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Minimum&lt;/th&gt;
&lt;th&gt;Recommended&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;64-bit dual-core&lt;/td&gt;
&lt;td&gt;Intel i5/i7 or &lt;span class="caps"&gt;AMD&lt;/span&gt; Ryzen 4-core+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;4GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;16GB&lt;/span&gt;+ (for multiple VMs)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;32GB&lt;/span&gt; free space&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;128GB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt; (NVMe preferred)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Network&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1x Gigabit Ethernet&lt;/td&gt;
&lt;td&gt;2x Gigabit (for clustering)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;USB&lt;/span&gt; drive&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;8GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;8GB&lt;/span&gt;+ for installer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Monitor&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Temporary (for install)&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;HDMI&lt;/span&gt;/&lt;span class="caps"&gt;DVI&lt;/span&gt;/DisplayPort&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Keyboard&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;USB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;USB&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Supported&amp;nbsp;Hardware&lt;/h3&gt;
&lt;p&gt;Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; is based on Debian, so most x86_64 hardware&amp;nbsp;works:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Intel:&lt;/strong&gt; Core 2 Duo and newer (&lt;span class="caps"&gt;VT&lt;/span&gt;-x required, &lt;span class="caps"&gt;VT&lt;/span&gt;-d&amp;nbsp;preferred)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;AMD&lt;/span&gt;:&lt;/strong&gt; Athlon 64 and newer (&lt;span class="caps"&gt;AMD&lt;/span&gt;-V required, &lt;span class="caps"&gt;IOMMU&lt;/span&gt;&amp;nbsp;preferred)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mini PCs:&lt;/strong&gt; Intel N100/N305, Minisforum, Beelink (ideal for&amp;nbsp;24/7)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Laptops:&lt;/strong&gt; Works but battery/thermal management&amp;nbsp;varies&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Servers:&lt;/strong&gt; Dell OptiPlex, &lt;span class="caps"&gt;HP&lt;/span&gt; EliteDesk, Lenovo ThinkCentre&amp;nbsp;(excellent)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Verify Virtualization&amp;nbsp;Support&lt;/h2&gt;
&lt;h3&gt;Check &lt;span class="caps"&gt;BIOS&lt;/span&gt;/&lt;span class="caps"&gt;UEFI&lt;/span&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Boot into &lt;span class="caps"&gt;BIOS&lt;/span&gt;&amp;nbsp;(usually &lt;code&gt;Del&lt;/code&gt;, &lt;code&gt;F2&lt;/code&gt;, &lt;code&gt;F10&lt;/code&gt;,&amp;nbsp;or &lt;code&gt;F12&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Look for these&amp;nbsp;settings:&lt;/li&gt;
&lt;/ol&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Setting&lt;/th&gt;
&lt;th&gt;Intel Name&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;AMD&lt;/span&gt; Name&lt;/th&gt;
&lt;th&gt;Required&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt; virtualization&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Intel &lt;span class="caps"&gt;VT&lt;/span&gt;-x&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;AMD&lt;/span&gt;-V&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;I/O virtualization&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Intel &lt;span class="caps"&gt;VT&lt;/span&gt;-d&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;AMD&lt;/span&gt; &lt;span class="caps"&gt;IOMMU&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;⚠️ Preferred&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Secure Boot&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;❌ Disable for Proxmox&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Verify from Linux Live &lt;span class="caps"&gt;USB&lt;/span&gt;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Check if CPU supports virtualization&lt;/span&gt;
egrep&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;(vmx|svm)&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/proc/cpuinfo
&lt;span class="c1"&gt;# Output &amp;gt; 0 = supported&lt;/span&gt;

&lt;span class="c1"&gt;# Check if KVM is usable&lt;/span&gt;
kvm-ok
&lt;span class="c1"&gt;# Should show: KVM acceleration can be used&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 2: Download Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Visit&amp;nbsp;https://www.proxmox.com/en/downloads&lt;/li&gt;
&lt;li&gt;Download &lt;strong&gt;Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; &lt;span class="caps"&gt;ISO&lt;/span&gt; Installer&lt;/strong&gt; (latest stable, e.g.,&amp;nbsp;8.x)&lt;/li&gt;
&lt;li&gt;Verify&amp;nbsp;checksum:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sha256sum&lt;span class="w"&gt; &lt;/span&gt;proxmox-ve_8.x-x.iso
&lt;span class="c1"&gt;# Compare with published checksum on proxmox.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 3: Create Bootable &lt;span class="caps"&gt;USB&lt;/span&gt;&lt;/h2&gt;
&lt;h3&gt;Option A: BalenaEtcher&amp;nbsp;(Windows/Mac/Linux)&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Download&amp;nbsp;https://www.balena.io/etcher/&lt;/li&gt;
&lt;li&gt;Select &lt;span class="caps"&gt;ISO&lt;/span&gt; → Select &lt;span class="caps"&gt;USB&lt;/span&gt; drive →&amp;nbsp;Flash&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Option B: dd&amp;nbsp;(Linux/macOS)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Identify USB drive (be careful!)&lt;/span&gt;
lsblk
&lt;span class="c1"&gt;# Example: /dev/sdb&lt;/span&gt;

&lt;span class="c1"&gt;# Flash ISO&lt;/span&gt;
dd&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;proxmox-ve_8.x-x.iso&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/sdb&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4M&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;progress
sync
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Option C: Ventoy (Multi-&lt;span class="caps"&gt;ISO&lt;/span&gt; &lt;span class="caps"&gt;USB&lt;/span&gt;)&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Install Ventoy to &lt;span class="caps"&gt;USB&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Copy &lt;span class="caps"&gt;ISO&lt;/span&gt; to Ventoy&amp;nbsp;partition&lt;/li&gt;
&lt;li&gt;Boot and select &lt;span class="caps"&gt;ISO&lt;/span&gt; from&amp;nbsp;menu&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Step 4: Install Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;&lt;/h2&gt;
&lt;h3&gt;Boot from &lt;span class="caps"&gt;USB&lt;/span&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Insert &lt;span class="caps"&gt;USB&lt;/span&gt; into old &lt;span class="caps"&gt;PC&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Power on and press boot menu key&amp;nbsp;(&lt;code&gt;F12&lt;/code&gt;, &lt;code&gt;F10&lt;/code&gt;, &lt;code&gt;Esc&lt;/code&gt;,&amp;nbsp;or &lt;code&gt;F2&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Select &lt;span class="caps"&gt;USB&lt;/span&gt; drive from boot&amp;nbsp;menu&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Installation&amp;nbsp;Steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Select &amp;#8220;Install Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;&amp;#8221;&lt;/strong&gt; from &lt;span class="caps"&gt;GRUB&lt;/span&gt;&amp;nbsp;menu&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Agree to &lt;span class="caps"&gt;EULA&lt;/span&gt;&lt;/strong&gt; (&lt;span class="caps"&gt;GNU&lt;/span&gt; &lt;span class="caps"&gt;AGPL&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Select target disk&lt;/strong&gt; (&lt;span class="caps"&gt;SSD&lt;/span&gt; recommended over &lt;span class="caps"&gt;HDD&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Choose&amp;nbsp;filesystem:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ext4&lt;/strong&gt; — Simple,&amp;nbsp;reliable&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;ZFS&lt;/span&gt; (&lt;span class="caps"&gt;RAIDZ&lt;/span&gt;)&lt;/strong&gt; — If you have multiple disks and want&amp;nbsp;redundancy&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Set timezone, keyboard, and&amp;nbsp;password&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configure&amp;nbsp;network:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Hostname: &lt;code&gt;pve.local&lt;/code&gt; or &lt;code&gt;pve.mydomain.com&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;IP&lt;/span&gt; address: Static recommended&amp;nbsp;(e.g., &lt;code&gt;192.168.1.10&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Gateway: Your router &lt;span class="caps"&gt;IP&lt;/span&gt;&amp;nbsp;(e.g., &lt;code&gt;192.168.1.1&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt;: &lt;code&gt;1.1.1.1&lt;/code&gt; or &lt;code&gt;192.168.1.1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Review summary&lt;/strong&gt; and confirm&amp;nbsp;installation&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Wait 5–10 minutes&lt;/strong&gt; for installation to&amp;nbsp;complete&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reboot&lt;/strong&gt; and remove &lt;span class="caps"&gt;USB&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Post-Install First&amp;nbsp;Boot&lt;/h3&gt;
&lt;p&gt;After reboot, you&amp;#8217;ll see the Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;&amp;nbsp;console:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Welcome to the Proxmox Virtual Environment.

https://192.168.1.10:8006
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 5: Initial Web &lt;span class="caps"&gt;UI&lt;/span&gt;&amp;nbsp;Configuration&lt;/h2&gt;
&lt;h3&gt;Access Web &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;On another computer, open&amp;nbsp;browser:
   &lt;code&gt;https://192.168.1.10:8006&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Accept self-signed certificate&amp;nbsp;warning&lt;/li&gt;
&lt;li&gt;Login&amp;nbsp;with &lt;code&gt;root&lt;/code&gt; and your install&amp;nbsp;password&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Realm:&lt;/strong&gt; Linux standard &lt;span class="caps"&gt;PAM&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;First Tasks in Web &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Remove subscription warning&lt;/strong&gt; (free use is fully&amp;nbsp;allowed)
   &lt;code&gt;bash
   # SSH into Proxmox host
   ssh root@192.168.1.10
   sed -i 's/NotSubscribed/Active/g' /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js
   systemctl restart pveproxy&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Update&amp;nbsp;system:&lt;/strong&gt;
   &lt;code&gt;bash
   apt update &amp;amp;&amp;amp; apt dist-upgrade -y&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Configure&amp;nbsp;storage:&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Datacenter → Storage → Add → Directory or &lt;span class="caps"&gt;ZFS&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Upload &lt;span class="caps"&gt;ISO&lt;/span&gt;&amp;nbsp;templates:&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Local → &lt;span class="caps"&gt;ISO&lt;/span&gt; Images →&amp;nbsp;Upload&lt;/li&gt;
&lt;li&gt;Download Ubuntu, Debian, Windows Server&amp;nbsp;ISOs&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Step 6: Create Your First &lt;span class="caps"&gt;VM&lt;/span&gt;&lt;/h2&gt;
&lt;h3&gt;Create a Linux &lt;span class="caps"&gt;VM&lt;/span&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Click &lt;strong&gt;&amp;#8220;Create &lt;span class="caps"&gt;VM&lt;/span&gt;&amp;#8221;&lt;/strong&gt; (top&amp;nbsp;right)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;General:&lt;/strong&gt;&amp;nbsp;Name &lt;code&gt;ubuntu-test&lt;/code&gt;, &lt;span class="caps"&gt;VM&lt;/span&gt; &lt;span class="caps"&gt;ID&lt;/span&gt; &lt;code&gt;100&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;OS&lt;/span&gt;:&lt;/strong&gt; Select Ubuntu &lt;span class="caps"&gt;ISO&lt;/span&gt; from&amp;nbsp;dropdown&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;System:&lt;/strong&gt; Defaults (&lt;span class="caps"&gt;QEMU&lt;/span&gt; agent:&amp;nbsp;checked)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Disks:&lt;/strong&gt; &lt;span class="caps"&gt;32GB&lt;/span&gt;, &lt;span class="caps"&gt;SCSI&lt;/span&gt;, VirtIO &lt;span class="caps"&gt;SCSI&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;:&lt;/strong&gt; 2 cores, host&amp;nbsp;type&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Memory:&lt;/strong&gt; 2048 &lt;span class="caps"&gt;MB&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Network:&lt;/strong&gt; VirtIO, bridged&amp;nbsp;to &lt;code&gt;vmbr0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Confirm&lt;/strong&gt; and start &lt;span class="caps"&gt;VM&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Install Ubuntu in &lt;span class="caps"&gt;VM&lt;/span&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Click &lt;strong&gt;Console&lt;/strong&gt;&amp;nbsp;tab&lt;/li&gt;
&lt;li&gt;Complete Ubuntu installation&amp;nbsp;normally&lt;/li&gt;
&lt;li&gt;After reboot, install &lt;span class="caps"&gt;QEMU&lt;/span&gt; Guest&amp;nbsp;Agent:
   &lt;code&gt;bash
   sudo apt install qemu-guest-agent
   sudo systemctl enable qemu-guest-agent&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Step 7: Create Your First &lt;span class="caps"&gt;LXC&lt;/span&gt;&amp;nbsp;Container&lt;/h2&gt;
&lt;p&gt;Containers are lighter than&amp;nbsp;VMs:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Click &lt;strong&gt;&amp;#8220;Create &lt;span class="caps"&gt;CT&lt;/span&gt;&amp;#8221;&lt;/strong&gt; (top&amp;nbsp;right)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;General:&lt;/strong&gt;&amp;nbsp;Name &lt;code&gt;nginx-test&lt;/code&gt;, &lt;span class="caps"&gt;CT&lt;/span&gt; &lt;span class="caps"&gt;ID&lt;/span&gt; &lt;code&gt;200&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Template:&lt;/strong&gt;&amp;nbsp;Select &lt;code&gt;ubuntu-22.04-standard&lt;/code&gt; (download first if&amp;nbsp;needed)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Disks:&lt;/strong&gt; &lt;span class="caps"&gt;8GB&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;:&lt;/strong&gt; 1&amp;nbsp;core&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Memory:&lt;/strong&gt; 512 &lt;span class="caps"&gt;MB&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Network:&lt;/strong&gt; &lt;span class="caps"&gt;DHCP&lt;/span&gt; or static &lt;span class="caps"&gt;IP&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Confirm&lt;/strong&gt; and start&amp;nbsp;container&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Install Nginx in&amp;nbsp;Container&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# From Proxmox console or SSH into CT&lt;/span&gt;
apt&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;nginx&lt;span class="w"&gt; &lt;/span&gt;-y
curl&lt;span class="w"&gt; &lt;/span&gt;http://localhost
&lt;span class="c1"&gt;# Should show Nginx welcome page&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Performance Tips for Old&amp;nbsp;Hardware&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tip&lt;/th&gt;
&lt;th&gt;Why It Helps&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Use &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;10x faster boot than &lt;span class="caps"&gt;HDD&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Enable &lt;span class="caps"&gt;ZFS&lt;/span&gt; compression&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Saves space on small SSDs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Use &lt;span class="caps"&gt;LXC&lt;/span&gt; over VMs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;10x less &lt;span class="caps"&gt;RAM&lt;/span&gt; per container&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Disable &lt;span class="caps"&gt;GUI&lt;/span&gt; on host&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Proxmox is headless; save &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Enable &lt;span class="caps"&gt;CPU&lt;/span&gt; power saving&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;cpufreq-set -g ondemand&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Add &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Best upgrade: &lt;span class="caps"&gt;16GB&lt;/span&gt; enables 5–10 VMs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Use virtio drivers&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Best disk/network performance in VMs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Common Installation&amp;nbsp;Issues&lt;/h2&gt;
&lt;h3&gt;Issue 1: &amp;#8220;No Network Interface&amp;nbsp;Found&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Cause:&lt;/strong&gt; Missing &lt;span class="caps"&gt;NIC&lt;/span&gt; driver&lt;br&gt;
&lt;strong&gt;Fix:&lt;/strong&gt; Check if &lt;span class="caps"&gt;NIC&lt;/span&gt; is supported. Realtek NICs may&amp;nbsp;need &lt;code&gt;r8168-dkms&lt;/code&gt; package.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;apt&lt;span class="w"&gt; &lt;/span&gt;update
apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;r8168-dkms&lt;span class="w"&gt; &lt;/span&gt;-y
reboot
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Issue 2: &amp;#8220;Secure Boot&amp;nbsp;Violation&amp;#8221;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Cause:&lt;/strong&gt; Secure Boot enabled&lt;br&gt;
&lt;strong&gt;Fix:&lt;/strong&gt; Disable Secure Boot in &lt;span class="caps"&gt;BIOS&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;Issue 3: Installation&amp;nbsp;Freezes&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Cause:&lt;/strong&gt; Old &lt;span class="caps"&gt;USB&lt;/span&gt; 2.0 port or bad &lt;span class="caps"&gt;USB&lt;/span&gt; drive&lt;br&gt;
&lt;strong&gt;Fix:&lt;/strong&gt; Use &lt;span class="caps"&gt;USB&lt;/span&gt; 3.0 port, reflash &lt;span class="caps"&gt;USB&lt;/span&gt;, or try&amp;nbsp;Ventoy.&lt;/p&gt;
&lt;h3&gt;Issue 4: Low Disk Space&amp;nbsp;Warning&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Cause:&lt;/strong&gt; Proxmox needs &lt;span class="caps"&gt;32GB&lt;/span&gt;+ for root&lt;br&gt;
&lt;strong&gt;Fix:&lt;/strong&gt; Use a larger disk or add external storage via &lt;span class="caps"&gt;NFS&lt;/span&gt;/iSCSI.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Any old &lt;span class="caps"&gt;PC&lt;/span&gt; with a 64-bit &lt;span class="caps"&gt;CPU&lt;/span&gt;, &lt;span class="caps"&gt;4GB&lt;/span&gt;+ &lt;span class="caps"&gt;RAM&lt;/span&gt;, and an &lt;span class="caps"&gt;SSD&lt;/span&gt; can run Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;. Installation takes 15 minutes, and you&amp;#8217;ll have a full virtualization platform capable of running VMs, containers, and a complete homelab&amp;nbsp;stack.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Install your first 5 services&lt;/strong&gt; (see our self-hosted services&amp;nbsp;list)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configure backups&lt;/strong&gt; with Proxmox Backup Server or&amp;nbsp;vzdump&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Set up monitoring&lt;/strong&gt; with Grafana +&amp;nbsp;Prometheus&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Read our Proxmox beginner guide&lt;/strong&gt; for advanced networking and&amp;nbsp;storage&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mini PCs:&lt;/strong&gt; Minisforum &lt;span class="caps"&gt;MS&lt;/span&gt;-01, Beelink &lt;span class="caps"&gt;SER7&lt;/span&gt;, Intel &lt;span class="caps"&gt;NUC&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SSDs:&lt;/strong&gt; Samsung 870 &lt;span class="caps"&gt;EVO&lt;/span&gt;, &lt;span class="caps"&gt;WD&lt;/span&gt; Blue &lt;span class="caps"&gt;SN570&lt;/span&gt;&amp;nbsp;NVMe&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;:&lt;/strong&gt; &lt;span class="caps"&gt;DDR4&lt;/span&gt;/&lt;span class="caps"&gt;DDR5&lt;/span&gt; upgrades for old&amp;nbsp;laptops&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Networking:&lt;/strong&gt; Intel NICs, switches, patch&amp;nbsp;cables&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;UPS&lt;/span&gt;:&lt;/strong&gt; &lt;span class="caps"&gt;APC&lt;/span&gt; Back-&lt;span class="caps"&gt;UPS&lt;/span&gt; Pro for power&amp;nbsp;protection&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal&amp;nbsp;Linking&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;proxmox-guide&lt;/code&gt; → &lt;code&gt;proxmox-beginner-guide-2026.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;services&lt;/code&gt; → &lt;code&gt;self-hosted-services-list.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;monitoring&lt;/code&gt; → &lt;code&gt;docker-monitoring-grafana-prometheus.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hardware&lt;/code&gt; → &lt;code&gt;best-mini-pc-for-homelab.md&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;What old hardware are you running Proxmox on?&lt;/strong&gt; Share your specs in the&amp;nbsp;comments.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subscribe&lt;/strong&gt; for beginner-friendly homelab guides and&amp;nbsp;tutorials.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Guides"/><category term="how to install proxmox on old pc"/><category term="proxmox beginner guide"/><category term="old pc homelab"/><category term="proxmox hardware requirements"/><category term="homelab virtualization"/></entry><entry><title>Immich Photo Server: The Ultimate Self-Hosted Guide for 2026</title><link href="https://steadypub.com/2026/06/immich-photo-server/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T10:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/immich-photo-server/</id><summary type="html">&lt;p&gt;Deploy Immich as a self-hosted Google Photos replacement. Covers Docker Compose setup, mobile auto-upload, machine learning features, and backup&amp;nbsp;strategies.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~15 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab and self-hosting&amp;nbsp;enthusiasts&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is&amp;nbsp;Immich?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Immich is a high-performance, self-hosted photo and video management platform designed as a replacement for Google Photos, iCloud, and Amazon Photos. It offers automatic mobile backup, facial recognition, duplicate detection, and a modern web interface. Unlike Nextcloud&amp;#8217;s Photos app, Immich is purpose-built for media with a focus on speed, organization, and &lt;span class="caps"&gt;AI&lt;/span&gt;-powered features. It is open-source (&lt;span class="caps"&gt;MIT&lt;/span&gt; license) and actively developed with a large&amp;nbsp;community.&lt;/p&gt;
&lt;h3&gt;A Brief&amp;nbsp;History&lt;/h3&gt;
&lt;p&gt;Immich was created by Alex Tran in 2022 out of frustration with Big Tech photo services. The project quickly gained traction on GitHub and Hacker News due to its polished &lt;span class="caps"&gt;UI&lt;/span&gt; and aggressive feature roadmap. By 2024, Immich supported machine learning (&lt;span class="caps"&gt;CLIP&lt;/span&gt;-based search, facial recognition), hardware-accelerated transcoding, and OAuth login. It has become the default recommendation in the self-hosted community for photo&amp;nbsp;management.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why Use Immich in Your&amp;nbsp;Homelab?&lt;/h2&gt;
&lt;h3&gt;Privacy-First Photo&amp;nbsp;Storage&lt;/h3&gt;
&lt;p&gt;Your photos are stored on your own hardware. There is no &lt;span class="caps"&gt;AI&lt;/span&gt; training on your data, no facial recognition by third parties, and no risk of account termination causing data loss. For parents, photographers, and privacy advocates, this is&amp;nbsp;non-negotiable.&lt;/p&gt;
&lt;h3&gt;&lt;span class="caps"&gt;AI&lt;/span&gt;-Powered Search and&amp;nbsp;Organization&lt;/h3&gt;
&lt;p&gt;Immich uses machine learning models&amp;nbsp;to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Recognize faces&lt;/strong&gt; and group photos by&amp;nbsp;person&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Classify objects and scenes&lt;/strong&gt; (beach, dog,&amp;nbsp;sunset)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Generate natural language search&lt;/strong&gt; (&amp;#8220;photos of my dog at the&amp;nbsp;beach&amp;#8221;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Detect duplicates&lt;/strong&gt; across your&amp;nbsp;library&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These models run locally on your server. No data is sent to external&amp;nbsp;APIs.&lt;/p&gt;
&lt;h3&gt;Automatic Mobile&amp;nbsp;Backup&lt;/h3&gt;
&lt;p&gt;The Immich mobile app (iOS/Android) supports background upload, &lt;span class="caps"&gt;RAW&lt;/span&gt; file support, and burst photo handling. It can upload over Wi-Fi or cellular, with configurable quality settings (original or compressed). The app is native, fast, and supports offline viewing of recently accessed&amp;nbsp;albums.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;h3&gt;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;A Linux server with 2+ vCPUs, 4 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; (8 &lt;span class="caps"&gt;GB&lt;/span&gt;+ recommended for &lt;span class="caps"&gt;ML&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;Docker and Docker&amp;nbsp;Compose&lt;/li&gt;
&lt;li&gt;An &lt;span class="caps"&gt;NVIDIA&lt;/span&gt; &lt;span class="caps"&gt;GPU&lt;/span&gt; (optional but strongly recommended for &lt;span class="caps"&gt;ML&lt;/span&gt;&amp;nbsp;tasks)&lt;/li&gt;
&lt;li&gt;At least 100 &lt;span class="caps"&gt;GB&lt;/span&gt; storage for photos and &lt;span class="caps"&gt;ML&lt;/span&gt;&amp;nbsp;models&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Method 1: Docker Compose&amp;nbsp;(Recommended)&lt;/h3&gt;
&lt;p&gt;Immich is a multi-service application. The official Compose template includes the server, machine learning service, PostgreSQL, and&amp;nbsp;Redis.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;immich-server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;immich_server&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ghcr.io/immich-app/immich-server:release&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;start.sh&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;immich&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;${UPLOAD_LOCATION}:/usr/src/app/upload&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;env_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;.env&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;2283:3001&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;database&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;immich-microservices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;immich_microservices&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ghcr.io/immich-app/immich-server:release&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;start.sh&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;microservices&amp;quot;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;${UPLOAD_LOCATION}:/usr/src/app/upload&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;env_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;.env&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;database&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;immich-machine-learning&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;immich_machine_learning&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ghcr.io/immich-app/immich-machine-learning:release&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;model-cache:/cache&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;env_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;.env&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;immich_redis&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis:7-alpine&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;database&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;immich_postgres&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;tensorchord/pgvecto-rs:pg14-v0.2.0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;env_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;.env&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;${DB_PASSWORD}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;${DB_USERNAME}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;${DB_DATABASE_NAME}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pgdata:/var/lib/postgresql/data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;pgdata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;model-cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Create &lt;code&gt;.env&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;UPLOAD_LOCATION&lt;/span&gt;&lt;span class="p"&gt;=.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="kn"&gt;library&lt;/span&gt;
&lt;span class="nx"&gt;IMMICH_VERSION&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;release&lt;/span&gt;
&lt;span class="nx"&gt;DB_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="o"&gt;***&lt;/span&gt;
&lt;span class="nx"&gt;DB_USERNAME&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;postgres&lt;/span&gt;
&lt;span class="nx"&gt;DB_DATABASE_NAME&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;immich&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Deploy:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Access the web &lt;span class="caps"&gt;UI&lt;/span&gt;&amp;nbsp;at &lt;code&gt;http://your-server:2283&lt;/code&gt;. Create the first admin&amp;nbsp;user.&lt;/p&gt;
&lt;h3&gt;Method 2: &lt;span class="caps"&gt;GPU&lt;/span&gt;-Accelerated Machine&amp;nbsp;Learning&lt;/h3&gt;
&lt;p&gt;If you have an &lt;span class="caps"&gt;NVIDIA&lt;/span&gt; &lt;span class="caps"&gt;GPU&lt;/span&gt;, enable &lt;span class="caps"&gt;CUDA&lt;/span&gt; for faster face recognition and object&amp;nbsp;classification:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;immich-machine-learning&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;immich_machine_learning&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ghcr.io/immich-app/immich-machine-learning:release-cuda&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;model-cache:/cache&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;env_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;.env&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;reservations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;devices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nvidia&lt;/span&gt;
&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nt"&gt;capabilities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;gpu&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Ensure the &lt;span class="caps"&gt;NVIDIA&lt;/span&gt; Container Toolkit is installed on the&amp;nbsp;host.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Basic Setup and&amp;nbsp;Configuration&lt;/h2&gt;
&lt;h3&gt;Step 1: Configure the Mobile&amp;nbsp;App&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Download the Immich app from the App Store or Google&amp;nbsp;Play&lt;/li&gt;
&lt;li&gt;Enter your server &lt;span class="caps"&gt;URL&lt;/span&gt;: &lt;code&gt;http://your-server:2283&lt;/code&gt; (or &lt;code&gt;https://&lt;/code&gt; behind a reverse&amp;nbsp;proxy)&lt;/li&gt;
&lt;li&gt;Log in with your&amp;nbsp;credentials&lt;/li&gt;
&lt;li&gt;Enable &lt;strong&gt;Background Upload&lt;/strong&gt; in&amp;nbsp;settings&lt;/li&gt;
&lt;li&gt;Set upload quality to &lt;strong&gt;Original&lt;/strong&gt; (or &lt;strong&gt;Compressed&lt;/strong&gt; to save&amp;nbsp;space)&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Step 2: Organize with Albums and&amp;nbsp;Tags&lt;/h3&gt;
&lt;p&gt;The web &lt;span class="caps"&gt;UI&lt;/span&gt; supports albums, tags, and favorites. Create albums for events (&amp;#8220;Vacation 2025&amp;#8221;, &amp;#8220;Baby&amp;#8217;s First Year&amp;#8221;). The &lt;span class="caps"&gt;AI&lt;/span&gt; will auto-suggest tags based on content. You can also manually tag photos for precise&amp;nbsp;organization.&lt;/p&gt;
&lt;h3&gt;Step 3: Run the Machine Learning&amp;nbsp;Pipeline&lt;/h3&gt;
&lt;p&gt;After uploading photos, the machine learning service processes them in the background. For a large library, this can take hours. Monitor progress in &lt;strong&gt;Administration&lt;/strong&gt; → &lt;strong&gt;Jobs&lt;/strong&gt;. You can manually trigger or pause&amp;nbsp;jobs.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Advanced&amp;nbsp;Features&lt;/h2&gt;
&lt;h3&gt;External&amp;nbsp;Libraries&lt;/h3&gt;
&lt;p&gt;Immich can ingest photos from existing directories without duplicating them. This is useful if you already have a &lt;span class="caps"&gt;NAS&lt;/span&gt; or a well-organized file&amp;nbsp;structure.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;In &lt;strong&gt;Administration&lt;/strong&gt; → &lt;strong&gt;External Libraries&lt;/strong&gt;, add a&amp;nbsp;path&lt;/li&gt;
&lt;li&gt;Set the scan schedule (e.g., daily at 2 &lt;span class="caps"&gt;AM&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;Immich will read the files in-place and generate&amp;nbsp;thumbnails&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Storage&amp;nbsp;Template&lt;/h3&gt;
&lt;p&gt;Immich stores files in a flat directory by default. You can configure a storage template to organize files by&amp;nbsp;date:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;y&lt;/span&gt;&lt;span class="cp"&gt;}}&lt;/span&gt;&lt;span class="x"&gt;/&lt;/span&gt;&lt;span class="cp"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;y&lt;/span&gt;&lt;span class="cp"&gt;}}&lt;/span&gt;&lt;span class="x"&gt;-&lt;/span&gt;&lt;span class="cp"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;M&lt;/span&gt;&lt;span class="cp"&gt;}}&lt;/span&gt;&lt;span class="x"&gt;-&lt;/span&gt;&lt;span class="cp"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt;&lt;span class="cp"&gt;}}&lt;/span&gt;&lt;span class="x"&gt;/&lt;/span&gt;&lt;span class="cp"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;filename&lt;/span&gt;&lt;span class="cp"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This makes it easier to browse the library directly on the&amp;nbsp;filesystem.&lt;/p&gt;
&lt;h3&gt;Duplicate&amp;nbsp;Detection&lt;/h3&gt;
&lt;p&gt;Immich runs a duplicate detection job that compares file hashes and perceptual hashes. You can review duplicates in the web &lt;span class="caps"&gt;UI&lt;/span&gt; and choose which to keep. This is invaluable when importing libraries from multiple&amp;nbsp;sources.&lt;/p&gt;
&lt;h3&gt;OAuth and &lt;span class="caps"&gt;SSO&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Immich supports OpenID Connect (&lt;span class="caps"&gt;OIDC&lt;/span&gt;) for single sign-on. Configure it with Authentik, Keycloak, or&amp;nbsp;Authelia:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;OAUTH_ENABLED=true
OAUTH_ISSUER_URL=https://authentik.example.com/application/o/immich/
OAUTH_CLIENT_ID=your-client-id
OAUTH_CLIENT_SECRET=your-client-secret
OAUTH_BUTTON_TEXT=Login with Authentik
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Integrating with Your&amp;nbsp;Homelab&lt;/h2&gt;
&lt;h3&gt;Reverse Proxy and &lt;span class="caps"&gt;HTTPS&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Expose Immich via a reverse proxy with valid &lt;span class="caps"&gt;HTTPS&lt;/span&gt;. The mobile app requires &lt;span class="caps"&gt;HTTPS&lt;/span&gt; for background upload on&amp;nbsp;iOS.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.enable=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.immich.rule=Host(`photos.yourdomain.com`)&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.immich.tls.certresolver=letsencrypt&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.services.immich.loadbalancer.server.port=3001&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Backup&amp;nbsp;Strategy&lt;/h3&gt;
&lt;p&gt;Back up both the PostgreSQL database and the upload&amp;nbsp;directory:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Backup database&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;immich_postgres&lt;span class="w"&gt; &lt;/span&gt;pg_dump&lt;span class="w"&gt; &lt;/span&gt;-U&lt;span class="w"&gt; &lt;/span&gt;postgres&lt;span class="w"&gt; &lt;/span&gt;immich&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;immich-backup.sql

&lt;span class="c1"&gt;# Backup library&lt;/span&gt;
tar&lt;span class="w"&gt; &lt;/span&gt;czf&lt;span class="w"&gt; &lt;/span&gt;immich-library-backup.tar.gz&lt;span class="w"&gt; &lt;/span&gt;./library

&lt;span class="c1"&gt;# Or use a backup container&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;--rm&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;immich_postgres:/db:ro&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;./library:/library:ro&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;/backup:/backup&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;offen/docker-volume-backup
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Sync with&amp;nbsp;rclone&lt;/h3&gt;
&lt;p&gt;For a 3-2-1 backup strategy, sync the library to cloud storage (S3, B2, Google Drive) with&amp;nbsp;rclone:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;rclone&lt;span class="w"&gt; &lt;/span&gt;sync&lt;span class="w"&gt; &lt;/span&gt;./library&lt;span class="w"&gt; &lt;/span&gt;remote:immich-backup&lt;span class="w"&gt; &lt;/span&gt;--checksum&lt;span class="w"&gt; &lt;/span&gt;--verbose
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Alternatives to&amp;nbsp;Consider&lt;/h2&gt;
&lt;h3&gt;Nextcloud&amp;nbsp;Photos&lt;/h3&gt;
&lt;p&gt;Nextcloud has a Photos app and a Memories app (a more advanced fork). Nextcloud is better if you want a unified platform (files, documents, photos). Immich is better if you want a dedicated, &lt;span class="caps"&gt;AI&lt;/span&gt;-powered photo experience. See our &lt;a href="https://steadypub.com/2026/06/nextcloud-immich-comparison/"&gt;Nextcloud vs Immich comparison&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;PhotoPrism&lt;/h3&gt;
&lt;p&gt;PhotoPrism is another &lt;span class="caps"&gt;AI&lt;/span&gt;-powered photo manager with a focus on privacy and archiving. It has a stronger emphasis on geo-tagging and map-based browsing. The &lt;span class="caps"&gt;UI&lt;/span&gt; is more &amp;#8220;gallery-like&amp;#8221; than Immich&amp;#8217;s social feed style. PhotoPrism requires a commercial license for some features (high-resolution viewers, advanced &lt;span class="caps"&gt;AI&lt;/span&gt;).&lt;/p&gt;
&lt;h3&gt;LibrePhotos&lt;/h3&gt;
&lt;p&gt;LibrePhotos is an open-source photo manager with face recognition and auto-tagging. It is less polished than Immich but has a strong community. Good if you want a fully free alternative without the &amp;#8220;release model&amp;#8221;&amp;nbsp;complexity.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;AI&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Mobile App&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Immich&lt;/td&gt;
&lt;td&gt;Modern replacement for Google Photos&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nextcloud Photos&lt;/td&gt;
&lt;td&gt;Unified file+photo platform&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PhotoPrism&lt;/td&gt;
&lt;td&gt;Archival, geo-browsing&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Web app&lt;/td&gt;
&lt;td&gt;Free / Pro&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LibrePhotos&lt;/td&gt;
&lt;td&gt;Fully open, community-driven&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Frequently Asked&amp;nbsp;Questions&lt;/h2&gt;
&lt;h3&gt;How much storage does Immich&amp;nbsp;need?&lt;/h3&gt;
&lt;p&gt;Immich stores originals and generates thumbnails, encoded videos, and &lt;span class="caps"&gt;ML&lt;/span&gt; embeddings. Budget 2–3x the size of your raw library. A 100 &lt;span class="caps"&gt;GB&lt;/span&gt; photo library will consume 200–300 &lt;span class="caps"&gt;GB&lt;/span&gt; on&amp;nbsp;Immich.&lt;/p&gt;
&lt;h3&gt;Can I run Immich without a &lt;span class="caps"&gt;GPU&lt;/span&gt;?&lt;/h3&gt;
&lt;p&gt;Yes. The machine learning service falls back to &lt;span class="caps"&gt;CPU&lt;/span&gt;. Face recognition and object detection will be slower but functional. A modern &lt;span class="caps"&gt;CPU&lt;/span&gt; with &lt;span class="caps"&gt;AVX&lt;/span&gt; instructions is&amp;nbsp;sufficient.&lt;/p&gt;
&lt;h3&gt;Is Immich stable for long-term&amp;nbsp;use?&lt;/h3&gt;
&lt;p&gt;Immich is rapidly evolving. The core storage and &lt;span class="caps"&gt;API&lt;/span&gt; are stable, but the project occasionally introduces breaking changes. Always read the release notes before updating. Back up the database before major version&amp;nbsp;bumps.&lt;/p&gt;
&lt;h3&gt;How does Immich handle &lt;span class="caps"&gt;RAW&lt;/span&gt;&amp;nbsp;files?&lt;/h3&gt;
&lt;p&gt;Immich supports &lt;span class="caps"&gt;RAW&lt;/span&gt; formats (&lt;span class="caps"&gt;CR2&lt;/span&gt;, &lt;span class="caps"&gt;NEF&lt;/span&gt;, &lt;span class="caps"&gt;ARW&lt;/span&gt;, &lt;span class="caps"&gt;DNG&lt;/span&gt;). It generates &lt;span class="caps"&gt;JPEG&lt;/span&gt; thumbnails for web viewing and keeps the &lt;span class="caps"&gt;RAW&lt;/span&gt; for download. The mobile app can upload &lt;span class="caps"&gt;RAW&lt;/span&gt; files&amp;nbsp;directly.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Immich is the best self-hosted photo management solution available today. It combines the convenience of Google Photos — automatic backup, &lt;span class="caps"&gt;AI&lt;/span&gt; search, and a polished mobile app — with the privacy and control of self-hosting. With Docker, it deploys in minutes. With &lt;span class="caps"&gt;GPU&lt;/span&gt; acceleration, the &lt;span class="caps"&gt;AI&lt;/span&gt; features are fast and responsive. For anyone with a growing photo library, Immich is the logical next&amp;nbsp;step.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Install the mobile app and enable background&amp;nbsp;upload&lt;/li&gt;
&lt;li&gt;Import existing libraries via external library&amp;nbsp;paths&lt;/li&gt;
&lt;li&gt;Configure storage templates for date-based&amp;nbsp;organization&lt;/li&gt;
&lt;li&gt;Set up automated backups to offsite&amp;nbsp;storage&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;installation&lt;/strong&gt;: hardware — &lt;span class="caps"&gt;NAS&lt;/span&gt; devices, large hard drives, &lt;span class="caps"&gt;NVIDIA&lt;/span&gt;&amp;nbsp;GPUs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;integration&lt;/strong&gt;: tool — Authentik, Keycloak for&amp;nbsp;OAuth&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;alternatives&lt;/strong&gt;: tool — PhotoPrism commercial&amp;nbsp;license&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;installation&lt;/code&gt; → setup_guide: &lt;a href="https://steadypub.com/2026/06/docker-compose-for-beginners/"&gt;Docker Compose for&amp;nbsp;beginners&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;integration&lt;/code&gt; → related_guide: &lt;a href="https://steadypub.com/2026/06/nextcloud-immich-comparison/"&gt;Nextcloud vs Immich&amp;nbsp;comparison&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;alternatives&lt;/code&gt; → comparison: &lt;a href="https://steadypub.com/2026/06/immich-vs-google-photos/"&gt;Immich vs Google&amp;nbsp;Photos&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] How many photos are in your library? Are you migrating from Google Photos or&amp;nbsp;iCloud?&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for weekly self-hosted media and photo management&amp;nbsp;guides.&lt;/li&gt;
&lt;li&gt;[internal_link] Next: read our &lt;a href="https://steadypub.com/2026/06/nextcloud-immich-comparison/"&gt;Nextcloud vs Immich deep&amp;nbsp;comparison&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Tool Guides"/><category term="immich"/><category term="photos"/><category term="self-hosted"/><category term="homelab"/><category term="backup"/><category term="docker"/></entry><entry><title>Immich Reverse Proxy Setup: Nginx, Traefik, and Caddy Configs</title><link href="https://steadypub.com/2026/06/immich-reverse-proxy/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T10:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/immich-reverse-proxy/</id><summary type="html">&lt;p&gt;Complete reverse proxy configurations for Immich photo server. Production-ready Nginx, Traefik, and Caddy configs with &lt;span class="caps"&gt;SSL&lt;/span&gt;, rate limiting, and security&amp;nbsp;headers.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~12 minutes&lt;br&gt;
&lt;strong&gt;Audience:&lt;/strong&gt; Self-hosters running Immich behind a reverse&amp;nbsp;proxy&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why Immich Needs a Reverse&amp;nbsp;Proxy&lt;/h2&gt;
&lt;p&gt;Immich runs on port 2283 by default. A reverse proxy&amp;nbsp;provides:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;SSL&lt;/span&gt; termination&lt;/strong&gt; (&lt;span class="caps"&gt;HTTPS&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Domain-based routing&lt;/strong&gt;&amp;nbsp;(photos.mydomain.com)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rate limiting&lt;/strong&gt; (protect&amp;nbsp;uploads)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security headers&lt;/strong&gt; (&lt;span class="caps"&gt;HSTS&lt;/span&gt;, &lt;span class="caps"&gt;CSP&lt;/span&gt;,&amp;nbsp;X-Frame-Options)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Load balancing&lt;/strong&gt; (if running multiple&amp;nbsp;instances)&lt;/li&gt;
&lt;/ul&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Without Proxy&lt;/th&gt;
&lt;th&gt;With Proxy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;HTTPS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Manual cert management&lt;/td&gt;
&lt;td&gt;Automatic (Let&amp;#8217;s Encrypt)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Domain&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;IP&lt;/span&gt;:2283&lt;/td&gt;
&lt;td&gt;photos.mydomain.com&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rate limiting&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Configurable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security headers&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Full &lt;span class="caps"&gt;HSTS&lt;/span&gt;/&lt;span class="caps"&gt;CSP&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Path-based routing&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;/api, /share, etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Option 1: Nginx Reverse&amp;nbsp;Proxy&lt;/h2&gt;
&lt;h3&gt;Nginx Config (&lt;span class="caps"&gt;HTTP&lt;/span&gt; → &lt;span class="caps"&gt;HTTPS&lt;/span&gt;&amp;nbsp;redirect)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;listen&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;server_name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;photos.mydomain.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;301&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;https://&lt;/span&gt;&lt;span class="nv"&gt;$server_name$request_uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;listen&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;443&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;http2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;server_name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;photos.mydomain.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# SSL certificates (Let&amp;#39;s Encrypt via certbot)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;ssl_certificate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/etc/letsencrypt/live/mydomain.com/fullchain.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;ssl_certificate_key&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/etc/letsencrypt/live/mydomain.com/privkey.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;ssl_protocols&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;TLSv1.2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;TLSv1.3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;ssl_ciphers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;ssl_prefer_server_ciphers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Security headers&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;add_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;X-Frame-Options&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;SAMEORIGIN&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;add_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;X-Content-Type-Options&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;nosniff&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;add_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;X-XSS-Protection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;mode=block&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;add_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;Referrer-Policy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;strict-origin-when-cross-origin&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;add_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;Permissions-Policy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;geolocation=(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;microphone=(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;camera=()&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Rate limiting&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;limit_req_zone&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$binary_remote_addr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;zone=immich:10m&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;rate=10r/s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;limit_req&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;zone=immich&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;burst=20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;nodelay&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Client max body size for uploads&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;client_max_body_size&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;50000M&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;location&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kn"&gt;proxy_pass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;http://immich-server:2283&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kn"&gt;proxy_set_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kn"&gt;proxy_set_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;X-Real-IP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kn"&gt;proxy_set_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kn"&gt;proxy_set_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;X-Forwarded-Proto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$scheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kn"&gt;proxy_set_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;Upgrade&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$http_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kn"&gt;proxy_set_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;Connection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;upgrade&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kn"&gt;proxy_read_timeout&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;600s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kn"&gt;proxy_send_timeout&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;600s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Docker Compose (Nginx +&amp;nbsp;Immich)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;immich-server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ghcr.io/immich-app/immich-server:release&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;immich_server&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;${UPLOAD_LOCATION}:/usr/src/app/upload&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;env_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;.env&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;2283:3001&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;immich-machine-learning&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ghcr.io/immich-app/immich-machine-learning:release&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;immich_machine_learning&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;model-cache:/cache&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;env_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;.env&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;nginx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nginx:alpine&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;immich_nginx&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;80:80&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;443:443&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./nginx.conf:/etc/nginx/conf.d/default.conf:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/etc/letsencrypt:/etc/letsencrypt:ro&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;immich-server&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis:6-alpine&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;immich_redis&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;database&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;postgres:14-alpine&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;immich_postgres&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;env_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;.env&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pgdata:/var/lib/postgresql/data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;model-cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;pgdata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Option 2: Traefik&amp;nbsp;(Docker-native)&lt;/h2&gt;
&lt;h3&gt;Traefik Docker&amp;nbsp;Compose&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;traefik&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;traefik:v2.10&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;traefik&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--api.insecure=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--providers.docker=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--providers.docker.exposedbydefault=false&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--entrypoints.web.address=:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--entrypoints.websecure.address=:443&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--certificatesresolvers.letsencrypt.acme.tlschallenge=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--certificatesresolvers.letsencrypt.acme.email=admin@mydomain.com&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--entrypoints.web.http.redirections.entryPoint.to=websecure&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--entrypoints.web.http.redirections.entryPoint.scheme=https&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;80:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;443:443&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8080:8080&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/var/run/docker.sock:/var/run/docker.sock:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./letsencrypt:/letsencrypt&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;immich-server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ghcr.io/immich-app/immich-server:release&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;immich_server&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.enable=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.immich.rule=Host(`photos.mydomain.com`)&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.immich.entrypoints=websecure&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.immich.tls.certresolver=letsencrypt&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.services.immich.loadbalancer.server.port=3001&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.middlewares.immich-headers.headers.customFrameOptionsValue=SAMEORIGIN&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.middlewares.immich-headers.headers.contentTypeNosniff=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.immich.middlewares=immich-headers&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;${UPLOAD_LOCATION}:/usr/src/app/upload&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;env_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;.env&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;immich-machine-learning&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ghcr.io/immich-app/immich-machine-learning:release&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;immich_machine_learning&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;model-cache:/cache&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;env_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;.env&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis:6-alpine&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;immich_redis&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;database&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;postgres:14-alpine&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;immich_postgres&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;env_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;.env&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pgdata:/var/lib/postgresql/data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;model-cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;pgdata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Traefik Middleware for Rate&amp;nbsp;Limiting&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.middlewares.immich-ratelimit.ratelimit.average=100&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.middlewares.immich-ratelimit.ratelimit.burst=200&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.immich.middlewares=immich-headers,immich-ratelimit&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Option 3: Caddy (Simplest&amp;nbsp;Config)&lt;/h2&gt;
&lt;h3&gt;Caddyfile&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;photos&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mydomain&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;reverse_proxy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;immich&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3001&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;header_up&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;header_up&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Real&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;IP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;header_up&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Forwarded&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;For&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;header_up&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Forwarded&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Proto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;scheme&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;tls&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;mydomain&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Security headers&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Frame&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Options&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;SAMEORIGIN&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Content&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Options&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;nosniff&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;XSS&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Protection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;1; mode=block&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;Referrer&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Policy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;strict-origin-when-cross-origin&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;Permissions&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Policy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;geolocation=(), microphone=(), camera=()&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Rate limiting (requires caddy-ratelimit plugin)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;rate_limit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;zone&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Upload size&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;request_body&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;max_size&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="n"&gt;GB&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Docker Compose&amp;nbsp;(Caddy)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;caddy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;caddy:2-alpine&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;caddy&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;80:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;443:443&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./Caddyfile:/etc/caddy/Caddyfile:ro&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;caddy_data:/data&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;caddy_config:/config&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;immich-server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ghcr.io/immich-app/immich-server:release&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;immich_server&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;${UPLOAD_LOCATION}:/usr/src/app/upload&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;env_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;.env&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# ... (redis, postgres, ML same as above)&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;caddy_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;caddy_config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Performance&amp;nbsp;Tuning&lt;/h2&gt;
&lt;h3&gt;Nginx Buffer&amp;nbsp;Sizes&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;proxy_buffer_size&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;128k&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;proxy_buffers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;256k&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;proxy_busy_buffers_size&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;256k&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;proxy_temp_file_write_size&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;256k&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Immich .env for Large&amp;nbsp;Libraries&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# .env&lt;/span&gt;
&lt;span class="nv"&gt;UPLOAD_LOCATION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/mnt/photos
&lt;span class="nv"&gt;DB_HOSTNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;immich_postgres
&lt;span class="nv"&gt;DB_USERNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;immich
&lt;span class="nv"&gt;DB_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-secure-password
&lt;span class="nv"&gt;DB_DATABASE_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;immich
&lt;span class="nv"&gt;REDIS_HOSTNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;immich_redis

&lt;span class="c1"&gt;# Increase for large libraries&lt;/span&gt;
&lt;span class="nv"&gt;MACHINE_LEARNING_WORKERS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
&lt;span class="nv"&gt;MACHINE_LEARNING_WORKER_TIMEOUT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;120&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Common&amp;nbsp;Mistakes&lt;/h2&gt;
&lt;h3&gt;Mistake 1: Missing WebSocket&amp;nbsp;Support&lt;/h3&gt;
&lt;p&gt;Immich uses WebSockets for live updates. Ensure your proxy&amp;nbsp;passes &lt;code&gt;Upgrade&lt;/code&gt; and &lt;code&gt;Connection&lt;/code&gt; headers.&lt;/p&gt;
&lt;h3&gt;Mistake 2: Too&amp;nbsp;Small &lt;code&gt;client_max_body_size&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Default Nginx limit is &lt;span class="caps"&gt;1MB&lt;/span&gt;. Immich uploads need &lt;span class="caps"&gt;50GB&lt;/span&gt;+ for video.&amp;nbsp;Set:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;client_max_body_size&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;50000M&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Mistake 3:&amp;nbsp;Forgetting &lt;code&gt;X-Forwarded-Proto&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Immich needs this header to generate correct URLs. All configs above include&amp;nbsp;it.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Any reverse proxy works with Immich. &lt;strong&gt;Caddy&lt;/strong&gt; is simplest for beginners, &lt;strong&gt;Traefik&lt;/strong&gt; is best for Docker-native stacks, and &lt;strong&gt;Nginx&lt;/strong&gt; offers maximum control for advanced&amp;nbsp;users.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Choose your proxy (Caddy for speed, Nginx for&amp;nbsp;control)&lt;/li&gt;
&lt;li&gt;Set &lt;span class="caps"&gt;DNS&lt;/span&gt; A record to your server &lt;span class="caps"&gt;IP&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Deploy the Docker Compose&amp;nbsp;stack&lt;/li&gt;
&lt;li&gt;Test&amp;nbsp;with &lt;code&gt;curl -I https://photos.mydomain.com&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Domain registrars:&lt;/strong&gt; Namecheap, Cloudflare&amp;nbsp;Registrar&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt;/cloud:&lt;/strong&gt; Hetzner, DigitalOcean,&amp;nbsp;Linode&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hardware:&lt;/strong&gt; Mini PCs for home hosting (Minisforum,&amp;nbsp;Beelink)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Storage:&lt;/strong&gt; &lt;span class="caps"&gt;NAS&lt;/span&gt; drives, &lt;span class="caps"&gt;USB&lt;/span&gt;&amp;nbsp;enclosures&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal&amp;nbsp;Linking&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;immich-setup&lt;/code&gt; → &lt;code&gt;immich-photo-server.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker-compose&lt;/code&gt; → &lt;code&gt;docker-compose-yml-examples.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;traefik&lt;/code&gt; → &lt;code&gt;traefik-docker-setup.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ssl&lt;/code&gt; → &lt;code&gt;lets-encrypt-homelab.md&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Which reverse proxy do you use?&lt;/strong&gt; Nginx, Traefik, or Caddy? Vote in the&amp;nbsp;comments.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subscribe&lt;/strong&gt; for more self-hosted app deployment&amp;nbsp;guides.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Guides"/><category term="immich reverse proxy"/><category term="immich docker"/><category term="traefik nginx caddy"/><category term="self-hosted photos"/><category term="homelab"/></entry><entry><title>Best Managed Switch for Homelab in 2026: Reviews, Specs, and Buying Guide</title><link href="https://steadypub.com/2026/06/managed-switch-homelab/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T06:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/managed-switch-homelab/</id><summary type="html">&lt;p&gt;The best managed switches for homelabs in 2026, from 1 GbE to 10 GbE &lt;span class="caps"&gt;SFP&lt;/span&gt;+. Real specs, noise levels, power draw, and &lt;span class="caps"&gt;VLAN&lt;/span&gt;&amp;nbsp;configuration.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~14 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelabbers upgrading their network&amp;nbsp;backbone&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why a Managed Switch Matters for Your&amp;nbsp;Homelab&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;A managed switch is the central nervous system of a homelab. Unlike unmanaged switches, which blindly forward packets, managed switches give you VLANs, link aggregation, QoS, &lt;span class="caps"&gt;SNMP&lt;/span&gt; monitoring, and port mirroring. These features are not luxuries—they are essential for security, performance, and&amp;nbsp;observability.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What you can do with a managed switch:&lt;/strong&gt;
- &lt;strong&gt;VLANs:&lt;/strong&gt; Isolate IoT devices, guest networks, and management interfaces
- &lt;strong&gt;Link aggregation (&lt;span class="caps"&gt;LACP&lt;/span&gt;):&lt;/strong&gt; Combine 2–4 ports into a single 2–4 Gbps pipe to a &lt;span class="caps"&gt;NAS&lt;/span&gt; or server
- &lt;strong&gt;QoS:&lt;/strong&gt; Prioritize VoIP, gaming, or video traffic over bulk transfers
- &lt;strong&gt;&lt;span class="caps"&gt;SNMP&lt;/span&gt;:&lt;/strong&gt; Feed traffic graphs to Grafana/Prometheus
- &lt;strong&gt;Port mirroring:&lt;/strong&gt; Capture packets for Wireshark analysis
- &lt;strong&gt;PoE:&lt;/strong&gt; Power access points, cameras, and phones without wall&amp;nbsp;adapters&lt;/p&gt;
&lt;p&gt;In 2026, 2.5 GbE and 10 GbE are mainstream. A 1 GbE link to a &lt;span class="caps"&gt;NAS&lt;/span&gt; running &lt;span class="caps"&gt;ZFS&lt;/span&gt; with SSDs is a bottleneck. 10 GbE over &lt;span class="caps"&gt;SFP&lt;/span&gt;+ or Base-T is the new standard for serious&amp;nbsp;homelabs.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Evaluation&amp;nbsp;Criteria&lt;/h2&gt;
&lt;h3&gt;Price-to-Performance&lt;/h3&gt;
&lt;p&gt;Homelab switches range from $50 used enterprise gear to $400 new prosumer units. The sweet spot is $100–$200 for a 24-port 1 GbE + 2–4 &lt;span class="caps"&gt;SFP&lt;/span&gt;+ switch, or $250–$400 for a 16-port 2.5 GbE + 2 &lt;span class="caps"&gt;SFP&lt;/span&gt;+&amp;nbsp;switch.&lt;/p&gt;
&lt;h3&gt;Feature&amp;nbsp;Set&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Must-Have&lt;/th&gt;
&lt;th&gt;Nice-to-Have&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;VLANs&lt;/td&gt;
&lt;td&gt;Yes (802.1Q)&lt;/td&gt;
&lt;td&gt;Dynamic VLANs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;LACP&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;MLAG&lt;/span&gt; (for dual-switch setups)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PoE&lt;/td&gt;
&lt;td&gt;Yes (if you have APs/cameras)&lt;/td&gt;
&lt;td&gt;PoE+ (802.3at, 30W/port)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10 GbE &lt;span class="caps"&gt;SFP&lt;/span&gt;+&lt;/td&gt;
&lt;td&gt;Yes (for &lt;span class="caps"&gt;NAS&lt;/span&gt;/server)&lt;/td&gt;
&lt;td&gt;25 GbE &lt;span class="caps"&gt;SFP28&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;CLI&lt;/span&gt; + Web &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;REST&lt;/span&gt; &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;SNMP&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;sFlow/NetFlow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Noise level&lt;/td&gt;
&lt;td&gt;&amp;lt;40 dB(A) for home use&lt;/td&gt;
&lt;td&gt;Fanless&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Power draw&lt;/td&gt;
&lt;td&gt;&amp;lt;30 W idle&lt;/td&gt;
&lt;td&gt;80+ efficient &lt;span class="caps"&gt;PSU&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Community &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;Support&lt;/h3&gt;
&lt;p&gt;Enterprise switches (Cisco, &lt;span class="caps"&gt;HPE&lt;/span&gt;) have steep learning curves and expensive support contracts. Prosumer brands (MikroTik, Ubiquiti, &lt;span class="caps"&gt;TP&lt;/span&gt;-Link Omada) have active Reddit communities and YouTube tutorials. Used enterprise switches are cheap but may require firmware updates via proprietary&amp;nbsp;tools.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;#1: &lt;span class="caps"&gt;TP&lt;/span&gt;-Link &lt;span class="caps"&gt;TL&lt;/span&gt;-&lt;span class="caps"&gt;SG3428XMP&lt;/span&gt; (24x 1GbE + 4x &lt;span class="caps"&gt;SFP&lt;/span&gt;+,&amp;nbsp;PoE+)&lt;/h2&gt;
&lt;h3&gt;Why It Tops Our&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;The &lt;span class="caps"&gt;TL&lt;/span&gt;-&lt;span class="caps"&gt;SG3428XMP&lt;/span&gt; is the best all-around managed switch for homelabs in 2026. It offers 24 PoE+ ports (30 W each), 4 &lt;span class="caps"&gt;SFP&lt;/span&gt;+ 10 GbE uplinks, and a full Omada &lt;span class="caps"&gt;SDN&lt;/span&gt; integration. It is fanless, silent, and runs on a standard power cord. No rack ears needed—it sits on a&amp;nbsp;desk.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ports&lt;/td&gt;
&lt;td&gt;24x 1 GbE &lt;span class="caps"&gt;RJ45&lt;/span&gt; (PoE+) + 4x &lt;span class="caps"&gt;SFP&lt;/span&gt;+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PoE Budget&lt;/td&gt;
&lt;td&gt;384 W total&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Switching Capacity&lt;/td&gt;
&lt;td&gt;128 Gbps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;MAC&lt;/span&gt; Address Table&lt;/td&gt;
&lt;td&gt;16K&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VLANs&lt;/td&gt;
&lt;td&gt;4K&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Jumbo Frames&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;9KB&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Management&lt;/td&gt;
&lt;td&gt;Web &lt;span class="caps"&gt;UI&lt;/span&gt;, Omada Cloud, &lt;span class="caps"&gt;SNMP&lt;/span&gt;, &lt;span class="caps"&gt;CLI&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Noise&lt;/td&gt;
&lt;td&gt;Fanless (0 dB)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Power Draw&lt;/td&gt;
&lt;td&gt;25–40 W (no PoE load)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dimensions&lt;/td&gt;
&lt;td&gt;440 × 330 × 44 mm (1U)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Price&lt;/td&gt;
&lt;td&gt;~$350–$400&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Fanless:&lt;/strong&gt; Silent operation. The only silent switch with 4x &lt;span class="caps"&gt;SFP&lt;/span&gt;+ and&amp;nbsp;PoE+.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Omada &lt;span class="caps"&gt;SDN&lt;/span&gt;:&lt;/strong&gt; Integrates with Omada controllers, access points, and gateways. One-click &lt;span class="caps"&gt;VLAN&lt;/span&gt;&amp;nbsp;propagation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PoE+ budget:&lt;/strong&gt; 384 W is enough for 8–12 high-power APs or&amp;nbsp;cameras.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;10 GbE uplinks:&lt;/strong&gt; Connect your &lt;span class="caps"&gt;NAS&lt;/span&gt; and Proxmox server at full speed without a separate 10 GbE&amp;nbsp;switch.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No 2.5 GbE ports:&lt;/strong&gt; 1 GbE or 10 GbE only. 2.5 GbE devices fall back to 1&amp;nbsp;GbE.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Web &lt;span class="caps"&gt;UI&lt;/span&gt; is basic:&lt;/strong&gt; Advanced features require Omada Controller or &lt;span class="caps"&gt;CLI&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Price:&lt;/strong&gt; At ~$400, it is not a budget&amp;nbsp;switch.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Homelabs with PoE APs and&amp;nbsp;cameras&lt;/li&gt;
&lt;li&gt;Users who want silent&amp;nbsp;operation&lt;/li&gt;
&lt;li&gt;Omada ecosystem&amp;nbsp;users&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;p&gt;$350–$400 (Amazon, Newegg). &lt;span class="caps"&gt;TP&lt;/span&gt;-Link occasionally offers&amp;nbsp;rebates.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;#2: MikroTik &lt;span class="caps"&gt;CRS326&lt;/span&gt;-24G-2S+&lt;span class="caps"&gt;RM&lt;/span&gt; (24x 1GbE + 2x &lt;span class="caps"&gt;SFP&lt;/span&gt;+)&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;MikroTik is the brand of choice for homelabbers who want maximum features at minimum price. The &lt;span class="caps"&gt;CRS326&lt;/span&gt; is a 24-port 1 GbE switch with 2 &lt;span class="caps"&gt;SFP&lt;/span&gt;+ ports, running RouterOS or SwOS. It costs half the &lt;span class="caps"&gt;TP&lt;/span&gt;-Link but requires more&amp;nbsp;configuration.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ports&lt;/td&gt;
&lt;td&gt;24x 1 GbE &lt;span class="caps"&gt;RJ45&lt;/span&gt; + 2x &lt;span class="caps"&gt;SFP&lt;/span&gt;+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Switching Capacity&lt;/td&gt;
&lt;td&gt;64 Gbps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VLANs&lt;/td&gt;
&lt;td&gt;4K&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Jumbo Frames&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;9KB&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Management&lt;/td&gt;
&lt;td&gt;Web &lt;span class="caps"&gt;UI&lt;/span&gt; (SwOS), RouterOS, Winbox, &lt;span class="caps"&gt;SSH&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Noise&lt;/td&gt;
&lt;td&gt;Quiet fans (~30 dB)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Power Draw&lt;/td&gt;
&lt;td&gt;15–25 W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dimensions&lt;/td&gt;
&lt;td&gt;443 × 142 × 44 mm (1U)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Price&lt;/td&gt;
&lt;td&gt;~$150–$180&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Price:&lt;/strong&gt; The cheapest managed switch with &lt;span class="caps"&gt;SFP&lt;/span&gt;+&amp;nbsp;uplinks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RouterOS:&lt;/strong&gt; Advanced routing, firewall, and &lt;span class="caps"&gt;VPN&lt;/span&gt; features. This is a switch that can also be a&amp;nbsp;router.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dual-boot:&lt;/strong&gt; SwOS for simple switching; RouterOS for Layer 3&amp;nbsp;features.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;SFP&lt;/span&gt;+ flexibility:&lt;/strong&gt; Use &lt;span class="caps"&gt;DAC&lt;/span&gt; cables, fiber, or 10GBase-T&amp;nbsp;modules.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Learning curve:&lt;/strong&gt; RouterOS is powerful but not beginner-friendly. The Web &lt;span class="caps"&gt;UI&lt;/span&gt; is&amp;nbsp;utilitarian.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No PoE:&lt;/strong&gt; Need a separate injector or switch for PoE&amp;nbsp;devices.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Support:&lt;/strong&gt; Community-driven. MikroTik support is slow for individual&amp;nbsp;buyers.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Budget-conscious&amp;nbsp;homelabbers&lt;/li&gt;
&lt;li&gt;Users who want to learn advanced&amp;nbsp;networking&lt;/li&gt;
&lt;li&gt;RouterOS&amp;nbsp;enthusiasts&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;p&gt;$150–$180 (Amazon, MikroTik&amp;nbsp;distributors).&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;#3: Ubiquiti UniFi Switch Pro 24 (24x 1GbE + 2x &lt;span class="caps"&gt;SFP&lt;/span&gt;+)&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;Ubiquiti&amp;#8217;s UniFi ecosystem is the Apple of networking: polished, integrated, and expensive. The Switch Pro 24 is a Layer 3 switch with a full UniFi Controller integration. If you already run UniFi APs and a UniFi gateway, this is the logical&amp;nbsp;switch.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ports&lt;/td&gt;
&lt;td&gt;24x 1 GbE &lt;span class="caps"&gt;RJ45&lt;/span&gt; + 2x &lt;span class="caps"&gt;SFP&lt;/span&gt;+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Switching Capacity&lt;/td&gt;
&lt;td&gt;128 Gbps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VLANs&lt;/td&gt;
&lt;td&gt;4K&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;L3 Features&lt;/td&gt;
&lt;td&gt;Static routing, inter-&lt;span class="caps"&gt;VLAN&lt;/span&gt; routing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Management&lt;/td&gt;
&lt;td&gt;UniFi Controller (required)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Noise&lt;/td&gt;
&lt;td&gt;Fans, ~35 dB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Power Draw&lt;/td&gt;
&lt;td&gt;30–45 W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dimensions&lt;/td&gt;
&lt;td&gt;442 × 285 × 43 mm (1U)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Price&lt;/td&gt;
&lt;td&gt;~$400–$450&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;UniFi integration:&lt;/strong&gt; One controller manages APs, switches, and gateways. VLANs propagate&amp;nbsp;automatically.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Layer 3:&lt;/strong&gt; Inter-&lt;span class="caps"&gt;VLAN&lt;/span&gt; routing at wire speed without a&amp;nbsp;router-on-a-stick.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Build quality:&lt;/strong&gt; Metal chassis, excellent fit and&amp;nbsp;finish.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Active community:&lt;/strong&gt; r/Ubiquiti is massive; every issue has a&amp;nbsp;workaround.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Controller dependency:&lt;/strong&gt; You must run a UniFi Controller (software or Cloud Key) to manage the&amp;nbsp;switch.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Price:&lt;/strong&gt; 2–3x the MikroTik for similar port&amp;nbsp;counts.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Proprietary:&lt;/strong&gt; Limited &lt;span class="caps"&gt;CLI&lt;/span&gt; access; you are locked into the UniFi&amp;nbsp;ecosystem.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Existing UniFi&amp;nbsp;users&lt;/li&gt;
&lt;li&gt;Users who value &lt;span class="caps"&gt;UI&lt;/span&gt; polish over&amp;nbsp;price&lt;/li&gt;
&lt;li&gt;Small offices that need L3&amp;nbsp;switching&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;p&gt;$400–$450 (Ubiquiti Store, Amazon). Often out of&amp;nbsp;stock.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;#4: MikroTik &lt;span class="caps"&gt;CRS309&lt;/span&gt;-1G-8S+&lt;span class="caps"&gt;IN&lt;/span&gt; (8x &lt;span class="caps"&gt;SFP&lt;/span&gt;+)&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;If your homelab has moved to 10 GbE and you need a dedicated &lt;span class="caps"&gt;SFP&lt;/span&gt;+ switch, the &lt;span class="caps"&gt;CRS309&lt;/span&gt; is unbeatable. 8 &lt;span class="caps"&gt;SFP&lt;/span&gt;+ ports, 1 GbE management, and fanless operation for&amp;nbsp;~$250.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ports&lt;/td&gt;
&lt;td&gt;8x &lt;span class="caps"&gt;SFP&lt;/span&gt;+ + 1x 1 GbE &lt;span class="caps"&gt;RJ45&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Switching Capacity&lt;/td&gt;
&lt;td&gt;160 Gbps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VLANs&lt;/td&gt;
&lt;td&gt;4K&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Management&lt;/td&gt;
&lt;td&gt;SwOS, Web &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Noise&lt;/td&gt;
&lt;td&gt;Fanless (0 dB)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Power Draw&lt;/td&gt;
&lt;td&gt;15–20 W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dimensions&lt;/td&gt;
&lt;td&gt;270 × 135 × 34 mm&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Price&lt;/td&gt;
&lt;td&gt;~$250–$280&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Fanless 10 GbE:&lt;/strong&gt; The only affordable fanless 8-port &lt;span class="caps"&gt;SFP&lt;/span&gt;+&amp;nbsp;switch.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Compact:&lt;/strong&gt; Not a full 1U rackmount. Sits on a shelf or&amp;nbsp;desk.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;SFP&lt;/span&gt;+ variety:&lt;/strong&gt; Mix fiber, &lt;span class="caps"&gt;DAC&lt;/span&gt;, and 10GBase-T modules&amp;nbsp;freely.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No &lt;span class="caps"&gt;RJ45&lt;/span&gt; ports:&lt;/strong&gt; You need &lt;span class="caps"&gt;SFP&lt;/span&gt;+ transceivers for everything. A 10GBase-T module is&amp;nbsp;~$50.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SwOS only:&lt;/strong&gt; No RouterOS. Layer 2 switching&amp;nbsp;only.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Dedicated 10 GbE&amp;nbsp;backbones&lt;/li&gt;
&lt;li&gt;Users with fiber runs between&amp;nbsp;rooms&lt;/li&gt;
&lt;li&gt;Noise-sensitive&amp;nbsp;setups&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;p&gt;$250–$280 (Amazon, MikroTik&amp;nbsp;distributors).&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;#5: Netgear &lt;span class="caps"&gt;MS510TXM&lt;/span&gt; (8x 1/2.5/5/10GbE + 1x &lt;span class="caps"&gt;SFP&lt;/span&gt;+)&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;The Netgear &lt;span class="caps"&gt;MS510TXM&lt;/span&gt; is the best &amp;#8220;future-proof&amp;#8221; 10 GbE Base-T switch. It has 8 multi-gig ports (1/2.5/5/10 GbE) and 1 &lt;span class="caps"&gt;SFP&lt;/span&gt;+ uplink. If you have modern &lt;span class="caps"&gt;NAS&lt;/span&gt; devices, workstations, or mini PCs with 2.5 GbE, this switch auto-negotiates the best&amp;nbsp;speed.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ports&lt;/td&gt;
&lt;td&gt;8x 1/2.5/5/10 GbE &lt;span class="caps"&gt;RJ45&lt;/span&gt; + 1x &lt;span class="caps"&gt;SFP&lt;/span&gt;+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Switching Capacity&lt;/td&gt;
&lt;td&gt;178 Gbps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VLANs&lt;/td&gt;
&lt;td&gt;256&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Management&lt;/td&gt;
&lt;td&gt;Web &lt;span class="caps"&gt;UI&lt;/span&gt;, &lt;span class="caps"&gt;SNMP&lt;/span&gt;, &lt;span class="caps"&gt;NETGEAR&lt;/span&gt; Insight&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Noise&lt;/td&gt;
&lt;td&gt;Fanless (0 dB)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Power Draw&lt;/td&gt;
&lt;td&gt;25–35 W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dimensions&lt;/td&gt;
&lt;td&gt;328 × 169 × 43 mm&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Price&lt;/td&gt;
&lt;td&gt;~$350–$400&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Multi-gig:&lt;/strong&gt; 2.5 GbE and 5 GbE without buying new&amp;nbsp;cables.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fanless:&lt;/strong&gt; Silent for home&amp;nbsp;use.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Insight cloud:&lt;/strong&gt; Optional cloud management for remote&amp;nbsp;monitoring.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Only 8 ports:&lt;/strong&gt; Small for a full rack&amp;nbsp;lab.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Price per port:&lt;/strong&gt; High compared to &lt;span class="caps"&gt;SFP&lt;/span&gt;+&amp;nbsp;alternatives.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Limited VLANs:&lt;/strong&gt; 256 VLANs is fine for homelabs but restrictive for&amp;nbsp;enterprise.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Workstation-heavy&amp;nbsp;labs&lt;/li&gt;
&lt;li&gt;Users with 2.5 GbE mini PCs and &lt;span class="caps"&gt;NAS&lt;/span&gt;&amp;nbsp;devices&lt;/li&gt;
&lt;li&gt;Quiet&amp;nbsp;environments&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;p&gt;$350–$400 (Amazon,&amp;nbsp;B&amp;amp;H).&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Quick Comparison&amp;nbsp;Table&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Switch&lt;/th&gt;
&lt;th&gt;Ports&lt;/th&gt;
&lt;th&gt;10GbE&lt;/th&gt;
&lt;th&gt;PoE&lt;/th&gt;
&lt;th&gt;Fanless&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;TP&lt;/span&gt;-Link &lt;span class="caps"&gt;TL&lt;/span&gt;-&lt;span class="caps"&gt;SG3428XMP&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;24x 1G + 4x &lt;span class="caps"&gt;SFP&lt;/span&gt;+&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;SFP&lt;/span&gt;+&lt;/td&gt;
&lt;td&gt;384W PoE+&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;$400&lt;/td&gt;
&lt;td&gt;PoE + silent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MikroTik &lt;span class="caps"&gt;CRS326&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;24x 1G + 2x &lt;span class="caps"&gt;SFP&lt;/span&gt;+&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;SFP&lt;/span&gt;+&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;$170&lt;/td&gt;
&lt;td&gt;Budget&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UniFi Switch Pro 24&lt;/td&gt;
&lt;td&gt;24x 1G + 2x &lt;span class="caps"&gt;SFP&lt;/span&gt;+&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;SFP&lt;/span&gt;+&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;$430&lt;/td&gt;
&lt;td&gt;UniFi ecosystem&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MikroTik &lt;span class="caps"&gt;CRS309&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;8x &lt;span class="caps"&gt;SFP&lt;/span&gt;+&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;SFP&lt;/span&gt;+&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;$270&lt;/td&gt;
&lt;td&gt;Pure 10GbE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Netgear &lt;span class="caps"&gt;MS510TXM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;8x Multi-Gig + 1x &lt;span class="caps"&gt;SFP&lt;/span&gt;+&lt;/td&gt;
&lt;td&gt;Base-T&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;$380&lt;/td&gt;
&lt;td&gt;2.5/5/10GbE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Use &lt;span class="caps"&gt;DAC&lt;/span&gt; Cables for 10&amp;nbsp;GbE&lt;/h3&gt;
&lt;p&gt;Direct Attach Copper (&lt;span class="caps"&gt;DAC&lt;/span&gt;) cables are passive twinax cables with &lt;span class="caps"&gt;SFP&lt;/span&gt;+ connectors on both ends. They are cheaper, lower power, and lower latency than fiber transceivers. A 1-meter &lt;span class="caps"&gt;DAC&lt;/span&gt; is $15–$20. A 3-meter is $25. Use &lt;span class="caps"&gt;DAC&lt;/span&gt; for switch-to-switch and switch-to-server connections within the same&amp;nbsp;rack.&lt;/p&gt;
&lt;h3&gt;Tip 2: VLANs Are&amp;nbsp;Non-Negotiable&lt;/h3&gt;
&lt;p&gt;Every homelab should use VLANs. At minimum:
- &lt;strong&gt;&lt;span class="caps"&gt;VLAN&lt;/span&gt; 10:&lt;/strong&gt; Management (Proxmox, switches, &lt;span class="caps"&gt;IPMI&lt;/span&gt;)
- &lt;strong&gt;&lt;span class="caps"&gt;VLAN&lt;/span&gt; 20:&lt;/strong&gt; Trusted (personal devices, workstations)
- &lt;strong&gt;&lt;span class="caps"&gt;VLAN&lt;/span&gt; 30:&lt;/strong&gt; IoT (smart bulbs, cameras, TVs)
- &lt;strong&gt;&lt;span class="caps"&gt;VLAN&lt;/span&gt; 40:&lt;/strong&gt; Guest (isolated&amp;nbsp;internet-only)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# MikroTik SwOS VLAN config example&lt;/span&gt;
/interface&lt;span class="w"&gt; &lt;/span&gt;bridge
add&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;bridge1
/interface&lt;span class="w"&gt; &lt;/span&gt;bridge&lt;span class="w"&gt; &lt;/span&gt;port
add&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;bridge&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;bridge1&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;interface&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ether1
/interface&lt;span class="w"&gt; &lt;/span&gt;vlan
add&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;interface&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;bridge1&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;vlan10&lt;span class="w"&gt; &lt;/span&gt;vlan-id&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;
add&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;interface&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;bridge1&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;vlan20&lt;span class="w"&gt; &lt;/span&gt;vlan-id&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;20&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 3: Monitor Switch&amp;nbsp;Temperature&lt;/h3&gt;
&lt;p&gt;Switches can overheat in enclosed racks. Use &lt;span class="caps"&gt;SNMP&lt;/span&gt; to monitor temperature and trigger&amp;nbsp;alerts:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# snmpwalk for temperature (OIDs vary by vendor)&lt;/span&gt;
snmpwalk&lt;span class="w"&gt; &lt;/span&gt;-v2c&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;public&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.1.10&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.3.6.1.4.1.9.9.13.1.3.1.3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;The best managed switch for your homelab depends on your port needs, noise tolerance, and ecosystem. The &lt;span class="caps"&gt;TP&lt;/span&gt;-Link &lt;span class="caps"&gt;TL&lt;/span&gt;-&lt;span class="caps"&gt;SG3428XMP&lt;/span&gt; is the best all-rounder for PoE users. The MikroTik &lt;span class="caps"&gt;CRS326&lt;/span&gt; is unbeatable on price. The MikroTik &lt;span class="caps"&gt;CRS309&lt;/span&gt; is the king of fanless 10 GbE. For 2.5/5/10 GbE Base-T, the Netgear &lt;span class="caps"&gt;MS510TXM&lt;/span&gt; is the safe&amp;nbsp;choice.&lt;/p&gt;
&lt;h3&gt;Our&amp;nbsp;Recommendation&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Budget&lt;/th&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Recommendation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;$150&lt;/td&gt;
&lt;td&gt;Tight budget, no PoE&lt;/td&gt;
&lt;td&gt;MikroTik &lt;span class="caps"&gt;CRS326&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$250&lt;/td&gt;
&lt;td&gt;10 GbE backbone only&lt;/td&gt;
&lt;td&gt;MikroTik &lt;span class="caps"&gt;CRS309&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$350&lt;/td&gt;
&lt;td&gt;PoE + silent + 10GbE uplinks&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;TP&lt;/span&gt;-Link &lt;span class="caps"&gt;TL&lt;/span&gt;-&lt;span class="caps"&gt;SG3428XMP&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$400&lt;/td&gt;
&lt;td&gt;UniFi ecosystem + L3&lt;/td&gt;
&lt;td&gt;UniFi Switch Pro 24&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$400&lt;/td&gt;
&lt;td&gt;Multi-gig workstations&lt;/td&gt;
&lt;td&gt;Netgear &lt;span class="caps"&gt;MS510TXM&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;TP&lt;/span&gt;-Link Omada:&lt;/strong&gt; Amazon Associates, direct affiliate&amp;nbsp;program&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MikroTik:&lt;/strong&gt; Amazon, B&amp;amp;H,&amp;nbsp;distributors&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ubiquiti:&lt;/strong&gt; UniFi Store&amp;nbsp;(direct)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Netgear:&lt;/strong&gt; Amazon,&amp;nbsp;B&amp;amp;H&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;SFP&lt;/span&gt;+ modules:&lt;/strong&gt; 10Gtek, &lt;span class="caps"&gt;FS&lt;/span&gt;.com (Amazon,&amp;nbsp;direct)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;vlan-setup&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;homelab-networking-basics.md&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;10gbe-cabling&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;homelab-ethernet-cabling.md&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;poe&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;tp-link-omada-vs-unifi.md&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;snmp-monitoring&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;prometheus-monitoring-homelab.md&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] What switch powers your homelab? Share your model and why you chose&amp;nbsp;it.&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for our networking gear deals and new switch&amp;nbsp;reviews.&lt;/li&gt;
&lt;li&gt;[internal_link] Ready to configure VLANs? Read our &lt;a href="https://steadypub.com/2026/06/homelab-networking-basics/"&gt;homelab networking basics&lt;/a&gt; guide&amp;nbsp;next.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Guides"/><category term="managed switch homelab"/><category term="homelab"/><category term="self-hosted"/><category term="networking"/><category term="10gbe"/></entry><entry><title>Minisforum MS-01 Review: The Ultimate Mini PC for Homelab 2026</title><link href="https://steadypub.com/2026/06/minisforum-ms-01-review/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T10:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/minisforum-ms-01-review/</id><summary type="html">&lt;p&gt;An in-depth review of the Minisforum &lt;span class="caps"&gt;MS&lt;/span&gt;-01 mini &lt;span class="caps"&gt;PC&lt;/span&gt; for homelab use. Covers specs, performance, thermals, Proxmox compatibility, and whether it is worth the&amp;nbsp;price.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~14 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab and self-hosting&amp;nbsp;enthusiasts&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;The Minisforum &lt;span class="caps"&gt;MS&lt;/span&gt;-01 is a compact mini &lt;span class="caps"&gt;PC&lt;/span&gt; built for power users. Unlike typical &lt;span class="caps"&gt;NUC&lt;/span&gt;-style devices, the &lt;span class="caps"&gt;MS&lt;/span&gt;-01 features dual 10GbE &lt;span class="caps"&gt;SFP&lt;/span&gt;+ ports, dual 2.5GbE &lt;span class="caps"&gt;RJ45&lt;/span&gt; ports, and an Intel Core i9-13900H processor. It is marketed as a &amp;#8220;mini workstation,&amp;#8221; but the homelab community has adopted it as a high-performance virtualization host, &lt;span class="caps"&gt;NAS&lt;/span&gt; replacement, and router platform. This review evaluates its real-world performance for self-hosted&amp;nbsp;infrastructure.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why It Matters&amp;nbsp;Today&lt;/h2&gt;
&lt;h3&gt;10GbE at Mini &lt;span class="caps"&gt;PC&lt;/span&gt;&amp;nbsp;Prices&lt;/h3&gt;
&lt;p&gt;Before the &lt;span class="caps"&gt;MS&lt;/span&gt;-01, 10GbE networking in a small form factor required expensive enterprise gear or &lt;span class="caps"&gt;DIY&lt;/span&gt; builds with PCIe cards. The &lt;span class="caps"&gt;MS&lt;/span&gt;-01 integrates dual &lt;span class="caps"&gt;SFP&lt;/span&gt;+ ports natively, making it ideal for fast storage (TrueNAS, Proxmox Ceph) or high-throughput router/firewall setups (OPNsense,&amp;nbsp;pfSense).&lt;/p&gt;
&lt;h3&gt;Intel 13th Gen&amp;nbsp;Performance&lt;/h3&gt;
&lt;p&gt;The i9-13900H (14 cores, 20 threads) rivals desktop CPUs from a few years ago. For a homelab, this means 10+ VMs, multiple &lt;span class="caps"&gt;LXC&lt;/span&gt; containers, and Jellyfin transcoding — all on a 65W device the size of a hardcover&amp;nbsp;book.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Specifications&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Specification&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Intel Core i9-13900H (14C/20T, up to 5.4 GHz)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;GPU&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Intel Iris Xe (96 &lt;span class="caps"&gt;EU&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;DDR5&lt;/span&gt;-5200, up to 64 &lt;span class="caps"&gt;GB&lt;/span&gt; (2x &lt;span class="caps"&gt;SODIMM&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;3x M.2 2280 NVMe PCIe 4.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Networking&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2x 10GbE &lt;span class="caps"&gt;SFP&lt;/span&gt;+, 2x 2.5GbE &lt;span class="caps"&gt;RJ45&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;USB&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1x &lt;span class="caps"&gt;USB4&lt;/span&gt; (40 Gbps), 3x &lt;span class="caps"&gt;USB&lt;/span&gt; 3.2 Gen2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Display&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1x &lt;span class="caps"&gt;HDMI&lt;/span&gt; 2.1, 1x &lt;span class="caps"&gt;DP&lt;/span&gt; 1.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Power&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;19V &lt;span class="caps"&gt;DC&lt;/span&gt;, 120W adapter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dimensions&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;196 x 189 x 48 mm&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Weight&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.2 kg&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Pros&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;10GbE networking&lt;/strong&gt;: Unmatched at this price point for homelab&amp;nbsp;use&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Triple NVMe&lt;/strong&gt;: Enough fast storage for a &lt;span class="caps"&gt;ZFS&lt;/span&gt; pool or Ceph&amp;nbsp;cluster&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;USB4&lt;/span&gt;&lt;/strong&gt;: Can connect an external &lt;span class="caps"&gt;GPU&lt;/span&gt; or high-speed&amp;nbsp;storage&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Low power&lt;/strong&gt;: 15–65W depending on load; efficient for 24/7&amp;nbsp;operation&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Silent at idle&lt;/strong&gt;: Fan is inaudible when not under heavy&amp;nbsp;load&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Proxmox compatible&lt;/strong&gt;: Runs Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; out of the box with full &lt;span class="caps"&gt;IOMMU&lt;/span&gt;&amp;nbsp;support&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Cons&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Price&lt;/strong&gt;: ~$600–$800 depending on &lt;span class="caps"&gt;RAM&lt;/span&gt; and &lt;span class="caps"&gt;SSD&lt;/span&gt; configuration; more expensive than N100 mini&amp;nbsp;PCs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Thermals under sustained load&lt;/strong&gt;: Can reach 85°C+ during all-core stress&amp;nbsp;tests&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No 2.5&amp;#8221; &lt;span class="caps"&gt;SATA&lt;/span&gt; bay&lt;/strong&gt;: All storage must be NVMe (more expensive per &lt;span class="caps"&gt;TB&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;SFP&lt;/span&gt;+ modules not included&lt;/strong&gt;: &lt;span class="caps"&gt;DAC&lt;/span&gt; cables or transceivers add&amp;nbsp;$20–50&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Single fan&lt;/strong&gt;: If it fails, the system has no&amp;nbsp;redundancy&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Best&amp;nbsp;For&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Homelab operators needing 10GbE without rack&amp;nbsp;servers&lt;/li&gt;
&lt;li&gt;Proxmox/Kubernetes hosts with multiple fast&amp;nbsp;VMs&lt;/li&gt;
&lt;li&gt;OPNsense/pfSense routers with high &lt;span class="caps"&gt;WAN&lt;/span&gt;&amp;nbsp;throughput&lt;/li&gt;
&lt;li&gt;Jellyfin/Plex servers with 4K transcode&amp;nbsp;requirements&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Pricing&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Configuration&lt;/th&gt;
&lt;th&gt;Approximate Price&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Barebone (no &lt;span class="caps"&gt;RAM&lt;/span&gt;/&lt;span class="caps"&gt;SSD&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;~$550&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;32 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; + 1 &lt;span class="caps"&gt;TB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;~$700&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;64 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; + 2 &lt;span class="caps"&gt;TB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;~$900&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Performance&amp;nbsp;Benchmarks&lt;/h2&gt;
&lt;h3&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;: Cinebench&amp;nbsp;R23&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mode&lt;/th&gt;
&lt;th&gt;Score&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Single-core&lt;/td&gt;
&lt;td&gt;1,850&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-core&lt;/td&gt;
&lt;td&gt;16,200&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Network:&amp;nbsp;iperf3&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Interface&lt;/th&gt;
&lt;th&gt;Throughput&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;10GbE &lt;span class="caps"&gt;SFP&lt;/span&gt;+ (&lt;span class="caps"&gt;DAC&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;9.82 Gbps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2.5GbE &lt;span class="caps"&gt;RJ45&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;2.35 Gbps&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Storage: CrystalDiskMark&amp;nbsp;(NVMe)&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test&lt;/th&gt;
&lt;th&gt;Speed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Sequential read&lt;/td&gt;
&lt;td&gt;6,800 &lt;span class="caps"&gt;MB&lt;/span&gt;/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sequential write&lt;/td&gt;
&lt;td&gt;5,200 &lt;span class="caps"&gt;MB&lt;/span&gt;/s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Power&amp;nbsp;Draw&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Load&lt;/th&gt;
&lt;th&gt;Watts&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Idle&lt;/td&gt;
&lt;td&gt;18W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4K transcode&lt;/td&gt;
&lt;td&gt;45W&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;All-core stress&lt;/td&gt;
&lt;td&gt;65W&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Proxmox and&amp;nbsp;Virtualization&lt;/h2&gt;
&lt;p&gt;The &lt;span class="caps"&gt;MS&lt;/span&gt;-01 is an excellent Proxmox host. &lt;span class="caps"&gt;IOMMU&lt;/span&gt; is enabled in &lt;span class="caps"&gt;BIOS&lt;/span&gt;, allowing &lt;span class="caps"&gt;GPU&lt;/span&gt; passthrough to VMs. The 10GbE ports can be bridged to VMs for high-speed network appliances. With 64 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, you can&amp;nbsp;run:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1x Windows 11 &lt;span class="caps"&gt;VM&lt;/span&gt; (8 &lt;span class="caps"&gt;GB&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;2x Ubuntu server VMs (4 &lt;span class="caps"&gt;GB&lt;/span&gt;&amp;nbsp;each)&lt;/li&gt;
&lt;li&gt;3x &lt;span class="caps"&gt;LXC&lt;/span&gt; containers (2 &lt;span class="caps"&gt;GB&lt;/span&gt;&amp;nbsp;each)&lt;/li&gt;
&lt;li&gt;1x Jellyfin &lt;span class="caps"&gt;VM&lt;/span&gt; with &lt;span class="caps"&gt;GPU&lt;/span&gt; passthrough (4 &lt;span class="caps"&gt;GB&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;Headroom for testing and&amp;nbsp;development&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Use a &lt;span class="caps"&gt;DAC&lt;/span&gt; Cable for&amp;nbsp;10GbE&lt;/h3&gt;
&lt;p&gt;Direct Attach Copper (&lt;span class="caps"&gt;DAC&lt;/span&gt;) cables are cheaper and more reliable than &lt;span class="caps"&gt;SFP&lt;/span&gt;+ transceivers for short runs (under 3 meters). A 1-meter &lt;span class="caps"&gt;DAC&lt;/span&gt; costs&amp;nbsp;~$15.&lt;/p&gt;
&lt;h3&gt;Tip 2: Replace the Thermal&amp;nbsp;Paste&lt;/h3&gt;
&lt;p&gt;The factory thermal paste is adequate but not excellent. Replacing it with high-quality paste (e.g., Thermal Grizzly Kryonaut) can drop peak temperatures by&amp;nbsp;5–10°C.&lt;/p&gt;
&lt;h3&gt;Tip 3: Run Proxmox on a &lt;span class="caps"&gt;USB&lt;/span&gt;&amp;nbsp;Drive&lt;/h3&gt;
&lt;p&gt;With three NVMe slots, you can dedicate all internal storage to VMs. Install Proxmox on a high-quality &lt;span class="caps"&gt;USB&lt;/span&gt; drive or small &lt;span class="caps"&gt;SATA&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt; connected via &lt;span class="caps"&gt;USB&lt;/span&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;The Minisforum &lt;span class="caps"&gt;MS&lt;/span&gt;-01 is the best mini &lt;span class="caps"&gt;PC&lt;/span&gt; for advanced homelab use in 2026. It combines desktop-class &lt;span class="caps"&gt;CPU&lt;/span&gt; performance, 10GbE networking, and triple NVMe storage in a compact, efficient chassis. The price is higher than entry-level N100 mini PCs, but the capability is in a different league entirely. If your homelab needs fast networking, multiple VMs, or 4K transcoding, the &lt;span class="caps"&gt;MS&lt;/span&gt;-01 is the default&amp;nbsp;recommendation.&lt;/p&gt;
&lt;h3&gt;Our&amp;nbsp;Recommendation&lt;/h3&gt;
&lt;p&gt;Buy the barebone configuration and add your own &lt;span class="caps"&gt;RAM&lt;/span&gt; and NVMe drives. This gives you the best value and lets you choose high-quality components. Pair it with a 10GbE switch (e.g., MikroTik &lt;span class="caps"&gt;CRS305&lt;/span&gt;) to unlock its full networking&amp;nbsp;potential.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;installation&lt;/strong&gt;: hardware — Minisforum &lt;span class="caps"&gt;MS&lt;/span&gt;-01, 10GbE switches, NVMe&amp;nbsp;SSDs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;integration&lt;/strong&gt;: tool — Proxmox subscriptions, TrueNAS&amp;nbsp;hardware&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;alternatives&lt;/strong&gt;: tool — Beelink &lt;span class="caps"&gt;SER7&lt;/span&gt;, Intel &lt;span class="caps"&gt;NUC&lt;/span&gt; 13&amp;nbsp;Pro&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;what-is&lt;/code&gt; → related_comparison: &lt;a href="https://steadypub.com/2026/06/mini-pc-vs-rack-server/"&gt;Mini &lt;span class="caps"&gt;PC&lt;/span&gt; vs rack&amp;nbsp;server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prerequisites&lt;/code&gt; → setup_guide: &lt;a href="https://steadypub.com/2026/06/intel-n100-mini-pc-homelab/"&gt;Intel N100 mini &lt;span class="caps"&gt;PC&lt;/span&gt;&amp;nbsp;homelab&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → next_steps: &lt;a href="https://steadypub.com/2026/06/proxmox-beginner-guide-2026/"&gt;Proxmox beginner&amp;nbsp;guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] Do you run the &lt;span class="caps"&gt;MS&lt;/span&gt;-01 in your homelab? Share your specs and use&amp;nbsp;case.&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for weekly homelab hardware reviews and buying&amp;nbsp;guides.&lt;/li&gt;
&lt;li&gt;[internal_link] Next: &lt;a href="https://steadypub.com/2026/06/mini-pc-vs-rack-server/"&gt;compare mini PCs with rack&amp;nbsp;servers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Hardware"/><category term="minisforum"/><category term="ms-01"/><category term="mini pc"/><category term="homelab"/><category term="hardware"/><category term="review"/></entry><entry><title>Nextcloud vs Immich: Which Self-Hosted Photo Solution Wins in 2026?</title><link href="https://steadypub.com/2026/06/nextcloud-immich-comparison/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T10:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/nextcloud-immich-comparison/</id><summary type="html">&lt;p&gt;An honest, feature-by-feature comparison of Nextcloud Photos and Immich for self-hosted photo management. Covers &lt;span class="caps"&gt;AI&lt;/span&gt;, mobile apps, backup, storage, and real-world use&amp;nbsp;cases.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~14 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab and self-hosting&amp;nbsp;enthusiasts&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;Nextcloud and Immich are the two leading self-hosted photo management platforms. Both offer mobile auto-upload, web galleries, and privacy-first storage. However, they approach the problem differently. Nextcloud is a general-purpose file sync platform with a photo app; Immich is a purpose-built photo manager with &lt;span class="caps"&gt;AI&lt;/span&gt; features. This guide compares them across 12 criteria to help you choose the right tool for your&amp;nbsp;homelab.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why This Comparison&amp;nbsp;Matters&lt;/h2&gt;
&lt;h3&gt;The Self-Hosted Photo&amp;nbsp;Problem&lt;/h3&gt;
&lt;p&gt;Google Photos and iCloud are convenient but expensive and privacy-invasive. Self-hosting solves this, but choosing the wrong platform leads to frustration: slow uploads, missing &lt;span class="caps"&gt;AI&lt;/span&gt; search, or poor mobile apps. This comparison prevents that mistake by matching each tool to the right user&amp;nbsp;profile.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;h3&gt;Nextcloud: General-Purpose&amp;nbsp;Deployment&lt;/h3&gt;
&lt;p&gt;Nextcloud deploys as a Docker stack with a database, Redis, and web server. It is more complex because it is a full collaboration&amp;nbsp;platform.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Excerpt from Nextcloud Compose&lt;/span&gt;
&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud:apache&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8080:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;postgres:15-alpine&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis:alpine&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Immich: Dedicated Photo&amp;nbsp;Stack&lt;/h3&gt;
&lt;p&gt;Immich is a multi-service app with a dedicated server, microservices, machine learning, and PostgreSQL with&amp;nbsp;pgvecto.rs.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Excerpt from Immich Compose&lt;/span&gt;
&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;immich-server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ghcr.io/immich-app/immich-server:release&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;immich-machine-learning&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ghcr.io/immich-app/immich-machine-learning:release&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;database&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;tensorchord/pgvecto-rs:pg14-v0.2.0&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis:7-alpine&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Verdict:&lt;/strong&gt; Immich is more specialized but not simpler. Both require Docker Compose&amp;nbsp;knowledge.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Basic Setup and&amp;nbsp;Configuration&lt;/h2&gt;
&lt;h3&gt;Nextcloud&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Install the &lt;strong&gt;Memories&lt;/strong&gt; app (superior to the built-in Photos&amp;nbsp;app)&lt;/li&gt;
&lt;li&gt;Enable auto-upload in the mobile&amp;nbsp;app&lt;/li&gt;
&lt;li&gt;Configure external storage for large&amp;nbsp;libraries&lt;/li&gt;
&lt;li&gt;Set up a reverse proxy for &lt;span class="caps"&gt;HTTPS&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Immich&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Deploy the Compose&amp;nbsp;stack&lt;/li&gt;
&lt;li&gt;Create an admin&amp;nbsp;user&lt;/li&gt;
&lt;li&gt;Install the mobile app and enable background&amp;nbsp;upload&lt;/li&gt;
&lt;li&gt;Configure storage templates (optional but&amp;nbsp;recommended)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Verdict:&lt;/strong&gt; Immich&amp;#8217;s setup is more guided. Nextcloud requires app selection (Memories vs Photos) to get a comparable&amp;nbsp;experience.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Advanced&amp;nbsp;Features&lt;/h2&gt;
&lt;h3&gt;&lt;span class="caps"&gt;AI&lt;/span&gt; and&amp;nbsp;Search&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Nextcloud&lt;/th&gt;
&lt;th&gt;Immich&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Face recognition&lt;/td&gt;
&lt;td&gt;Yes (via Memories + Recognize)&lt;/td&gt;
&lt;td&gt;Yes (native, faster)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Object/scene detection&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Yes (&lt;span class="caps"&gt;CLIP&lt;/span&gt;-based)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Natural language search&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes (&amp;#8220;photos of my dog at the beach&amp;#8221;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Duplicate detection&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Smart albums&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Mobile&amp;nbsp;Apps&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Nextcloud&lt;/th&gt;
&lt;th&gt;Immich&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Auto-upload&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Background upload&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RAW&lt;/span&gt; support&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Offline viewing&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Map view&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Search&lt;/td&gt;
&lt;td&gt;Basic&lt;/td&gt;
&lt;td&gt;Advanced (&lt;span class="caps"&gt;AI&lt;/span&gt;-powered)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Backup and&amp;nbsp;Storage&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Nextcloud&lt;/th&gt;
&lt;th&gt;Immich&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Storage templates&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes (date-based folders)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;External libraries&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Object storage (S3)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Client-side encryption&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;End-to-end encryption&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Integrating with Your&amp;nbsp;Homelab&lt;/h2&gt;
&lt;h3&gt;Nextcloud&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Best for&lt;/strong&gt;: Users who want a unified platform (files, documents, calendar,&amp;nbsp;photos)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Integration&lt;/strong&gt;: Mount existing &lt;span class="caps"&gt;NAS&lt;/span&gt; shares via external&amp;nbsp;storage&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Plugins&lt;/strong&gt;: Memories, Recognize, Maps, Face&amp;nbsp;Recognition&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Immich&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Best for&lt;/strong&gt;: Users who want a Google Photos clone with &lt;span class="caps"&gt;AI&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Integration&lt;/strong&gt;: Use as a dedicated photo backend; sync to &lt;span class="caps"&gt;NAS&lt;/span&gt; via&amp;nbsp;rclone&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;API&lt;/span&gt;&lt;/strong&gt;: &lt;span class="caps"&gt;REST&lt;/span&gt; &lt;span class="caps"&gt;API&lt;/span&gt; for automation and third-party&amp;nbsp;integrations&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Alternatives to&amp;nbsp;Consider&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;AI&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Mobile App&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Nextcloud&lt;/td&gt;
&lt;td&gt;Unified platform&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Immich&lt;/td&gt;
&lt;td&gt;Photo-focused&lt;/td&gt;
&lt;td&gt;Excellent&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PhotoPrism&lt;/td&gt;
&lt;td&gt;Archival, geo-browsing&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Web app&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LibrePhotos&lt;/td&gt;
&lt;td&gt;Open-source purist&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Frequently Asked&amp;nbsp;Questions&lt;/h2&gt;
&lt;h3&gt;Can I use both Nextcloud and&amp;nbsp;Immich?&lt;/h3&gt;
&lt;p&gt;Yes. Use Nextcloud for file sync and collaboration, Immich for photo management. They can share the same storage backend via &lt;span class="caps"&gt;NFS&lt;/span&gt; or&amp;nbsp;S3.&lt;/p&gt;
&lt;h3&gt;Which is better for&amp;nbsp;families?&lt;/h3&gt;
&lt;p&gt;Immich is better for families who primarily want photo sharing and &lt;span class="caps"&gt;AI&lt;/span&gt; search. Nextcloud is better if you also need file sharing, calendars, and document&amp;nbsp;editing.&lt;/p&gt;
&lt;h3&gt;Does Immich support client-side&amp;nbsp;encryption?&lt;/h3&gt;
&lt;p&gt;Not yet. Immich prioritizes speed and &lt;span class="caps"&gt;AI&lt;/span&gt; features. If encryption is mandatory, use Nextcloud with &lt;span class="caps"&gt;E2EE&lt;/span&gt; or sync Immich to an encrypted &lt;span class="caps"&gt;NAS&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;How much storage does each&amp;nbsp;need?&lt;/h3&gt;
&lt;p&gt;Budget 2–3x your raw photo size for both. Thumbnails, &lt;span class="caps"&gt;AI&lt;/span&gt; embeddings, and versions consume extra&amp;nbsp;space.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Choose Immich if&lt;/strong&gt;: You want a Google Photos replacement with &lt;span class="caps"&gt;AI&lt;/span&gt; search, face recognition, and a polished mobile&amp;nbsp;app.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Choose Nextcloud if&lt;/strong&gt;: You want a unified private cloud with files, photos, documents, and collaboration in one&amp;nbsp;platform.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Try Immich for 30 days with your full&amp;nbsp;library&lt;/li&gt;
&lt;li&gt;Compare mobile app&amp;nbsp;experiences&lt;/li&gt;
&lt;li&gt;Decide if you need Nextcloud&amp;#8217;s broader&amp;nbsp;ecosystem&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;installation&lt;/strong&gt;: hardware — Mini PCs, &lt;span class="caps"&gt;NAS&lt;/span&gt; devices,&amp;nbsp;SSDs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;integration&lt;/strong&gt;: tool — Cloud storage backup&amp;nbsp;services&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;alternatives&lt;/strong&gt;: tool — PhotoPrism commercial&amp;nbsp;license&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;installation&lt;/code&gt; → setup_guide: &lt;a href="https://steadypub.com/2026/06/immich-photo-server/"&gt;Immich setup&amp;nbsp;guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;integration&lt;/code&gt; → related_guide: &lt;a href="https://steadypub.com/2026/06/nextcloud-self-hosted/"&gt;Nextcloud self-hosted&amp;nbsp;guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;alternatives&lt;/code&gt; → comparison: &lt;a href="https://steadypub.com/2026/06/immich-vs-google-photos/"&gt;Immich vs Google&amp;nbsp;Photos&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] Which photo manager do you use? Nextcloud, Immich, or something&amp;nbsp;else?&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for weekly self-hosted app&amp;nbsp;comparisons.&lt;/li&gt;
&lt;li&gt;[internal_link] Next: &lt;a href="https://steadypub.com/2026/06/immich-photo-server/"&gt;set up Immich on your&amp;nbsp;server&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Comparisons"/><category term="nextcloud"/><category term="immich"/><category term="photos"/><category term="self-hosted"/><category term="comparison"/><category term="homelab"/></entry><entry><title>Nextcloud Self-Hosted: A Complete Deployment Guide for Your Homelab</title><link href="https://steadypub.com/2026/06/nextcloud-self-hosted/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T10:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/nextcloud-self-hosted/</id><summary type="html">&lt;p&gt;A practical guide to deploying Nextcloud on your own server. Covers Docker, bare metal, performance tuning, and essential apps for a complete private&amp;nbsp;cloud.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~14 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab and self-hosting&amp;nbsp;enthusiasts&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is&amp;nbsp;Nextcloud?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Nextcloud is an open-source suite of client-server software for creating and using file hosting services. It is functionally similar to Dropbox, Google Drive, and Microsoft OneDrive, but hosted on your own server. Nextcloud also includes apps for calendar, contacts, tasks, notes, video conferencing, and password management. It is the most widely deployed self-hosted cloud platform in the homelab and small business&amp;nbsp;communities.&lt;/p&gt;
&lt;h3&gt;A Brief&amp;nbsp;History&lt;/h3&gt;
&lt;p&gt;Nextcloud was founded in 2016 by Frank Karlitschek and a core team of ownCloud developers. The project was created to ensure that the software remained fully open-source and free from proprietary licensing. Since then, Nextcloud has grown to over 400 employees, with enterprise support, a vibrant app ecosystem, and partnerships with major hardware vendors (Dell, &lt;span class="caps"&gt;HPE&lt;/span&gt;, Western Digital). The community edition remains fully free and&amp;nbsp;unencumbered.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why Self-Host&amp;nbsp;Nextcloud?&lt;/h2&gt;
&lt;h3&gt;Data Ownership and&amp;nbsp;Privacy&lt;/h3&gt;
&lt;p&gt;When you self-host Nextcloud, your files, contacts, and calendar data reside on hardware you control. There is no third-party access, no data mining, and no risk of service shutdown. For &lt;span class="caps"&gt;GDPR&lt;/span&gt;-conscious users, healthcare professionals, and journalists, this is often a legal or ethical&amp;nbsp;requirement.&lt;/p&gt;
&lt;h3&gt;Cost&amp;nbsp;Control&lt;/h3&gt;
&lt;p&gt;Commercial cloud storage charges per gigabyte. For a family with 2 &lt;span class="caps"&gt;TB&lt;/span&gt; of photos, videos, and documents, annual costs can exceed $100. A self-hosted Nextcloud on a mini &lt;span class="caps"&gt;PC&lt;/span&gt; or &lt;span class="caps"&gt;NAS&lt;/span&gt; has a one-time hardware cost and negligible electricity. Over five years, the savings are&amp;nbsp;substantial.&lt;/p&gt;
&lt;h3&gt;Customization and&amp;nbsp;Integration&lt;/h3&gt;
&lt;p&gt;Nextcloud&amp;#8217;s App Store contains over 400 apps. You can integrate with existing tools: mount external storage (S3, &lt;span class="caps"&gt;SMB&lt;/span&gt;, WebDAV), connect to Active Directory, or use webhooks to trigger automation. This makes Nextcloud a hub, not just a storage&amp;nbsp;bucket.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;h3&gt;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;A Linux server or &lt;span class="caps"&gt;NAS&lt;/span&gt; with 2+ &lt;span class="caps"&gt;CPU&lt;/span&gt; cores and 4 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Docker and Docker Compose (recommended) or &lt;span class="caps"&gt;LAMP&lt;/span&gt;&amp;nbsp;stack&lt;/li&gt;
&lt;li&gt;A domain name and reverse proxy (for &lt;span class="caps"&gt;HTTPS&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;SMTP&lt;/span&gt; server credentials (for email&amp;nbsp;notifications)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Method 1: Docker Compose&amp;nbsp;(Recommended)&lt;/h3&gt;
&lt;p&gt;This is the fastest, most maintainable deployment&amp;nbsp;method.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud:apache&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud-app&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8080:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud:/var/www/html&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_PASSWORD=***      - MYSQL_DATABASE=nextcloud&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_USER=nextcloud&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_HOST=db&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;NEXTCLOUD_ADMIN_USER=admin&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;NEXTCLOUD_ADMIN_PASSWORD=***      - NEXTCLOUD_TRUSTED_DOMAINS=cloud.yourdomain.com&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;db&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;mariadb:10.6&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud-db&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;--transaction-isolation=READ-COMMITTED --log-bin=binlog --binlog-format=ROW&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;db:/var/lib/mysql&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_ROOT_PASSWORD=***      - MYSQL_PASSWORD=***      - MYSQL_DATABASE=nextcloud&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_USER=nextcloud&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis:alpine&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud-redis&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;cron&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud:apache&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud:/var/www/html:ro&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;entrypoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/cron.sh&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;db&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;nextcloud&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Deploy:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Method 2: Ubuntu &lt;span class="caps"&gt;LAMP&lt;/span&gt;&amp;nbsp;Stack&lt;/h3&gt;
&lt;p&gt;For a bare-metal or &lt;span class="caps"&gt;VM&lt;/span&gt;&amp;nbsp;installation:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Install Apache, MariaDB, PHP&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;update
sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;apache2&lt;span class="w"&gt; &lt;/span&gt;mariadb-server&lt;span class="w"&gt; &lt;/span&gt;libapache2-mod-php&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;php-gd&lt;span class="w"&gt; &lt;/span&gt;php-mysql&lt;span class="w"&gt; &lt;/span&gt;php-curl&lt;span class="w"&gt; &lt;/span&gt;php-mbstring&lt;span class="w"&gt; &lt;/span&gt;php-intl&lt;span class="w"&gt; &lt;/span&gt;php-gmp&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;php-bcmath&lt;span class="w"&gt; &lt;/span&gt;php-xml&lt;span class="w"&gt; &lt;/span&gt;php-zip&lt;span class="w"&gt; &lt;/span&gt;php-imagick&lt;span class="w"&gt; &lt;/span&gt;php-opcache&lt;span class="w"&gt; &lt;/span&gt;php-apcu

&lt;span class="c1"&gt;# Download Nextcloud&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/var/www
sudo&lt;span class="w"&gt; &lt;/span&gt;wget&lt;span class="w"&gt; &lt;/span&gt;https://download.nextcloud.com/server/releases/latest.tar.bz2
sudo&lt;span class="w"&gt; &lt;/span&gt;tar&lt;span class="w"&gt; &lt;/span&gt;-xjf&lt;span class="w"&gt; &lt;/span&gt;latest.tar.bz2
sudo&lt;span class="w"&gt; &lt;/span&gt;chown&lt;span class="w"&gt; &lt;/span&gt;-R&lt;span class="w"&gt; &lt;/span&gt;www-data:www-data&lt;span class="w"&gt; &lt;/span&gt;nextcloud

&lt;span class="c1"&gt;# Enable required Apache modules&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;a2enmod&lt;span class="w"&gt; &lt;/span&gt;rewrite&lt;span class="w"&gt; &lt;/span&gt;headers&lt;span class="w"&gt; &lt;/span&gt;env&lt;span class="w"&gt; &lt;/span&gt;dir&lt;span class="w"&gt; &lt;/span&gt;mime&lt;span class="w"&gt; &lt;/span&gt;ssl
sudo&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;restart&lt;span class="w"&gt; &lt;/span&gt;apache2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Basic Setup and&amp;nbsp;Configuration&lt;/h2&gt;
&lt;h3&gt;Step 1: Complete the Web&amp;nbsp;Installer&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Navigate&amp;nbsp;to &lt;code&gt;http://your-server:8080&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Create an admin&amp;nbsp;account&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;MySQL/MariaDB&lt;/strong&gt; and enter&amp;nbsp;credentials&lt;/li&gt;
&lt;li&gt;Finish the&amp;nbsp;installation&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Step 2: Configure Trusted&amp;nbsp;Domains&lt;/h3&gt;
&lt;p&gt;Edit &lt;code&gt;config/config.php&lt;/code&gt; in the Nextcloud data&amp;nbsp;directory:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="x"&gt;  &amp;#39;trusted_domains&amp;#39; =&amp;gt; &lt;/span&gt;
&lt;span class="x"&gt;  array (&lt;/span&gt;
&lt;span class="x"&gt;    0 =&amp;gt; &amp;#39;cloud.yourdomain.com&amp;#39;,&lt;/span&gt;
&lt;span class="x"&gt;    1 =&amp;gt; &amp;#39;192.168.1.10&amp;#39;,&lt;/span&gt;
&lt;span class="x"&gt;  ),&lt;/span&gt;
&lt;span class="x"&gt;  &amp;#39;overwrite.cli.url&amp;#39; =&amp;gt; &amp;#39;https://cloud.yourdomain.com&amp;#39;,&lt;/span&gt;
&lt;span class="x"&gt;  &amp;#39;overwriteprotocol&amp;#39; =&amp;gt; &amp;#39;https&amp;#39;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Step 3: Enable Performance&amp;nbsp;Caching&lt;/h3&gt;
&lt;p&gt;Add&amp;nbsp;to &lt;code&gt;config.php&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="x"&gt;  &amp;#39;memcache.local&amp;#39; =&amp;gt; &amp;#39;\OC\Memcache\APCu&amp;#39;,&lt;/span&gt;
&lt;span class="x"&gt;  &amp;#39;memcache.locking&amp;#39; =&amp;gt; &amp;#39;\OC\Memcache\Redis&amp;#39;,&lt;/span&gt;
&lt;span class="x"&gt;  &amp;#39;redis&amp;#39; =&amp;gt; [&lt;/span&gt;
&lt;span class="x"&gt;    &amp;#39;host&amp;#39; =&amp;gt; &amp;#39;redis&amp;#39;,&lt;/span&gt;
&lt;span class="x"&gt;    &amp;#39;port&amp;#39; =&amp;gt; 6379,&lt;/span&gt;
&lt;span class="x"&gt;  ],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Step 4: Set Up&amp;nbsp;Email&lt;/h3&gt;
&lt;p&gt;In &lt;strong&gt;Administration Settings&lt;/strong&gt; → &lt;strong&gt;Basic Settings&lt;/strong&gt; → &lt;strong&gt;Email Server&lt;/strong&gt;,&amp;nbsp;configure:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Mode: &lt;strong&gt;&lt;span class="caps"&gt;SMTP&lt;/span&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Encryption: &lt;strong&gt;&lt;span class="caps"&gt;STARTTLS&lt;/span&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;From: &lt;code&gt;noreply@yourdomain.com&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Server: &lt;code&gt;smtp.gmail.com&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Port: &lt;code&gt;587&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Credentials: app-specific&amp;nbsp;password&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Advanced&amp;nbsp;Features&lt;/h2&gt;
&lt;h3&gt;External&amp;nbsp;Storage&lt;/h3&gt;
&lt;p&gt;Mount S3, &lt;span class="caps"&gt;SMB&lt;/span&gt;, or WebDAV as external&amp;nbsp;folders:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Enable the &lt;strong&gt;External Storage Support&lt;/strong&gt;&amp;nbsp;app&lt;/li&gt;
&lt;li&gt;Go to &lt;strong&gt;Administration&lt;/strong&gt; → &lt;strong&gt;External&amp;nbsp;Storage&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Add a mount point&amp;nbsp;(e.g., &lt;code&gt;s3://mybucket&lt;/code&gt; or &lt;code&gt;smb://nas/media&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Two-Factor&amp;nbsp;Authentication&lt;/h3&gt;
&lt;p&gt;Install the &lt;strong&gt;Two-Factor &lt;span class="caps"&gt;TOTP&lt;/span&gt;&lt;/strong&gt; app. In &lt;strong&gt;Personal Settings&lt;/strong&gt; → &lt;strong&gt;Security&lt;/strong&gt;, enable &lt;span class="caps"&gt;TOTP&lt;/span&gt;. Use a hardware token or authenticator&amp;nbsp;app.&lt;/p&gt;
&lt;h3&gt;Collabora&amp;nbsp;Online&lt;/h3&gt;
&lt;p&gt;For document editing, deploy the Collabora Docker&amp;nbsp;container:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;collabora&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;collabora/code&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud-collabora&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;9980:9980&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;domain=cloud.yourdomain.com&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;dictionaries=en_US&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;cap_add&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MKNOD&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then in Nextcloud, install the &lt;strong&gt;Collabora Online&lt;/strong&gt; app and set the server &lt;span class="caps"&gt;URL&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;End-to-End&amp;nbsp;Encryption&lt;/h3&gt;
&lt;p&gt;Enable the &lt;strong&gt;End-to-End Encryption&lt;/strong&gt; app for client-side encryption. The server cannot decrypt these files. The encryption key is held on the client; losing it means permanent data&amp;nbsp;loss.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Integrating with Your&amp;nbsp;Homelab&lt;/h2&gt;
&lt;h3&gt;Reverse&amp;nbsp;Proxy&lt;/h3&gt;
&lt;p&gt;Place Nextcloud behind a reverse proxy with Let&amp;#8217;s&amp;nbsp;Encrypt:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.enable=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.nextcloud.rule=Host(`cloud.yourdomain.com`)&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.nextcloud.tls.certresolver=letsencrypt&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.services.nextcloud.loadbalancer.server.port=80&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Backup&lt;/h3&gt;
&lt;p&gt;Back up both the database and the data&amp;nbsp;directory:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Database&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;nextcloud-db&lt;span class="w"&gt; &lt;/span&gt;mysqldump&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="w"&gt; &lt;/span&gt;nextcloud&lt;span class="w"&gt; &lt;/span&gt;-p***&lt;span class="w"&gt; &lt;/span&gt;nextcloud&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;nextcloud-db.sql

&lt;span class="c1"&gt;# Data&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;--rm&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;nextcloud:/data&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;:/backup&lt;span class="w"&gt; &lt;/span&gt;alpine&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;tar&lt;span class="w"&gt; &lt;/span&gt;czf&lt;span class="w"&gt; &lt;/span&gt;/backup/nextcloud-data.tar.gz&lt;span class="w"&gt; &lt;/span&gt;-C&lt;span class="w"&gt; &lt;/span&gt;/data&lt;span class="w"&gt; &lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Mobile and Desktop&amp;nbsp;Sync&lt;/h3&gt;
&lt;p&gt;Install the Nextcloud apps for iOS, Android, Windows, macOS, and Linux. Enable auto-upload for photos and select folders for&amp;nbsp;sync.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Alternatives to&amp;nbsp;Consider&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;Apps&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Nextcloud&lt;/td&gt;
&lt;td&gt;Full productivity suite&lt;/td&gt;
&lt;td&gt;400+&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ownCloud&lt;/td&gt;
&lt;td&gt;Enterprise compliance&lt;/td&gt;
&lt;td&gt;100+&lt;/td&gt;
&lt;td&gt;Free/Enterprise&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Seafile&lt;/td&gt;
&lt;td&gt;Fast file sync&lt;/td&gt;
&lt;td&gt;Few&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;File Browser&lt;/td&gt;
&lt;td&gt;Minimal file sharing&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Frequently Asked&amp;nbsp;Questions&lt;/h2&gt;
&lt;h3&gt;How much storage do I&amp;nbsp;need?&lt;/h3&gt;
&lt;p&gt;Plan for 2–3x your current data size to account for versions, trash, and&amp;nbsp;thumbnails.&lt;/p&gt;
&lt;h3&gt;Can I run Nextcloud on a Raspberry&amp;nbsp;Pi?&lt;/h3&gt;
&lt;p&gt;Yes, but use an &lt;span class="caps"&gt;SSD&lt;/span&gt; and limit the number of apps. Performance is acceptable for 1–3&amp;nbsp;users.&lt;/p&gt;
&lt;h3&gt;How do I update&amp;nbsp;Nextcloud?&lt;/h3&gt;
&lt;p&gt;For Docker, pull the latest image and recreate. For bare metal, run the built-in updater&amp;nbsp;or &lt;code&gt;occ upgrade&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Is Nextcloud&amp;nbsp;secure?&lt;/h3&gt;
&lt;p&gt;Yes, with proper hardening: &lt;span class="caps"&gt;HTTPS&lt;/span&gt;, &lt;span class="caps"&gt;2FA&lt;/span&gt;, server-side encryption, and regular&amp;nbsp;updates.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Nextcloud is the most capable self-hosted cloud platform. It provides file sync, collaboration, and communication tools in a single package. With Docker, it deploys in minutes. With proper caching, external storage, and a reverse proxy, it scales to family or small-team&amp;nbsp;use.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Install mobile apps and enable&amp;nbsp;auto-upload&lt;/li&gt;
&lt;li&gt;Configure external storage for your &lt;span class="caps"&gt;NAS&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Deploy Collabora for document&amp;nbsp;editing&lt;/li&gt;
&lt;li&gt;Set up automated&amp;nbsp;backups&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;installation&lt;/strong&gt;: hosting — &lt;span class="caps"&gt;VPS&lt;/span&gt; or dedicated server for remote&amp;nbsp;hosting&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;integration&lt;/strong&gt;: tool — OnlyOffice or Collabora&amp;nbsp;licenses&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;alternatives&lt;/strong&gt;: tool — &lt;span class="caps"&gt;NAS&lt;/span&gt;&amp;nbsp;hardware&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;installation&lt;/code&gt; → setup_guide: &lt;a href="https://steadypub.com/2026/06/docker-compose-for-beginners/"&gt;Docker Compose for&amp;nbsp;beginners&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;integration&lt;/code&gt; → related_guide: &lt;a href="https://steadypub.com/2026/06/nextcloud-vs-owncloud/"&gt;Nextcloud vs&amp;nbsp;ownCloud&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;alternatives&lt;/code&gt; → comparison: &lt;a href="https://steadypub.com/2026/06/nextcloud-immich-comparison/"&gt;Nextcloud vs&amp;nbsp;Immich&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] What apps do you run in Nextcloud? Share your&amp;nbsp;setup.&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for weekly self-hosting&amp;nbsp;guides.&lt;/li&gt;
&lt;li&gt;[internal_link] Next: compare &lt;a href="https://steadypub.com/2026/06/nextcloud-immich-comparison/"&gt;Nextcloud with&amp;nbsp;Immich&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Tool Guides"/><category term="nextcloud"/><category term="self-hosted"/><category term="cloud"/><category term="docker"/><category term="homelab"/><category term="nas"/></entry><entry><title>Nextcloud vs ownCloud: Which Self-Hosted Cloud Suite Wins in 2026?</title><link href="https://steadypub.com/2026/06/nextcloud-vs-owncloud/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T10:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/nextcloud-vs-owncloud/</id><summary type="html">&lt;p&gt;Nextcloud and ownCloud are the leading open-source cloud suites. Compare features, licensing, performance, and community support to choose the right one for your&amp;nbsp;homelab.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~10 minutes&lt;br&gt;
&lt;strong&gt;Audience:&lt;/strong&gt; Self-hosters choosing between Nextcloud and&amp;nbsp;ownCloud&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Shared&amp;nbsp;Heritage&lt;/h2&gt;
&lt;p&gt;Both projects share the same origin. In 2010, Frank Karlitschek started the ownCloud project. In 2016, Karlitschek and key developers forked ownCloud to create Nextcloud, citing concerns about open-source commitment and commercial focus. The split created two distinct&amp;nbsp;philosophies.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Licensing &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;Philosophy&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Nextcloud&lt;/th&gt;
&lt;th&gt;ownCloud&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;License&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;AGPLv3 (fully open)&lt;/td&gt;
&lt;td&gt;Dual: &lt;span class="caps"&gt;MIT&lt;/span&gt; (core) + proprietary (enterprise)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Business model&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Subscription support + apps&lt;/td&gt;
&lt;td&gt;Enterprise features + proprietary apps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Open source&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;100% open&lt;/td&gt;
&lt;td&gt;Core open; some features closed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Development&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Community-driven&lt;/td&gt;
&lt;td&gt;Company-controlled&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Price&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Free (pay for support)&lt;/td&gt;
&lt;td&gt;Free (pay for enterprise features)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Feature&amp;nbsp;Comparison&lt;/h2&gt;
&lt;h3&gt;Core Features&amp;nbsp;(Both)&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Nextcloud&lt;/th&gt;
&lt;th&gt;ownCloud&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;File sync &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; share&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WebDAV&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Calendar (CalDAV)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Contacts (CardDAV)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Web &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desktop sync clients&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mobile apps (iOS/Android)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;End-to-end encryption&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Office integration&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;User management&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sharing (public links)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Activity tracking&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Exclusive&amp;nbsp;Features&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Nextcloud&lt;/th&gt;
&lt;th&gt;ownCloud&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Talk (video conferencing)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌ (separate app)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Collectives (wiki)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Forms (surveys)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Whiteboard&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mail client&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Social (federated)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;AI&lt;/span&gt; assistant (Nextcloud Assistant)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Flow (automation)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Infinite Scale (oCIS)&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅ (re-architected)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Real-time collaboration&lt;/td&gt;
&lt;td&gt;❌ (Talk only)&lt;/td&gt;
&lt;td&gt;✅ (oCIS)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Webfinger federation&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Performance &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;Architecture&lt;/h2&gt;
&lt;h3&gt;Nextcloud&amp;nbsp;Architecture&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;PHP&lt;/span&gt;-based&lt;/strong&gt; (traditional &lt;span class="caps"&gt;LAMP&lt;/span&gt;/&lt;span class="caps"&gt;LEMP&lt;/span&gt;&amp;nbsp;stack)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Database:&lt;/strong&gt; MySQL/MariaDB, PostgreSQL,&amp;nbsp;SQLite&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cache:&lt;/strong&gt; Redis, APCu,&amp;nbsp;Memcached&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Web server:&lt;/strong&gt;&amp;nbsp;Apache/Nginx&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Strength:&lt;/strong&gt; Mature ecosystem, thousands of&amp;nbsp;apps&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Weakness:&lt;/strong&gt; &lt;span class="caps"&gt;PHP&lt;/span&gt; resource usage, scaling limits for 10K+&amp;nbsp;users&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;ownCloud Architecture&amp;nbsp;(Classic)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;PHP&lt;/span&gt;-based&lt;/strong&gt; (same stack as Nextcloud&amp;nbsp;historically)&lt;/li&gt;
&lt;li&gt;Being phased out in favor of &lt;strong&gt;Infinite Scale&amp;nbsp;(oCIS)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;ownCloud Infinite Scale&amp;nbsp;(oCIS)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Go-based&lt;/strong&gt; (microservices&amp;nbsp;architecture)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Database:&lt;/strong&gt; Built-in (no external &lt;span class="caps"&gt;DB&lt;/span&gt;&amp;nbsp;needed)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Storage:&lt;/strong&gt; S3-compatible&amp;nbsp;backends&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Web server:&lt;/strong&gt; Embedded (no Apache/Nginx&amp;nbsp;needed)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Strength:&lt;/strong&gt; Modern, fast, scalable,&amp;nbsp;container-native&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Weakness:&lt;/strong&gt; Newer ecosystem, fewer&amp;nbsp;apps&lt;/li&gt;
&lt;/ul&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Nextcloud (&lt;span class="caps"&gt;PHP&lt;/span&gt;)&lt;/th&gt;
&lt;th&gt;ownCloud Classic&lt;/th&gt;
&lt;th&gt;ownCloud oCIS&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Memory footprint&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;512MB&lt;/span&gt;–&lt;span class="caps"&gt;1GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;512MB&lt;/span&gt;–&lt;span class="caps"&gt;1GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;256MB&lt;/span&gt;–&lt;span class="caps"&gt;512MB&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt; usage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Moderate&lt;/td&gt;
&lt;td&gt;Moderate&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Concurrent users&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1,000–5,000&lt;/td&gt;
&lt;td&gt;1,000–5,000&lt;/td&gt;
&lt;td&gt;10,000+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Container startup&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;5–10s&lt;/td&gt;
&lt;td&gt;5–10s&lt;/td&gt;
&lt;td&gt;2–5s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;App ecosystem&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1,000+&lt;/td&gt;
&lt;td&gt;200+&lt;/td&gt;
&lt;td&gt;50+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Deployment complexity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Docker Deployment&amp;nbsp;Comparison&lt;/h2&gt;
&lt;h3&gt;Nextcloud Docker&amp;nbsp;Compose&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;nextcloud&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud:29-apache&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_PASSWORD=nextcloud&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_DATABASE=nextcloud&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_USER=nextcloud&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_HOST=db&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud_data:/var/www/html&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;8080:80&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;mariadb:10.6&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud_db&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_ROOT_PASSWORD=root&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_PASSWORD=nextcloud&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_DATABASE=nextcloud&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_USER=nextcloud&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;db_data:/var/lib/mysql&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis:alpine&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud_redis&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;nextcloud_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;db_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;ownCloud oCIS Docker&amp;nbsp;Compose&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;ocis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;owncloud/ocis:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ocis&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;OCIS_INSECURE=true&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;PROXY_HTTP_ADDR=0.0.0.0:9200&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;OCIS_URL=https://cloud.mydomain.com&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;IDM_ADMIN_PASSWORD=admin&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ocis_data:/var/lib/ocis&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;9200:9200&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;ocis_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Security&lt;/h2&gt;
&lt;h3&gt;Nextcloud&amp;nbsp;Security&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Security bug bounty:&lt;/strong&gt; Active HackerOne&amp;nbsp;program&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;End-to-end encryption:&lt;/strong&gt; Available for client-side&amp;nbsp;encryption&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Two-factor authentication:&lt;/strong&gt; &lt;span class="caps"&gt;TOTP&lt;/span&gt;, WebAuthn/&lt;span class="caps"&gt;FIDO2&lt;/span&gt;, backup&amp;nbsp;codes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Brute-force protection:&lt;/strong&gt; Built-in rate&amp;nbsp;limiting&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security scan:&lt;/strong&gt;&amp;nbsp;https://scan.nextcloud.com&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;ownCloud&amp;nbsp;Security&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Security bug bounty:&lt;/strong&gt; Active&amp;nbsp;program&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;End-to-end encryption:&lt;/strong&gt;&amp;nbsp;Available&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Two-factor authentication:&lt;/strong&gt; &lt;span class="caps"&gt;TOTP&lt;/span&gt;,&amp;nbsp;WebAuthn&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Virus scanning:&lt;/strong&gt; ClamAV&amp;nbsp;integration&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Community &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;Ecosystem&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Nextcloud&lt;/th&gt;
&lt;th&gt;ownCloud&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GitHub stars&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;28,000+&lt;/td&gt;
&lt;td&gt;8,000+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Contributors&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1,500+&lt;/td&gt;
&lt;td&gt;300+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;App marketplace&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1,000+ apps&lt;/td&gt;
&lt;td&gt;200+ apps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Community forum&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Very active&lt;/td&gt;
&lt;td&gt;Moderate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Reddit community&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;r/Nextcloud (25K+)&lt;/td&gt;
&lt;td&gt;r/ownCloud (3K+)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Documentation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Extensive&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Conference&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Nextcloud Conference (annual)&lt;/td&gt;
&lt;td&gt;ownCloud Conference&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;When to Choose&amp;nbsp;Nextcloud&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Users wanting an all-in-one productivity&amp;nbsp;suite&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ideal if:&lt;/strong&gt; You want Talk, Mail, Calendar, and Office in one&amp;nbsp;platform&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Strength:&lt;/strong&gt; Massive app ecosystem, active&amp;nbsp;community&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tradeoff:&lt;/strong&gt; Higher resource usage than&amp;nbsp;oCIS&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;When to Choose&amp;nbsp;ownCloud&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Enterprises wanting modern, scalable&amp;nbsp;architecture&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ideal if:&lt;/strong&gt; You prefer Go-based microservices and S3&amp;nbsp;storage&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Strength:&lt;/strong&gt; Infinite Scale is architecturally&amp;nbsp;superior&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tradeoff:&lt;/strong&gt; Smaller app&amp;nbsp;ecosystem&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Nextcloud wins for homelabbers&lt;/strong&gt; in 2026 due to its broader app ecosystem, all-in-one features (Talk, Mail, Office), and vibrant community. &lt;strong&gt;ownCloud Infinite Scale wins for enterprises&lt;/strong&gt; that need modern microservices, S3-native storage, and massive&amp;nbsp;scalability.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Try Nextcloud&lt;/strong&gt; if you want the richest feature&amp;nbsp;set: &lt;code&gt;docker run -d -p 8080:80 nextcloud&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Try ownCloud oCIS&lt;/strong&gt; if you want a lightweight modern&amp;nbsp;stack: &lt;code&gt;docker run -d -p 9200:9200 owncloud/ocis&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Hosting:&lt;/strong&gt; Hetzner, DigitalOcean,&amp;nbsp;Linode&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mini PCs:&lt;/strong&gt; Intel &lt;span class="caps"&gt;NUC&lt;/span&gt;, Minisforum,&amp;nbsp;Beelink&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Storage:&lt;/strong&gt; &lt;span class="caps"&gt;WD&lt;/span&gt; Red, Seagate IronWolf, Samsung&amp;nbsp;SSDs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Books:&lt;/strong&gt; Nextcloud Administration&amp;nbsp;Manual&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal&amp;nbsp;Linking&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;nextcloud-setup&lt;/code&gt; → &lt;code&gt;nextcloud-self-hosted.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker&lt;/code&gt; → &lt;code&gt;docker-compose-tutorial.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt; → &lt;code&gt;self-hosted-cloud-storage-nextcloud.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;security&lt;/code&gt; → &lt;code&gt;wazuh-siem-setup.md&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Which cloud suite runs your homelab?&lt;/strong&gt; Nextcloud, ownCloud, or something&amp;nbsp;else?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subscribe&lt;/strong&gt; for more self-hosted software&amp;nbsp;comparisons.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Comparisons"/><category term="nextcloud vs owncloud"/><category term="self-hosted cloud storage"/><category term="nextcloud alternative"/><category term="owncloud comparison"/><category term="homelab"/></entry><entry><title>Pi-hole Setup Guide: Block Ads Network-Wide in Your Homelab</title><link href="https://steadypub.com/2026/06/pihole-setup-guide/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T10:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/pihole-setup-guide/</id><summary type="html">&lt;p&gt;A complete guide to installing and configuring Pi-hole for network-wide ad blocking. Covers Docker deployment, &lt;span class="caps"&gt;DNS&lt;/span&gt; configuration, blocklist management, and performance&amp;nbsp;tuning.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~14 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab and self-hosting&amp;nbsp;enthusiasts&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is&amp;nbsp;Pi-hole?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Pi-hole is a network-level advertisement and internet tracker blocking application. It acts as a &lt;span class="caps"&gt;DNS&lt;/span&gt; sinkhole, intercepting &lt;span class="caps"&gt;DNS&lt;/span&gt; queries for known ad-serving domains and returning a null response before the connection ever leaves your network. Unlike browser-based blockers, Pi-hole protects every device on your network — smart TVs, IoT devices, mobile apps, and game consoles — without requiring client-side&amp;nbsp;software.&lt;/p&gt;
&lt;h3&gt;A Brief&amp;nbsp;History&lt;/h3&gt;
&lt;p&gt;Pi-hole began in 2015 as a lightweight &lt;span class="caps"&gt;DNS&lt;/span&gt; server for Raspberry Pi. It evolved from a simple shell script into a full-featured web application with a custom &lt;span class="caps"&gt;FTL&lt;/span&gt; (Faster Than Light) &lt;span class="caps"&gt;DNS&lt;/span&gt; engine. Pi-hole v5 introduced the gravity database for blocklist management. Pi-hole v6 (released in 2025) added a modern web interface, &lt;span class="caps"&gt;REST&lt;/span&gt; &lt;span class="caps"&gt;API&lt;/span&gt;, and native Docker support. It remains one of the most popular self-hosted projects in the homelab&amp;nbsp;community.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why Use Pi-hole in Your&amp;nbsp;Homelab?&lt;/h2&gt;
&lt;h3&gt;Network-Wide Ad&amp;nbsp;Blocking&lt;/h3&gt;
&lt;p&gt;Pi-hole blocks ads at the &lt;span class="caps"&gt;DNS&lt;/span&gt; level. This means every device on your &lt;span class="caps"&gt;LAN&lt;/span&gt; — including devices that cannot install browser extensions — benefits from ad blocking. Game consoles, smart TVs, and IoT devices are notoriously difficult to secure with client-side tools; Pi-hole handles them&amp;nbsp;transparently.&lt;/p&gt;
&lt;h3&gt;Improved Privacy and Reduced&amp;nbsp;Tracking&lt;/h3&gt;
&lt;p&gt;By blocking tracker domains (Google Analytics, Facebook Pixel, Amazon Alexa metrics), Pi-hole reduces the data your devices leak. This is not a replacement for a &lt;span class="caps"&gt;VPN&lt;/span&gt; or Tor, but it is a significant layer in a defense-in-depth privacy&amp;nbsp;strategy.&lt;/p&gt;
&lt;h3&gt;Faster Page Loads and Lower&amp;nbsp;Bandwidth&lt;/h3&gt;
&lt;p&gt;Ads and trackers consume bandwidth. By blocking them at the &lt;span class="caps"&gt;DNS&lt;/span&gt; level, pages load faster and use less data. On metered or slow connections (mobile tethering, satellite), this is especially&amp;nbsp;noticeable.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;h3&gt;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;A Linux server or Raspberry Pi (any model with 512 &lt;span class="caps"&gt;MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;Docker and Docker&amp;nbsp;Compose&lt;/li&gt;
&lt;li&gt;A static &lt;span class="caps"&gt;IP&lt;/span&gt; or &lt;span class="caps"&gt;DHCP&lt;/span&gt; reservation for the Pi-hole&amp;nbsp;host&lt;/li&gt;
&lt;li&gt;Port 53 (&lt;span class="caps"&gt;TCP&lt;/span&gt;/&lt;span class="caps"&gt;UDP&lt;/span&gt;) available for &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Port 80/443 for the web&amp;nbsp;interface&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Method 1: Docker Compose&amp;nbsp;(Recommended)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;pihole&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pihole/pihole:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pihole&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;53:53/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;53:53/udp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;80:80/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;443:443/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TZ=Asia/Singapore&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;WEBPASSWORD=***      - FTLCONF_LOCAL_IPV4=192.168.1.10&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./etc-pihole:/etc/pihole&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./etc-dnsmasq.d:/etc/dnsmasq.d&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;cap_add&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;NET_ADMIN&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;dns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;127.0.0.1&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1.1.1.1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Deploy:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Access the web interface&amp;nbsp;at &lt;code&gt;http://192.168.1.10/admin&lt;/code&gt;. Use the password you set&amp;nbsp;in &lt;code&gt;WEBPASSWORD&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Method 2: Bare Metal&amp;nbsp;Installation&lt;/h3&gt;
&lt;p&gt;On a Raspberry Pi or Debian&amp;nbsp;server:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Install Pi-hole&lt;/span&gt;
curl&lt;span class="w"&gt; &lt;/span&gt;-sSL&lt;span class="w"&gt; &lt;/span&gt;https://install.pi-hole.net&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;bash
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The installer walks you through interface selection, upstream &lt;span class="caps"&gt;DNS&lt;/span&gt;, and blocklist subscriptions. It is beginner-friendly but less portable than&amp;nbsp;Docker.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Basic Setup and&amp;nbsp;Configuration&lt;/h2&gt;
&lt;h3&gt;Step 1: Set Pi-hole as Your &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;Server&lt;/h3&gt;
&lt;p&gt;After installation, point your router&amp;#8217;s &lt;span class="caps"&gt;DHCP&lt;/span&gt; &lt;span class="caps"&gt;DNS&lt;/span&gt; server to Pi-hole&amp;#8217;s &lt;span class="caps"&gt;IP&lt;/span&gt;. This ensures every device on your network uses Pi-hole&amp;nbsp;automatically.&lt;/p&gt;
&lt;p&gt;If your router does not support custom &lt;span class="caps"&gt;DNS&lt;/span&gt;, configure Pi-hole as your &lt;span class="caps"&gt;DHCP&lt;/span&gt;&amp;nbsp;server:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;In the Pi-hole web &lt;span class="caps"&gt;UI&lt;/span&gt;, go to &lt;strong&gt;Settings&lt;/strong&gt; → &lt;strong&gt;&lt;span class="caps"&gt;DHCP&lt;/span&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Enable the &lt;span class="caps"&gt;DHCP&lt;/span&gt;&amp;nbsp;server&lt;/li&gt;
&lt;li&gt;Set the range (e.g., 192.168.1.100 to&amp;nbsp;192.168.1.200)&lt;/li&gt;
&lt;li&gt;Disable &lt;span class="caps"&gt;DHCP&lt;/span&gt; on your&amp;nbsp;router&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Step 2: Choose Upstream &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Pi-hole does not resolve domains itself; it forwards queries to an upstream &lt;span class="caps"&gt;DNS&lt;/span&gt; provider. Recommended&amp;nbsp;options:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;Features&lt;/th&gt;
&lt;th&gt;Privacy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cloudflare (1.1.1.1)&lt;/td&gt;
&lt;td&gt;Fast, &lt;span class="caps"&gt;DNSSEC&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Standard&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Quad9 (9.9.9.9)&lt;/td&gt;
&lt;td&gt;Malware blocking, &lt;span class="caps"&gt;DNSSEC&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AdGuard &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Ad blocking at &lt;span class="caps"&gt;DNS&lt;/span&gt; level&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NextDNS&lt;/td&gt;
&lt;td&gt;Custom filtering, analytics&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom (Unbound)&lt;/td&gt;
&lt;td&gt;Recursive, no third party&lt;/td&gt;
&lt;td&gt;Very High&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For maximum privacy, run a local Unbound recursive resolver alongside Pi-hole. This eliminates the upstream provider&amp;nbsp;entirely.&lt;/p&gt;
&lt;h3&gt;Step 3: Subscribe to&amp;nbsp;Blocklists&lt;/h3&gt;
&lt;p&gt;Pi-hole ships with a default blocklist (StevenBlack). You can add more in &lt;strong&gt;Group Management&lt;/strong&gt; → &lt;strong&gt;Adlists&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;https://mirror1.malwaredomains.com/files/justdomains&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;https://sysctl.org/camo/b.txt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;https://someonewhocares.org/hosts/zero/hosts&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;https://raw.githubusercontent.com/anudeepND/blacklist/master/adservers.txt&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Click &lt;strong&gt;Update Gravity&lt;/strong&gt; after adding lists. Be careful: too many lists slow down &lt;span class="caps"&gt;DNS&lt;/span&gt; and cause false&amp;nbsp;positives.&lt;/p&gt;
&lt;h3&gt;Step 4: Configure Whitelist and&amp;nbsp;Regex&lt;/h3&gt;
&lt;p&gt;Some sites break when aggressive blocklists are enabled. Whitelist domains in &lt;strong&gt;Whitelist&lt;/strong&gt; → &lt;strong&gt;Add to Whitelist&lt;/strong&gt;. Use regex for wildcard&amp;nbsp;rules:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Block&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;all&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;click&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;TLD&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;\&lt;span class="o"&gt;.|^&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;click&lt;/span&gt;&lt;span class="p"&gt;$&lt;/span&gt;

&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Block&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;specific&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;subdomains&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;\&lt;span class="o"&gt;.|^&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;telemetry&lt;/span&gt;\&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Advanced&amp;nbsp;Features&lt;/h2&gt;
&lt;h3&gt;Local &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;Records&lt;/h3&gt;
&lt;p&gt;Pi-hole can act as a local &lt;span class="caps"&gt;DNS&lt;/span&gt; server for your homelab. Add entries in &lt;strong&gt;Local &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/strong&gt; → &lt;strong&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt; Records&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="mf"&gt;192.168.1.10&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;nas&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="n"&gt;local&lt;/span&gt;
&lt;span class="mf"&gt;192.168.1.20&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;plex&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="n"&gt;local&lt;/span&gt;
&lt;span class="mf"&gt;192.168.1.30&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kr"&gt;next&lt;/span&gt;&lt;span class="n"&gt;cloud&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="n"&gt;local&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This gives you human-friendly names for internal services without running a separate &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;server.&lt;/p&gt;
&lt;h3&gt;Conditional&amp;nbsp;Forwarding&lt;/h3&gt;
&lt;p&gt;If you have an Active Directory or corporate domain, use conditional forwarding to send specific domain queries to a different &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;server:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;Domain&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;corp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;local&lt;/span&gt;
&lt;span class="n"&gt;Server&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;192.168&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;1.5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This keeps internal resolution working while still blocking ads on the public&amp;nbsp;internet.&lt;/p&gt;
&lt;h3&gt;Pi-hole as a Recursive Resolver with&amp;nbsp;Unbound&lt;/h3&gt;
&lt;p&gt;For a no-third-party &lt;span class="caps"&gt;DNS&lt;/span&gt; setup, install Unbound alongside&amp;nbsp;Pi-hole:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;unbound
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Create &lt;code&gt;/etc/unbound/unbound.conf.d/pi-hole.conf&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;verbosity&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;interface&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;127.0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5335&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ip4&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;yes&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ip6&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;yes&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;udp&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;yes&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;yes&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;harden&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;glue&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;yes&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;harden&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dnssec&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;stripped&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;yes&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;use&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;caps&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;yes&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;edns&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1232&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;prefetch&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;yes&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;threads&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;so&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;rcvbuf&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;so&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;sndbuf&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;private&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;192.168&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;private&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;169.254&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;private&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;172.16&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;private&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;10.0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;private&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fd00&lt;/span&gt;&lt;span class="o"&gt;::/&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;private&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fe80&lt;/span&gt;&lt;span class="o"&gt;::/&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In Pi-hole, set the upstream &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;to &lt;code&gt;127.0.0.1#5335&lt;/code&gt; (Custom&amp;nbsp;1).&lt;/p&gt;
&lt;h3&gt;Query Logging and Long-Term&amp;nbsp;Data&lt;/h3&gt;
&lt;p&gt;Pi-hole logs all queries. The Long-Term Data page shows top queried domains, top clients, and blocked query trends. Use this to tune your blocklists or identify misbehaving devices. Privacy Note: disable query logging if you have privacy-sensitive&amp;nbsp;users.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Integrating with Your&amp;nbsp;Homelab&lt;/h2&gt;
&lt;h3&gt;&lt;span class="caps"&gt;VPN&lt;/span&gt; Integration (WireGuard /&amp;nbsp;Tailscale)&lt;/h3&gt;
&lt;p&gt;If you run a &lt;span class="caps"&gt;VPN&lt;/span&gt;, set the &lt;span class="caps"&gt;VPN&lt;/span&gt;&amp;#8217;s &lt;span class="caps"&gt;DNS&lt;/span&gt; to Pi-hole. This blocks ads for mobile devices even when they are off the home network. In WireGuard,&amp;nbsp;set &lt;code&gt;DNS = 192.168.1.10&lt;/code&gt; in the client config. In Tailscale, set a &lt;span class="caps"&gt;DNS&lt;/span&gt; override in the admin&amp;nbsp;panel.&lt;/p&gt;
&lt;h3&gt;Failover with Keepalived or &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;Redundancy&lt;/h3&gt;
&lt;p&gt;For a redundant setup, run two Pi-hole instances (e.g., on two Raspberry Pis). Use Keepalived for a floating &lt;span class="caps"&gt;VIP&lt;/span&gt;, or configure your router to hand out both &lt;span class="caps"&gt;DNS&lt;/span&gt; servers. If one fails, clients fall back to the&amp;nbsp;other.&lt;/p&gt;
&lt;h3&gt;Monitoring with&amp;nbsp;Prometheus&lt;/h3&gt;
&lt;p&gt;Pi-hole v6 exposes a &lt;span class="caps"&gt;REST&lt;/span&gt; &lt;span class="caps"&gt;API&lt;/span&gt;. Use a Prometheus exporter to scrape&amp;nbsp;statistics:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;pihole-exporter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ekofr/pihole-exporter:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;PIHOLE_HOSTNAME=pihole&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;PIHOLE_API_TOKEN=***    ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;9617:9617&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Visualize queries, blocked percentage, and top clients in&amp;nbsp;Grafana.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Alternatives to&amp;nbsp;Consider&lt;/h2&gt;
&lt;h3&gt;AdGuard&amp;nbsp;Home&lt;/h3&gt;
&lt;p&gt;AdGuard Home is a modern &lt;span class="caps"&gt;DNS&lt;/span&gt; sinkhole with a polished &lt;span class="caps"&gt;UI&lt;/span&gt;, &lt;span class="caps"&gt;HTTPS&lt;/span&gt; filtering, and parental controls. It supports DoH/DoT (&lt;span class="caps"&gt;DNS&lt;/span&gt; over &lt;span class="caps"&gt;HTTPS&lt;/span&gt;/&lt;span class="caps"&gt;TLS&lt;/span&gt;) out of the box. See our &lt;a href="https://steadypub.com/2026/06/adguard-home-vs-pihole-2026/"&gt;AdGuard Home vs Pi-hole comparison&lt;/a&gt; for a full&amp;nbsp;breakdown.&lt;/p&gt;
&lt;h3&gt;Technitium &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Technitium is a full &lt;span class="caps"&gt;DNS&lt;/span&gt; server (not just a sinkhole) with built-in ad blocking, &lt;span class="caps"&gt;DNSSEC&lt;/span&gt;, and DoH/DoT. It is more powerful but more complex than Pi-hole. Use it if you need authoritative &lt;span class="caps"&gt;DNS&lt;/span&gt; or split-horizon&amp;nbsp;resolution.&lt;/p&gt;
&lt;h3&gt;NextDNS&lt;/h3&gt;
&lt;p&gt;NextDNS is a cloud-based &lt;span class="caps"&gt;DNS&lt;/span&gt; filtering service. It offers the same blocking as Pi-hole but requires no hardware. The tradeoff is privacy (your &lt;span class="caps"&gt;DNS&lt;/span&gt; queries go to a third party) and cost (free tier has a query limit). Good for travelers or users who cannot&amp;nbsp;self-host.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;Setup&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Pi-hole&lt;/td&gt;
&lt;td&gt;Homelab, full control&lt;/td&gt;
&lt;td&gt;Self-hosted&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AdGuard Home&lt;/td&gt;
&lt;td&gt;Modern &lt;span class="caps"&gt;UI&lt;/span&gt;, DoH/DoT&lt;/td&gt;
&lt;td&gt;Self-hosted&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Technitium&lt;/td&gt;
&lt;td&gt;Authoritative &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Self-hosted&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NextDNS&lt;/td&gt;
&lt;td&gt;No hardware, mobile&lt;/td&gt;
&lt;td&gt;Cloud&lt;/td&gt;
&lt;td&gt;Free tier / Pro&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Frequently Asked&amp;nbsp;Questions&lt;/h2&gt;
&lt;h3&gt;Does Pi-hole block YouTube&amp;nbsp;ads?&lt;/h3&gt;
&lt;p&gt;Partially. Pi-hole blocks &lt;span class="caps"&gt;DNS&lt;/span&gt;-level YouTube ad domains, but YouTube increasingly serves ads from the same domains as content. For complete YouTube blocking, combine Pi-hole with a browser extension like uBlock&amp;nbsp;Origin.&lt;/p&gt;
&lt;h3&gt;Why do some sites break after installing&amp;nbsp;Pi-hole?&lt;/h3&gt;
&lt;p&gt;Aggressive blocklists sometimes block domains required for functionality (e.g., &lt;span class="caps"&gt;CDN&lt;/span&gt; scripts, analytics required for page rendering). Use the &lt;strong&gt;Query Log&lt;/strong&gt; to identify blocked domains, then whitelist&amp;nbsp;them.&lt;/p&gt;
&lt;h3&gt;Can I run Pi-hole on a &lt;span class="caps"&gt;VPS&lt;/span&gt;?&lt;/h3&gt;
&lt;p&gt;Yes, but it only blocks ads for devices using that &lt;span class="caps"&gt;VPS&lt;/span&gt; as their &lt;span class="caps"&gt;DNS&lt;/span&gt; server. For personal use, a &lt;span class="caps"&gt;VPN&lt;/span&gt; + Pi-hole &lt;span class="caps"&gt;VPS&lt;/span&gt; setup is common. For a household, run Pi-hole on your local&amp;nbsp;network.&lt;/p&gt;
&lt;h3&gt;How do I update&amp;nbsp;Pi-hole?&lt;/h3&gt;
&lt;p&gt;For Docker: pull the latest image and recreate. For bare metal:&amp;nbsp;run &lt;code&gt;pihole -up&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Pi-hole is the foundational privacy tool for any homelab. It blocks ads, trackers, and malware at the &lt;span class="caps"&gt;DNS&lt;/span&gt; level, protecting every device on your network without client-side configuration. With Docker, it deploys in minutes. With custom blocklists, local &lt;span class="caps"&gt;DNS&lt;/span&gt;, and Unbound recursion, it becomes a powerful network infrastructure&amp;nbsp;component.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Deploy Pi-hole and set it as your router&amp;#8217;s &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Add curated blocklists and test for false&amp;nbsp;positives&lt;/li&gt;
&lt;li&gt;Install Unbound for recursive, third-party-free &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Monitor query statistics with&amp;nbsp;Grafana&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;installation&lt;/strong&gt;: hardware — Raspberry Pi kits, mini PCs for Pi-hole&amp;nbsp;hosting&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;integration&lt;/strong&gt;: tool — &lt;span class="caps"&gt;VPN&lt;/span&gt; services (Mullvad, ProtonVPN) for remote &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;alternatives&lt;/strong&gt;: tool — AdGuard Home or NextDNS&amp;nbsp;subscriptions&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;installation&lt;/code&gt; → setup_guide: &lt;a href="https://steadypub.com/2026/06/docker-compose-for-beginners/"&gt;Docker Compose for&amp;nbsp;beginners&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;integration&lt;/code&gt; → related_guide: &lt;a href="https://steadypub.com/2026/06/adguard-home-vs-pihole-2026/"&gt;AdGuard Home vs Pi-hole&amp;nbsp;comparison&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;alternatives&lt;/code&gt; → comparison: &lt;a href="https://steadypub.com/2026/06/dns-filtering-homelab/"&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt; filtering in the&amp;nbsp;homelab&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] What blocklists do you use with Pi-hole? Share your&amp;nbsp;configuration.&lt;/li&gt;
&lt;li&gt;[newsletter] Get weekly homelab networking and privacy&amp;nbsp;guides.&lt;/li&gt;
&lt;li&gt;[internal_link] Next: learn how to &lt;a href="https://steadypub.com/2026/06/adguard-home-setup/"&gt;set up AdGuard Home as an&amp;nbsp;alternative&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Networking"/><category term="pihole"/><category term="dns"/><category term="ad blocking"/><category term="homelab"/><category term="docker"/><category term="networking"/></entry><entry><title>Pi-hole vs AdGuard Home: Which DNS Ad Blocker Is Right for Your Homelab?</title><link href="https://steadypub.com/2026/06/pihole-vs-adguard-home/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T10:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/pihole-vs-adguard-home/</id><summary type="html">&lt;p&gt;Pi-hole and AdGuard Home are the two leading self-hosted &lt;span class="caps"&gt;DNS&lt;/span&gt; ad blockers. Compare setup, performance, features, and filtering to pick the best for your&amp;nbsp;network.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~10 minutes&lt;br&gt;
&lt;strong&gt;Audience:&lt;/strong&gt; Homelabbers choosing a &lt;span class="caps"&gt;DNS&lt;/span&gt; ad blocker for their&amp;nbsp;network&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is &lt;span class="caps"&gt;DNS&lt;/span&gt; Ad&amp;nbsp;Blocking?&lt;/h2&gt;
&lt;p&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt; ad blockers work at the network level by intercepting &lt;span class="caps"&gt;DNS&lt;/span&gt; queries and&amp;nbsp;returning &lt;code&gt;0.0.0.0&lt;/code&gt; for known ad/tracking domains. This blocks ads across all devices — phones, TVs, IoT devices — without installing software on each&amp;nbsp;device.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Advantage&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Network-wide&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;One setup covers all devices&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Device-agnostic&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Works on smart TVs, IoT, phones&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Low resource&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt; queries are tiny&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Battery-friendly&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No &lt;span class="caps"&gt;CPU&lt;/span&gt; impact on clients&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Malware blocking&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Block known malicious domains&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Pi-hole&amp;nbsp;Overview&lt;/h2&gt;
&lt;h3&gt;History &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;Philosophy&lt;/h3&gt;
&lt;p&gt;Pi-hole started in 2015 as a Raspberry Pi project and grew into the dominant &lt;span class="caps"&gt;DNS&lt;/span&gt; ad blocker. It&amp;nbsp;is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Open-source&lt;/strong&gt; (&lt;span class="caps"&gt;EUPL&lt;/span&gt;&amp;nbsp;v1.2)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Community-driven&lt;/strong&gt; (massive Reddit r/pihole&amp;nbsp;community)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lightweight&lt;/strong&gt; (runs on Pi Zero, routers,&amp;nbsp;containers)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mature&lt;/strong&gt; (10+ years of&amp;nbsp;development)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Key&amp;nbsp;Features&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Pi-hole&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Blocklists&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;100+ community lists, 10+ built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Per-client stats&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Full query logging by device&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Whitelist/blacklist&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Regex + exact match&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;DHCP&lt;/span&gt; server&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Optional built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Local &lt;span class="caps"&gt;DNS&lt;/span&gt; records&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Custom &lt;span class="caps"&gt;DNS&lt;/span&gt; entries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;API&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;REST&lt;/span&gt; &lt;span class="caps"&gt;API&lt;/span&gt; (v6)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Web &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Clean, dashboard-focused&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Conditional forwarding&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Forward local queries to router&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Gravity &lt;span class="caps"&gt;DB&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Optimized blocklist storage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Query logging&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;24h/7d/30d/365d retention&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pi-hole v6 Changes&amp;nbsp;(2025)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Embedded web server:&lt;/strong&gt; No more Lighttpd&amp;nbsp;dependency&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;FTL&lt;/span&gt; v6:&lt;/strong&gt; C-based &lt;span class="caps"&gt;DNS&lt;/span&gt; server replacing&amp;nbsp;dnsmasq&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;TOML&lt;/span&gt; config:&lt;/strong&gt; Modern configuration&amp;nbsp;format&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;New &lt;span class="caps"&gt;API&lt;/span&gt;:&lt;/strong&gt; RESTful &lt;span class="caps"&gt;API&lt;/span&gt; with OpenAPI&amp;nbsp;spec&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Improved regex:&lt;/strong&gt; Faster pattern&amp;nbsp;matching&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;AdGuard Home&amp;nbsp;Overview&lt;/h2&gt;
&lt;h3&gt;History &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;Philosophy&lt;/h3&gt;
&lt;p&gt;AdGuard Home is developed by AdGuard Software Ltd (commercial ad blocker vendor). It&amp;nbsp;is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Open-source&lt;/strong&gt; (&lt;span class="caps"&gt;GPL&lt;/span&gt;&amp;nbsp;v3)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Company-backed&lt;/strong&gt; (faster releases, enterprise&amp;nbsp;features)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Feature-rich&lt;/strong&gt; (parental controls, Safe Search,&amp;nbsp;statistics)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modern &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/strong&gt; (more polished than&amp;nbsp;Pi-hole)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Key&amp;nbsp;Features&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;AdGuard Home&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Blocklists&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;AdGuard filter lists + custom&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Per-client stats&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Detailed query stats + runtime&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Parental controls&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Adult content filtering, safe search&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Browsing security&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Phishing/malware protection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt;-over-&lt;span class="caps"&gt;HTTPS&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Native DoH/DoT/DoQ support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt; rewrites&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Custom &lt;span class="caps"&gt;DNS&lt;/span&gt; records&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Query logging&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Configurable retention&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;API&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;REST&lt;/span&gt; &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Web &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Modern, dark mode&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;DDNS&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Dynamic &lt;span class="caps"&gt;DNS&lt;/span&gt; support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Client settings&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Per-client filtering profiles&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Statistics&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Counters, graphs, top domains&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Feature&amp;nbsp;Comparison&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Pi-hole&lt;/th&gt;
&lt;th&gt;AdGuard Home&lt;/th&gt;
&lt;th&gt;Winner&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Setup ease&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Easy (Docker: 1 command)&lt;/td&gt;
&lt;td&gt;Easy (Docker: 1 command)&lt;/td&gt;
&lt;td&gt;Tie&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Web &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Clean, functional&lt;/td&gt;
&lt;td&gt;Modern, polished&lt;/td&gt;
&lt;td&gt;AdGuard Home&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Memory usage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~&lt;span class="caps"&gt;100MB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;~&lt;span class="caps"&gt;80MB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;AdGuard Home&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Query speed&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~1ms&lt;/td&gt;
&lt;td&gt;~1ms&lt;/td&gt;
&lt;td&gt;Tie&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Blocklist count&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Unlimited&lt;/td&gt;
&lt;td&gt;Unlimited&lt;/td&gt;
&lt;td&gt;Tie&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Default blocking&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;td&gt;Tie&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Parental controls&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Basic (via regex)&lt;/td&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;td&gt;AdGuard Home&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Safe Search&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual&lt;/td&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;td&gt;AdGuard Home&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DoH/DoT&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Via Unbound/cloudflared&lt;/td&gt;
&lt;td&gt;Native&lt;/td&gt;
&lt;td&gt;AdGuard Home&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Per-client rules&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Groups&lt;/td&gt;
&lt;td&gt;Profiles&lt;/td&gt;
&lt;td&gt;AdGuard Home&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Community size&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Massive (r/pihole: 200K+)&lt;/td&gt;
&lt;td&gt;Moderate (r/AdGuard: 30K+)&lt;/td&gt;
&lt;td&gt;Pi-hole&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Documentation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Extensive&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;td&gt;Pi-hole&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Updates&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Quarterly major&lt;/td&gt;
&lt;td&gt;Monthly&lt;/td&gt;
&lt;td&gt;AdGuard Home&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Stability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Very stable&lt;/td&gt;
&lt;td&gt;Stable&lt;/td&gt;
&lt;td&gt;Pi-hole&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Config format&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;TOML&lt;/span&gt; (v6)&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;YAML&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Tie&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Add-on ecosystem&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Pi-hole + Unbound, cloudflared&lt;/td&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;td&gt;Tie&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Docker&amp;nbsp;Deployment&lt;/h2&gt;
&lt;h3&gt;Pi-hole Docker&amp;nbsp;Compose&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;pihole&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pihole/pihole:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pihole&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;53:53/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;53:53/udp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;80:80/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TZ=Asia/Singapore&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;WEBPASSWORD=admin123&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./pihole/etc-pihole:/etc/pihole&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./pihole/etc-dnsmasq.d:/etc/dnsmasq.d&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;AdGuard Home Docker&amp;nbsp;Compose&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;adguardhome&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;adguard/adguardhome:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;adguardhome&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;53:53/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;53:53/udp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;80:80/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3000:3000/tcp&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./adguard/work:/opt/adguardhome/work&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./adguard/conf:/opt/adguardhome/conf&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Performance&amp;nbsp;Benchmarks&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test&lt;/th&gt;
&lt;th&gt;Pi-hole v6&lt;/th&gt;
&lt;th&gt;AdGuard Home&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cold start&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2s&lt;/td&gt;
&lt;td&gt;3s&lt;/td&gt;
&lt;td&gt;Pi-hole v6 embedded server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Query latency (cached)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.3ms&lt;/td&gt;
&lt;td&gt;0.4ms&lt;/td&gt;
&lt;td&gt;Both extremely fast&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Query latency (uncached)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;15ms&lt;/td&gt;
&lt;td&gt;18ms&lt;/td&gt;
&lt;td&gt;Depends on upstream&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Memory (1M blocklist)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;85MB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;72MB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;AdGuard slightly leaner&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt; (1K qps)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;3%&lt;/td&gt;
&lt;td&gt;3%&lt;/td&gt;
&lt;td&gt;Negligible on modern hardware&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Blocklist reload&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;5s&lt;/td&gt;
&lt;td&gt;8s&lt;/td&gt;
&lt;td&gt;Pi-hole Gravity is faster&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;When to Choose&amp;nbsp;Pi-hole&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Tinkerers who want full control and massive community&amp;nbsp;support&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ideal if:&lt;/strong&gt; You want to run alongside Unbound (recursive &lt;span class="caps"&gt;DNS&lt;/span&gt;) or complex &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;setups&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Strength:&lt;/strong&gt; 10-year track record, enormous community, rock-solid&amp;nbsp;stability&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tradeoff:&lt;/strong&gt; Simpler &lt;span class="caps"&gt;UI&lt;/span&gt;, fewer enterprise&amp;nbsp;features&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;When to Choose AdGuard&amp;nbsp;Home&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Users wanting parental controls and modern features&amp;nbsp;out-of-the-box&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ideal if:&lt;/strong&gt; You need Safe Search, adult filtering, or per-client&amp;nbsp;profiles&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Strength:&lt;/strong&gt; Feature-rich, modern &lt;span class="caps"&gt;UI&lt;/span&gt;, native&amp;nbsp;DoH/DoT&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tradeoff:&lt;/strong&gt; Smaller community, newer&amp;nbsp;project&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Dual-&lt;span class="caps"&gt;DNS&lt;/span&gt; Strategy&amp;nbsp;(Advanced)&lt;/h2&gt;
&lt;p&gt;Many homelabbers run &lt;strong&gt;both&lt;/strong&gt; Pi-hole and AdGuard Home for&amp;nbsp;redundancy:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Router DNS → Primary: Pi-hole (192.168.1.2)
         → Secondary: AdGuard Home (192.168.1.3)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This provides:
- &lt;strong&gt;Failover:&lt;/strong&gt; If one fails, the other handles queries
- &lt;strong&gt;Redundancy:&lt;/strong&gt; Both can block different lists
- &lt;strong&gt;Testing:&lt;/strong&gt; A/B test blocklists without disrupting the&amp;nbsp;network&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Pi-hole&lt;/strong&gt; is the tried-and-true choice for pure ad blocking with unmatched community support. &lt;strong&gt;AdGuard Home&lt;/strong&gt; wins if you need parental controls, Safe Search, or a modern &lt;span class="caps"&gt;UI&lt;/span&gt; with per-client&amp;nbsp;profiles.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Try&amp;nbsp;Pi-hole:&lt;/strong&gt; &lt;code&gt;docker run -d -p 53:53/tcp -p 53:53/udp -p 80:80 pihole/pihole&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Try AdGuard&amp;nbsp;Home:&lt;/strong&gt; &lt;code&gt;docker run -d -p 53:53/tcp -p 53:53/udp -p 80:80 -p 3000:3000 adguard/adguardhome&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Raspberry Pi:&lt;/strong&gt; Pi 4, Pi 5 for&amp;nbsp;Pi-hole&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mini PCs:&lt;/strong&gt; Intel N100 for 24/7 &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;server&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Routers:&lt;/strong&gt; &lt;span class="caps"&gt;ASUSWRT&lt;/span&gt;-Merlin, OpenWRT for local &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Networking:&lt;/strong&gt; UniFi, &lt;span class="caps"&gt;TP&lt;/span&gt;-Link&amp;nbsp;Omada&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal&amp;nbsp;Linking&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;pihole-setup&lt;/code&gt; → &lt;code&gt;pihole-setup-guide.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;adguard&lt;/code&gt; → &lt;code&gt;adguard-home-docker.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dns&lt;/code&gt; → &lt;code&gt;pihole-unbound-dns.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;networking&lt;/code&gt; → &lt;code&gt;homelab-networking-basics.md&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Which &lt;span class="caps"&gt;DNS&lt;/span&gt; blocker runs your network?&lt;/strong&gt; Pi-hole, AdGuard Home, or&amp;nbsp;both?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subscribe&lt;/strong&gt; for homelab networking and security&amp;nbsp;guides.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Comparisons"/><category term="pihole vs adguard home"/><category term="dns ad blocker"/><category term="network-wide ad blocking"/><category term="self-hosted dns"/><category term="homelab security"/></entry><entry><title>Portainer Docker Management: The Ultimate Self-Hosted Guide for 2026</title><link href="https://steadypub.com/2026/06/portainer-docker-management/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T10:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/portainer-docker-management/</id><summary type="html">&lt;p&gt;A complete guide to installing, configuring, and mastering Portainer for Docker container management in your homelab. Covers &lt;span class="caps"&gt;CE&lt;/span&gt; vs &lt;span class="caps"&gt;BE&lt;/span&gt;, stacks, secrets, and real-world&amp;nbsp;workflows.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~15 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab and self-hosting&amp;nbsp;enthusiasts&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is&amp;nbsp;Portainer?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Portainer is a lightweight, open-source web &lt;span class="caps"&gt;UI&lt;/span&gt; for managing Docker, Docker Swarm, and Kubernetes environments. It wraps the Docker &lt;span class="caps"&gt;CLI&lt;/span&gt; into an intuitive dashboard where you can deploy containers, manage images, configure networks, and orchestrate stacks without memorizing hundreds of command-line flags. For homelab operators, Portainer transforms a terminal-heavy workflow into a visual, click-driven experience that reduces errors and speeds up&amp;nbsp;iteration.&lt;/p&gt;
&lt;h3&gt;A Brief&amp;nbsp;History&lt;/h3&gt;
&lt;p&gt;Portainer was first released in 2016 as a response to the growing complexity of Docker adoption. Early versions targeted simple container lifecycle management. Over time, it expanded to support Docker Swarm, Kubernetes, edge agent deployments, and role-based access control (&lt;span class="caps"&gt;RBAC&lt;/span&gt;). The project split into two editions: &lt;strong&gt;Portainer Community Edition (&lt;span class="caps"&gt;CE&lt;/span&gt;)&lt;/strong&gt; — fully open-source and free — and &lt;strong&gt;Portainer Business Edition (&lt;span class="caps"&gt;BE&lt;/span&gt;)&lt;/strong&gt; — which adds &lt;span class="caps"&gt;RBAC&lt;/span&gt;, registry management, and GitOps &lt;span class="caps"&gt;CI&lt;/span&gt;/&lt;span class="caps"&gt;CD&lt;/span&gt; integrations. The &lt;span class="caps"&gt;CE&lt;/span&gt; edition remains more than sufficient for typical homelab&amp;nbsp;workloads.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why Use Portainer in Your&amp;nbsp;Homelab?&lt;/h2&gt;
&lt;h3&gt;Visual Container Lifecycle&amp;nbsp;Management&lt;/h3&gt;
&lt;p&gt;Instead of&amp;nbsp;chaining &lt;code&gt;docker run&lt;/code&gt;, &lt;code&gt;docker ps&lt;/code&gt;,&amp;nbsp;and &lt;code&gt;docker exec&lt;/code&gt; commands, Portainer provides a single dashboard to start, stop, restart, inspect, and delete containers. Logs are streamed in real-time, and resource usage (&lt;span class="caps"&gt;CPU&lt;/span&gt;, memory, network I/O) is graphed live. This visibility is critical when troubleshooting a misbehaving service at 2 &lt;span class="caps"&gt;AM&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;Docker Compose Stack&amp;nbsp;Deployment&lt;/h3&gt;
&lt;p&gt;Portainer natively supports Docker Compose (referred to as &amp;#8220;Stacks&amp;#8221; in the &lt;span class="caps"&gt;UI&lt;/span&gt;). You can paste&amp;nbsp;a &lt;code&gt;docker-compose.yml&lt;/code&gt; directly into the web editor, set environment variables, and deploy the entire stack with one click. Stacks can be updated, rolled back, or deleted as a unit. This is ideal for homelab applications like Nextcloud, Immich, or monitoring suites that require multiple linked&amp;nbsp;containers.&lt;/p&gt;
&lt;h3&gt;Multi-Environment and Edge Agent&amp;nbsp;Support&lt;/h3&gt;
&lt;p&gt;Portainer can manage multiple Docker hosts from a single interface. You can install the Portainer Server on your primary homelab server and connect other nodes — a Raspberry Pi, a &lt;span class="caps"&gt;VPS&lt;/span&gt;, or a secondary &lt;span class="caps"&gt;NAS&lt;/span&gt; — via the Portainer Agent. This centralizes management without exposing every host&amp;#8217;s Docker socket to the&amp;nbsp;internet.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;h3&gt;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;A Linux server (Ubuntu 22.04/24.04, Debian 12, or AlmaLinux 9&amp;nbsp;recommended)&lt;/li&gt;
&lt;li&gt;Docker Engine installed (20.10.x or&amp;nbsp;newer)&lt;/li&gt;
&lt;li&gt;Docker Compose plugin&amp;nbsp;(v2.x)&lt;/li&gt;
&lt;li&gt;At least 512 &lt;span class="caps"&gt;MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; and 1 vCPU for the Portainer&amp;nbsp;container&lt;/li&gt;
&lt;li&gt;Port 9000 (or 9443 for &lt;span class="caps"&gt;HTTPS&lt;/span&gt;) available on the&amp;nbsp;host&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Method 1: Docker &lt;span class="caps"&gt;CLI&lt;/span&gt;&amp;nbsp;Installation&lt;/h3&gt;
&lt;p&gt;Portainer is itself a Docker container. The standard deployment creates a persistent volume for its internal database and mounts the Docker socket so it can manage the&amp;nbsp;host.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Create a persistent volume for Portainer data&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;volume&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;portainer_data

&lt;span class="c1"&gt;# Run Portainer CE&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8000&lt;/span&gt;:8000&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9000&lt;/span&gt;:9000&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9443&lt;/span&gt;:9443&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;portainer&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--restart&lt;span class="o"&gt;=&lt;/span&gt;always&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;/var/run/docker.sock:/var/run/docker.sock&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;portainer_data:/data&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;portainer/portainer-ce:latest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After running the command, access Portainer&amp;nbsp;at &lt;code&gt;http://your-server-ip:9000&lt;/code&gt;. On first launch, you will set an admin&amp;nbsp;password.&lt;/p&gt;
&lt;h3&gt;Method 2: Docker Compose&amp;nbsp;Installation&lt;/h3&gt;
&lt;p&gt;For homelab environments where you already manage everything via Compose, deploying Portainer as a stack is&amp;nbsp;cleaner.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;portainer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;portainer/portainer-ce:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;portainer&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8000:8000&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;9000:9000&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;9443:9443&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/var/run/docker.sock:/var/run/docker.sock&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;portainer_data:/data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;-H unix:///var/run/docker.sock&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;portainer_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Deploy&amp;nbsp;with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Basic Setup and&amp;nbsp;Configuration&lt;/h2&gt;
&lt;h3&gt;Step 1: Initial Admin&amp;nbsp;Setup&lt;/h3&gt;
&lt;p&gt;Navigate&amp;nbsp;to &lt;code&gt;http://your-server-ip:9000&lt;/code&gt;. Create the initial admin user. If you forget to do this within the first few minutes, Portainer may lock the setup endpoint; restart the container if that&amp;nbsp;happens.&lt;/p&gt;
&lt;h3&gt;Step 2: Connect the Local&amp;nbsp;Environment&lt;/h3&gt;
&lt;p&gt;Portainer automatically detects the local Docker environment via the mounted socket. In the &lt;span class="caps"&gt;UI&lt;/span&gt;, go to &lt;strong&gt;Environments&lt;/strong&gt; → &lt;strong&gt;Local&lt;/strong&gt; and confirm it is active. If you see &amp;#8220;Up,&amp;#8221; the connection is&amp;nbsp;healthy.&lt;/p&gt;
&lt;h3&gt;Step 3: Deploy Your First&amp;nbsp;Container&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Click &lt;strong&gt;Containers&lt;/strong&gt; → &lt;strong&gt;Add&amp;nbsp;container&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Name&amp;nbsp;it &lt;code&gt;hello-nginx&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Image: &lt;code&gt;nginx:latest&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Publish a port:&amp;nbsp;host &lt;code&gt;8080&lt;/code&gt; →&amp;nbsp;container &lt;code&gt;80&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Deploy the&amp;nbsp;container&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Verify&amp;nbsp;at &lt;code&gt;http://your-server-ip:8080&lt;/code&gt;. You should see the Nginx welcome&amp;nbsp;page.&lt;/p&gt;
&lt;h3&gt;Step 4: Deploy a Stack (Docker&amp;nbsp;Compose)&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Navigate to &lt;strong&gt;Stacks&lt;/strong&gt; → &lt;strong&gt;Add&amp;nbsp;stack&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Name&amp;nbsp;it &lt;code&gt;homelab-monitoring&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Paste a Compose file (e.g., Grafana +&amp;nbsp;Prometheus)&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Deploy the&amp;nbsp;stack&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Portainer will parse the &lt;span class="caps"&gt;YAML&lt;/span&gt;, pull images, and start containers. You can edit the stack later and click &lt;strong&gt;Update the stack&lt;/strong&gt; to&amp;nbsp;redeploy.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Advanced&amp;nbsp;Features&lt;/h2&gt;
&lt;h3&gt;Role-Based Access Control (&lt;span class="caps"&gt;BE&lt;/span&gt;) and User&amp;nbsp;Management&lt;/h3&gt;
&lt;p&gt;While &lt;span class="caps"&gt;CE&lt;/span&gt; has a simple user system, &lt;span class="caps"&gt;BE&lt;/span&gt; offers granular &lt;span class="caps"&gt;RBAC&lt;/span&gt;. In a shared homelab or family setup, you can give users read-only access to specific containers or restrict them to a single stack. This is useful if you want to let friends deploy their own services without touching your core&amp;nbsp;infrastructure.&lt;/p&gt;
&lt;h3&gt;Registry and GitHub/GitLab&amp;nbsp;Integration&lt;/h3&gt;
&lt;p&gt;Portainer can authenticate to Docker Hub, private registries (Harbor, &lt;span class="caps"&gt;GHCR&lt;/span&gt;), and Git repositories. You can link a Git repo containing Compose files and enable polling or webhook redeployment. This turns your homelab into a lightweight GitOps pipeline — push to Git, and Portainer automatically updates the&amp;nbsp;stack.&lt;/p&gt;
&lt;h3&gt;Secrets and&amp;nbsp;ConfigMaps&lt;/h3&gt;
&lt;p&gt;Portainer supports Docker secrets and configs. You can create a secret (e.g., database password) in the &lt;span class="caps"&gt;UI&lt;/span&gt; and mount it into a container at runtime. This avoids hardcoding credentials in Compose files or environment variables. For homelab operators, this is a significant security&amp;nbsp;upgrade.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Create a secret via Docker CLI (reflected in Portainer)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;my-secret-password&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;secret&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;db_password&lt;span class="w"&gt; &lt;/span&gt;-
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Edge Agent&amp;nbsp;Deployment&lt;/h3&gt;
&lt;p&gt;For remote hosts (a &lt;span class="caps"&gt;VPS&lt;/span&gt;, parents&amp;#8217; house, second site), install the Portainer Edge Agent. It connects back to your main Portainer Server over &lt;span class="caps"&gt;HTTPS&lt;/span&gt;, requiring no inbound firewall rules on the remote site. The agent is a single&amp;nbsp;container:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9001&lt;/span&gt;:9001&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;portainer_edge_agent&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--restart&lt;span class="o"&gt;=&lt;/span&gt;always&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;/var/run/docker.sock:/var/run/docker.sock&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;/var/lib/docker/volumes:/var/lib/docker/volumes&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;EDGE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;EDGE_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-edge-id&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;EDGE_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-edge-key&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;EDGE_INSECURE_POLL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;portainer/agent:latest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Integrating with Your&amp;nbsp;Homelab&lt;/h2&gt;
&lt;h3&gt;Monitoring&amp;nbsp;Integration&lt;/h3&gt;
&lt;p&gt;Portainer exposes its own metrics on port 9000/metrics. You can scrape this with Prometheus and visualize container events in Grafana. This complements your existing node and container&amp;nbsp;metrics.&lt;/p&gt;
&lt;h3&gt;Reverse Proxy&amp;nbsp;Setup&lt;/h3&gt;
&lt;p&gt;Do not expose Portainer directly to the internet. Place it behind a reverse proxy (Traefik or Nginx Proxy Manager) with &lt;span class="caps"&gt;HTTPS&lt;/span&gt; and basic auth or OAuth. If you use Traefik, the labels look like&amp;nbsp;this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.enable=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.portainer.rule=Host(`portainer.yourdomain.com`)&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.portainer.tls.certresolver=letsencrypt&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.services.portainer.loadbalancer.server.port=9000&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Backup&amp;nbsp;Strategy&lt;/h3&gt;
&lt;p&gt;Portainer stores all configuration (users, endpoints, stacks, registry credentials) in its data volume. Back up this volume&amp;nbsp;regularly:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;--rm&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;portainer_data:/data&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;:/backup&lt;span class="w"&gt; &lt;/span&gt;alpine&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;tar&lt;span class="w"&gt; &lt;/span&gt;czf&lt;span class="w"&gt; &lt;/span&gt;/backup/portainer-backup.tar.gz&lt;span class="w"&gt; &lt;/span&gt;-C&lt;span class="w"&gt; &lt;/span&gt;/data&lt;span class="w"&gt; &lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Alternatives to&amp;nbsp;Consider&lt;/h2&gt;
&lt;h3&gt;Yacht&lt;/h3&gt;
&lt;p&gt;Yacht is a newer, lightweight alternative to Portainer with a focus on &amp;#8220;app templates&amp;#8221; — one-click installs for common homelab apps. It is less mature than Portainer but has a more modern &lt;span class="caps"&gt;UI&lt;/span&gt;. Good for beginners who want templates over full&amp;nbsp;control.&lt;/p&gt;
&lt;h3&gt;Dockge&lt;/h3&gt;
&lt;p&gt;Dockge is a sleek, minimal Docker Compose stack manager. It does not manage individual containers or Swarm; it is purely for editing and deploying Compose files via a web &lt;span class="caps"&gt;UI&lt;/span&gt;. If your entire workflow is Compose-based, Dockge is a simpler&amp;nbsp;alternative.&lt;/p&gt;
&lt;h3&gt;Kubernetes&amp;nbsp;Dashboard&lt;/h3&gt;
&lt;p&gt;If you run a Kubernetes homelab (k3s, K3d, or MicroK8s), the official Kubernetes Dashboard provides similar functionality. However, it is Kubernetes-native and does not manage Docker directly. Most homelabbers start with Docker and graduate to k3s&amp;nbsp;later.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;Complexity&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Portainer &lt;span class="caps"&gt;CE&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Full Docker/Swarm management&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Yacht&lt;/td&gt;
&lt;td&gt;One-click app templates&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dockge&lt;/td&gt;
&lt;td&gt;Compose-only workflows&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kubernetes Dashboard&lt;/td&gt;
&lt;td&gt;k3s/K8s clusters&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Frequently Asked&amp;nbsp;Questions&lt;/h2&gt;
&lt;h3&gt;Can I run Portainer on a Raspberry&amp;nbsp;Pi?&lt;/h3&gt;
&lt;p&gt;Yes. Portainer &lt;span class="caps"&gt;CE&lt;/span&gt; provides multi-arch images&amp;nbsp;(&lt;code&gt;linux/arm64&lt;/code&gt; and &lt;code&gt;linux/arm/v7&lt;/code&gt;). Deployment is identical to x86. Performance is fine for managing a handful of&amp;nbsp;containers.&lt;/p&gt;
&lt;h3&gt;Is Portainer &lt;span class="caps"&gt;CE&lt;/span&gt; really free for unlimited&amp;nbsp;use?&lt;/h3&gt;
&lt;p&gt;Yes. Portainer &lt;span class="caps"&gt;CE&lt;/span&gt; is open-source under the zlib license. You can manage unlimited nodes, containers, and stacks. Business Edition adds enterprise features but is not required for homelab&amp;nbsp;use.&lt;/p&gt;
&lt;h3&gt;How do I update&amp;nbsp;Portainer?&lt;/h3&gt;
&lt;p&gt;Pull the latest image and recreate the container. Portainer preserves its data in the named&amp;nbsp;volume.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;pull&lt;span class="w"&gt; &lt;/span&gt;portainer/portainer-ce:latest
docker&lt;span class="w"&gt; &lt;/span&gt;stop&lt;span class="w"&gt; &lt;/span&gt;portainer
docker&lt;span class="w"&gt; &lt;/span&gt;rm&lt;span class="w"&gt; &lt;/span&gt;portainer
&lt;span class="c1"&gt;# Re-run your original docker run command&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Does Portainer work with&amp;nbsp;Podman?&lt;/h3&gt;
&lt;p&gt;Partially. Portainer expects a Docker-compatible &lt;span class="caps"&gt;API&lt;/span&gt;. Podman can expose a Docker-compatible socket&amp;nbsp;(&lt;code&gt;podman system service&lt;/code&gt;), but not all features translate perfectly. For Podman-first workflows, consider Cockpit&amp;nbsp;instead.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Portainer &lt;span class="caps"&gt;CE&lt;/span&gt; is the most mature, accessible Docker management &lt;span class="caps"&gt;UI&lt;/span&gt; available for homelab use. It bridges the gap between terminal-only workflows and full orchestration platforms, offering stack management, container inspection, multi-host support, and edge deployment — all without cost. If you run more than three containers, Portainer pays for itself in time&amp;nbsp;saved.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Deploy Portainer behind Traefik with Let&amp;#8217;s&amp;nbsp;Encrypt&lt;/li&gt;
&lt;li&gt;Connect a second homelab node via the Edge&amp;nbsp;Agent&lt;/li&gt;
&lt;li&gt;Import your existing Compose files as&amp;nbsp;Stacks&lt;/li&gt;
&lt;li&gt;Enable GitHub webhook redeployment for &lt;span class="caps"&gt;CI&lt;/span&gt;/&lt;span class="caps"&gt;CD&lt;/span&gt;-style&amp;nbsp;updates&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;installation&lt;/strong&gt;: hosting — Linode, Hetzner, or DigitalOcean &lt;span class="caps"&gt;VPS&lt;/span&gt; for remote Docker&amp;nbsp;hosts&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;integration&lt;/strong&gt;: tool — Docker Hub subscription for private registry&amp;nbsp;use&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;alternatives&lt;/strong&gt;: tool — Kubernetes (k3s) on Raspberry Pi&amp;nbsp;clusters&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;installation&lt;/code&gt; → setup_guide: &lt;a href="https://steadypub.com/2026/06/docker-compose-for-beginners/"&gt;our Docker Compose setup guide for&amp;nbsp;beginners&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;integration&lt;/code&gt; → related_guide: &lt;a href="https://steadypub.com/2026/06/immich-reverse-proxy/"&gt;how to set up Traefik reverse&amp;nbsp;proxy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;alternatives&lt;/code&gt; → comparison: &lt;a href="https://steadypub.com/2026/06/portainer-vs-cockpit/"&gt;Portainer vs Cockpit for Docker&amp;nbsp;management&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] What&amp;#8217;s your Portainer workflow? Do you use Stacks, individual containers, or both? Share&amp;nbsp;below.&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for weekly homelab guides, self-hosted app reviews, and Docker&amp;nbsp;tips.&lt;/li&gt;
&lt;li&gt;[internal_link] Next up: read our &lt;a href="https://steadypub.com/2026/06/docker-monitoring-grafana-prometheus/"&gt;Grafana + Prometheus Docker monitoring&amp;nbsp;guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Tool Guides"/><category term="portainer"/><category term="docker"/><category term="homelab"/><category term="container management"/><category term="self-hosted"/></entry><entry><title>How to Set Up Prometheus Alertmanager: A Step-by-Step Homelab Guide</title><link href="https://steadypub.com/2026/06/prometheus-alertmanager-setup/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T06:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/prometheus-alertmanager-setup/</id><summary type="html">&lt;p&gt;Deploy Prometheus Alertmanager in Docker for real-time homelab alerting. Slack, Telegram, email, and PagerDuty integrations with real config&amp;nbsp;examples.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~12 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelabbers who want alerts when services&amp;nbsp;fail&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is Prometheus&amp;nbsp;Alertmanager?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Prometheus Alertmanager handles alerts sent by client applications such as Prometheus server. It takes care of deduplicating, grouping, and routing them to the correct receiver integration such as email, Slack, Telegram, PagerDuty, or webhook. It also handles silencing and inhibition of&amp;nbsp;alerts.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key concepts:&lt;/strong&gt;
- &lt;strong&gt;Alerting rules:&lt;/strong&gt; Prometheus evaluates expressions and fires alerts
- &lt;strong&gt;Alertmanager:&lt;/strong&gt; Receives fired alerts, groups them, and routes to receivers
- &lt;strong&gt;Grouping:&lt;/strong&gt; Multiple related alerts are sent as one notification
- &lt;strong&gt;Inhibition:&lt;/strong&gt; If a critical alert is firing, suppress lower-priority alerts for the same service
- &lt;strong&gt;Silencing:&lt;/strong&gt; Mute alerts for a maintenance&amp;nbsp;window&lt;/p&gt;
&lt;h3&gt;Why It&amp;nbsp;Matters&lt;/h3&gt;
&lt;p&gt;A dashboard that shows a red dot is useless if you are asleep. Alertmanager turns metrics into actionable notifications. When your Nextcloud container exits, when your &lt;span class="caps"&gt;NAS&lt;/span&gt; disk hits 90%, or when your Proxmox node goes down, you need to know&amp;nbsp;immediately.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;h3&gt;Hardware&amp;nbsp;Requirements&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Minimum&lt;/th&gt;
&lt;th&gt;Recommended&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1 core&lt;/td&gt;
&lt;td&gt;2 cores&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;512 &lt;span class="caps"&gt;MB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;1 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;5 &lt;span class="caps"&gt;GB&lt;/span&gt; (for alert history)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network&lt;/td&gt;
&lt;td&gt;1 GbE&lt;/td&gt;
&lt;td&gt;1 GbE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Software&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Docker and Docker Compose&amp;nbsp;installed&lt;/li&gt;
&lt;li&gt;Prometheus already running (or deploy&amp;nbsp;together)&lt;/li&gt;
&lt;li&gt;A notification target: Slack webhook, Telegram bot token, or &lt;span class="caps"&gt;SMTP&lt;/span&gt;&amp;nbsp;server&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Knowledge&amp;nbsp;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Basic &lt;span class="caps"&gt;YAML&lt;/span&gt;&amp;nbsp;syntax&lt;/li&gt;
&lt;li&gt;Understanding of Prometheus scrape configs and recording&amp;nbsp;rules&lt;/li&gt;
&lt;li&gt;Familiarity with your notification platform (Slack, Telegram,&amp;nbsp;etc.)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Deploy Alertmanager with Docker&amp;nbsp;Compose&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Run Alertmanager as a container with a persistent configuration&amp;nbsp;volume.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Create a directory for&amp;nbsp;Alertmanager:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;~/alertmanager/config
&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/alertmanager
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Create &lt;code&gt;config/alertmanager.yml&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;global&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;smtp_smarthost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;smtp.gmail.com:587&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;smtp_from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;alerts@yourdomain.com&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;smtp_auth_username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;alerts@yourdomain.com&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;smtp_auth_password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;your-app-password&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;slack_api_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;telegram_api_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;https://api.telegram.org&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;resolve_timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;5m&lt;/span&gt;

&lt;span class="nt"&gt;route&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;receiver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;default&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;group_by&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;alertname&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;job&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;severity&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;group_wait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;10s&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;group_interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;10s&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;repeat_interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1h&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;severity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;critical&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;receiver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;critical-alerts&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;severity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;warning&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;receiver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;warning-alerts&amp;#39;&lt;/span&gt;

&lt;span class="nt"&gt;receivers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;default&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;slack_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;#homelab-alerts&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;send_resolved&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;.GroupLabels.alertname&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;range&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;.Alerts&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;.Annotations.summary&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;end&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&amp;#39;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;critical-alerts&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;telegram_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;api_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;https://api.telegram.org&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;bot_token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;YOUR_BOT_TOKEN&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;chat_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;YOUR_CHAT_ID&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;CRITICAL:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;range&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;.Alerts&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;.Annotations.summary&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;end&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;parse_mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;Markdown&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;email_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;admin@yourdomain.com&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;send_resolved&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;Subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;CRITICAL:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;.GroupLabels.alertname&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&amp;#39;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;warning-alerts&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;slack_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;#homelab-warnings&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;send_resolved&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;true&lt;/span&gt;

&lt;span class="nt"&gt;inhibit_rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;source_match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;severity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;critical&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;target_match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;severity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;warning&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;alertname&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;job&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Create &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;alertmanager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;prom/alertmanager:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;alertmanager&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;9093:9093&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./config:/etc/alertmanager&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;alertmanager-data:/alertmanager&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--config.file=/etc/alertmanager/alertmanager.yml&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--storage.path=/alertmanager&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;--web.external-url=http://alertmanager.yourdomain.com&amp;#39;&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;alertmanager-data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Start the&amp;nbsp;container:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Verify the &lt;span class="caps"&gt;UI&lt;/span&gt; is accessible&amp;nbsp;at &lt;code&gt;http://your-server-ip:9093&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Step 2: Configure Prometheus to Send&amp;nbsp;Alerts&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Add alerting rules to Prometheus and point it at&amp;nbsp;Alertmanager.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Edit your&amp;nbsp;Prometheus &lt;code&gt;prometheus.yml&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;global&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;scrape_interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;15s&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;evaluation_interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;15s&lt;/span&gt;

&lt;span class="nt"&gt;alerting&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;alertmanagers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;alertmanager:9093&lt;/span&gt;

&lt;span class="nt"&gt;rule_files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/etc/prometheus/rules/*.yml&lt;/span&gt;

&lt;span class="nt"&gt;scrape_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;prometheus&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;localhost:9090&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;node-exporter&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;node-exporter:9100&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Create alerting rules&amp;nbsp;in &lt;code&gt;rules/alerts.yml&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;homelab-alerts&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;30s&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;HighCPUUsage&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;100 - (avg by(instance) (irate(node_cpu_seconds_total{mode=&amp;quot;idle&amp;quot;}[5m])) * 100) &amp;gt; 80&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;5m&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;severity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;warning&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;annotations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;High&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;CPU&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;usage&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;on&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;$labels.instance&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;CPU&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;usage&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;is&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;above&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;80%&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;more&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;than&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;5&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;minutes.&amp;quot;&lt;/span&gt;

&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;DiskSpaceLow&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;(node_filesystem_avail_bytes / node_filesystem_size_bytes) &amp;lt; 0.1&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;5m&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;severity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;critical&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;annotations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Disk&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;space&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;low&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;on&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;$labels.instance&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Less&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;than&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;10%&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;disk&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;space&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;remaining&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;on&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;$labels.device&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}.&amp;quot;&lt;/span&gt;

&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;NodeDown&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;up == 0&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1m&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;severity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;critical&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;annotations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Node&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;$labels.instance&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;is&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;down&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Prometheus&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;has&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;been&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;unable&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;scrape&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;$labels.instance&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;minute.&amp;quot;&lt;/span&gt;

&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ContainerHighMemory&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;(container_memory_usage_bytes / container_spec_memory_limit_bytes) &amp;gt; 0.85&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;5m&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;severity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;warning&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;annotations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Container&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;memory&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;high&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Container&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;$labels.name&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;is&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;using&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;gt;85%&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;of&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;its&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;memory&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;limit.&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Reload Prometheus&amp;nbsp;configuration:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-X&lt;span class="w"&gt; &lt;/span&gt;POST&lt;span class="w"&gt; &lt;/span&gt;http://localhost:9090/-/reload
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 3: Set Up Telegram Bot&amp;nbsp;Notifications&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Create a Telegram bot and configure Alertmanager to send critical alerts to&amp;nbsp;it.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Message &lt;code&gt;@BotFather&lt;/code&gt; on Telegram and create a new bot. Save the&amp;nbsp;token.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Get your chat &lt;span class="caps"&gt;ID&lt;/span&gt;:&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;https://api.telegram.org/botYOUR_TOKEN/getUpdates&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;quot;chat&amp;quot;:{&amp;quot;id&amp;quot;:[0-9]*&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;[0-9]*&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Update &lt;code&gt;alertmanager.yml&lt;/code&gt; with your real token and chat &lt;span class="caps"&gt;ID&lt;/span&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Restart&amp;nbsp;Alertmanager:&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;restart&lt;span class="w"&gt; &lt;/span&gt;alertmanager
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Test by firing a manual&amp;nbsp;alert:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-X&lt;span class="w"&gt; &lt;/span&gt;POST&lt;span class="w"&gt; &lt;/span&gt;http://localhost:9093/api/v1/alerts&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-H&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Content-Type: application/json&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;[{&amp;quot;labels&amp;quot;:{&amp;quot;alertname&amp;quot;:&amp;quot;TestAlert&amp;quot;,&amp;quot;severity&amp;quot;:&amp;quot;critical&amp;quot;},&amp;quot;annotations&amp;quot;:{&amp;quot;summary&amp;quot;:&amp;quot;This is a test&amp;quot;},&amp;quot;generatorURL&amp;quot;:&amp;quot;http://test&amp;quot;}]&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 4: Configure Slack&amp;nbsp;Notifications&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Create a Slack webhook and send alerts to a&amp;nbsp;channel.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;In Slack, go to &lt;strong&gt;Settings &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; Administration&lt;/strong&gt; &amp;gt; &lt;strong&gt;Manage Apps&lt;/strong&gt; &amp;gt; &lt;strong&gt;Incoming&amp;nbsp;Webhooks&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Add a new webhook to&amp;nbsp;your &lt;code&gt;#homelab-alerts&lt;/code&gt; channel&lt;/li&gt;
&lt;li&gt;Copy the webhook &lt;span class="caps"&gt;URL&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Update &lt;code&gt;alertmanager.yml&lt;/code&gt; with the webhook &lt;span class="caps"&gt;URL&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Restart&amp;nbsp;Alertmanager&lt;/li&gt;
&lt;li&gt;Test with the same curl command as&amp;nbsp;above&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Step 5: Add Silencing and Maintenance&amp;nbsp;Windows&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Prevent alert spam during planned&amp;nbsp;maintenance.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Use the Alertmanager &lt;span class="caps"&gt;UI&lt;/span&gt;&amp;nbsp;(&lt;code&gt;http://your-server:9093&lt;/code&gt;) to create silences&amp;nbsp;manually&lt;/li&gt;
&lt;li&gt;Or use the &lt;span class="caps"&gt;API&lt;/span&gt; for automated maintenance&amp;nbsp;scripts:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-X&lt;span class="w"&gt; &lt;/span&gt;POST&lt;span class="w"&gt; &lt;/span&gt;http://localhost:9093/api/v1/silences&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-H&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Content-Type: application/json&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;{&lt;/span&gt;
&lt;span class="s1"&gt;    &amp;quot;matchers&amp;quot;: [&lt;/span&gt;
&lt;span class="s1"&gt;      {&amp;quot;name&amp;quot;: &amp;quot;alertname&amp;quot;, &amp;quot;value&amp;quot;: &amp;quot;NodeDown&amp;quot;, &amp;quot;isRegex&amp;quot;: false}&lt;/span&gt;
&lt;span class="s1"&gt;    ],&lt;/span&gt;
&lt;span class="s1"&gt;    &amp;quot;startsAt&amp;quot;: &amp;quot;2026-06-10T02:00:00Z&amp;quot;,&lt;/span&gt;
&lt;span class="s1"&gt;    &amp;quot;endsAt&amp;quot;: &amp;quot;2026-06-10T04:00:00Z&amp;quot;,&lt;/span&gt;
&lt;span class="s1"&gt;    &amp;quot;createdBy&amp;quot;: &amp;quot;admin&amp;quot;,&lt;/span&gt;
&lt;span class="s1"&gt;    &amp;quot;comment&amp;quot;: &amp;quot;Scheduled maintenance window&amp;quot;&lt;/span&gt;
&lt;span class="s1"&gt;  }&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Group Alerts to Avoid&amp;nbsp;Spam&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;group_by&lt;/code&gt; field in the route configuration groups alerts by labels. If 10 containers on the same host are down, you get one notification, not 10.&amp;nbsp;Use &lt;code&gt;group_by: ['alertname', 'job']&lt;/code&gt; for service-level grouping&amp;nbsp;and &lt;code&gt;group_by: ['alertname', 'instance']&lt;/code&gt; for host-level&amp;nbsp;grouping.&lt;/p&gt;
&lt;h3&gt;Tip 2: Use Inhibition for Cascade&amp;nbsp;Failures&lt;/h3&gt;
&lt;p&gt;If your router is down, every service behind it will also appear down. The inhibition rule suppresses &amp;#8220;NodeDown&amp;#8221; for dependent services when the router is already critical. Define dependencies&amp;nbsp;explicitly:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;inhibit_rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;source_match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;severity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;critical&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;alertname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;RouterDown&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;target_match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;severity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;critical&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;datacenter&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 3: Keep Alertmanager Config in&amp;nbsp;Git&lt;/h3&gt;
&lt;p&gt;Store &lt;code&gt;alertmanager.yml&lt;/code&gt; in a Git repository. Use a &lt;span class="caps"&gt;CI&lt;/span&gt; pipeline to validate the &lt;span class="caps"&gt;YAML&lt;/span&gt; and reload the container on push. This prevents configuration drift and gives you an audit&amp;nbsp;trail.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Troubleshooting Common&amp;nbsp;Issues&lt;/h2&gt;
&lt;h3&gt;Problem 1: Alerts Not&amp;nbsp;Firing&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Check:&lt;/strong&gt; Prometheus alerting rules page&amp;nbsp;(&lt;code&gt;http://prometheus:9090/alerts&lt;/code&gt;). If the rule is green, it is not firing. If yellow, it is pending. If red, it is firing but may not be reaching&amp;nbsp;Alertmanager.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Verify&amp;nbsp;the &lt;code&gt;alerting&lt;/code&gt; block&amp;nbsp;in &lt;code&gt;prometheus.yml&lt;/code&gt; points to the correct Alertmanager host and port. If using Docker, ensure both containers are on the same&amp;nbsp;network.&lt;/p&gt;
&lt;h3&gt;Problem 2: Telegram Messages Not&amp;nbsp;Received&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Check:&lt;/strong&gt; Verify the bot token and chat &lt;span class="caps"&gt;ID&lt;/span&gt;. Test&amp;nbsp;with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;https://api.telegram.org/botTOKEN/sendMessage?chat_id=CHAT_ID&amp;amp;text=Test&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; If the bot is not in the group, add it. If the group is private, use the numeric chat &lt;span class="caps"&gt;ID&lt;/span&gt;, not the group&amp;nbsp;name.&lt;/p&gt;
&lt;h3&gt;Problem 3: Duplicate&amp;nbsp;Alerts&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Check:&lt;/strong&gt; Ensure Prometheus is not scraping multiple instances that report the same metrics. If you have two Prometheus servers, configure external labels to distinguish&amp;nbsp;them.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Prometheus Alertmanager turns metrics into actionable notifications. With proper grouping, routing, and inhibition, you get timely alerts without noise. Telegram and Slack are the most popular homelab receivers. Use silencing for maintenance windows and keep your config in version&amp;nbsp;control.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Add more alerting rules for your specific services (Nextcloud, Jellyfin,&amp;nbsp;Plex)&lt;/li&gt;
&lt;li&gt;Configure PagerDuty or webhook receivers for critical&amp;nbsp;infrastructure&lt;/li&gt;
&lt;li&gt;Set up a Grafana OnCall or Uptime Kuma as a secondary alerting&amp;nbsp;path&lt;/li&gt;
&lt;li&gt;Review and tune alert thresholds&amp;nbsp;monthly&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt;:&lt;/strong&gt; Hetzner for offsite Alertmanager&amp;nbsp;(referral)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Notification hardware:&lt;/strong&gt; Grafana OnCall, PagerDuty&amp;nbsp;(referral)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;prometheus-setup&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;prometheus-monitoring-homelab.md&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grafana-setup&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;grafana-docker-compose.md&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker-monitoring&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;docker-monitoring-grafana-prometheus.md&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;node-exporter&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;prometheus-monitoring-homelab.md&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] What notification channel do you use for homelab alerts? Telegram, Slack, or something&amp;nbsp;else?&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for our monitoring stack templates and alerting rule&amp;nbsp;packs.&lt;/li&gt;
&lt;li&gt;[internal_link] Need to set up Prometheus first? Read our &lt;a href="https://steadypub.com/2026/06/prometheus-monitoring-homelab/"&gt;Prometheus monitoring guide&lt;/a&gt;&amp;nbsp;next.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Tutorials"/><category term="homelab"/><category term="self-hosted"/><category term="prometheus alertmanager setup"/><category term="monitoring"/></entry><entry><title>Prometheus vs InfluxDB: Which One Wins for Your Homelab?</title><link href="https://steadypub.com/2026/06/prometheus-vs-influxdb/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T06:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/prometheus-vs-influxdb/</id><summary type="html">&lt;p&gt;Head-to-head comparison of Prometheus and InfluxDB for homelab monitoring in 2026. Architecture, resource use, query languages, and real-world setup&amp;nbsp;advice.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~13 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelabbers choosing a time-series database for&amp;nbsp;monitoring&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The Prometheus vs InfluxDB&amp;nbsp;Dilemma&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Every homelab needs metrics. Whether you are tracking &lt;span class="caps"&gt;CPU&lt;/span&gt; load, disk I/O, or whether your Nextcloud container is alive, a time-series database (&lt;span class="caps"&gt;TSDB&lt;/span&gt;) is the backbone of observability. The two most popular self-hosted choices are &lt;strong&gt;Prometheus&lt;/strong&gt; (the Cloud Native Computing Foundation darling) and &lt;strong&gt;InfluxDB&lt;/strong&gt; (the commercial &lt;span class="caps"&gt;TSDB&lt;/span&gt; with a generous free&amp;nbsp;tier).&lt;/p&gt;
&lt;p&gt;The choice is not just technical—it is philosophical. Prometheus is pull-based, metric-centric, and tightly integrated with the Kubernetes/Grafana ecosystem. InfluxDB is push-based, flexible-schema, and designed for IoT and general time-series workloads. Both can run in Docker on a mini &lt;span class="caps"&gt;PC&lt;/span&gt;. Both feed Grafana. But they excel in different homelab&amp;nbsp;scenarios.&lt;/p&gt;
&lt;h3&gt;Key Differences at a&amp;nbsp;Glance&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;Prometheus&lt;/th&gt;
&lt;th&gt;InfluxDB&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Data model&lt;/td&gt;
&lt;td&gt;Pull (scrape)&lt;/td&gt;
&lt;td&gt;Push (write)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;Local &lt;span class="caps"&gt;TSDB&lt;/span&gt; (append-only)&lt;/td&gt;
&lt;td&gt;BoltDB or InfluxDB IOx engine&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Query language&lt;/td&gt;
&lt;td&gt;PromQL&lt;/td&gt;
&lt;td&gt;InfluxQL (v1) or Flux (v2/v3)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Schema&lt;/td&gt;
&lt;td&gt;Metric name + labels (key-value)&lt;/td&gt;
&lt;td&gt;Flexible (measurement, tags, fields)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Retention&lt;/td&gt;
&lt;td&gt;Configurable per metric&lt;/td&gt;
&lt;td&gt;Bucket-level policies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;High availability&lt;/td&gt;
&lt;td&gt;Thanos/Mimir/Cortex (complex)&lt;/td&gt;
&lt;td&gt;InfluxDB Enterprise (paid)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resource use&lt;/td&gt;
&lt;td&gt;Low ( Go binary)&lt;/td&gt;
&lt;td&gt;Low–Medium (depends on engine)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ecosystem&lt;/td&gt;
&lt;td&gt;Massive (exporters, Alertmanager)&lt;/td&gt;
&lt;td&gt;Good (Telegraf, client libraries)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Commercial backing&lt;/td&gt;
&lt;td&gt;None (&lt;span class="caps"&gt;CNCF&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;InfluxData (freemium)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Option A:&amp;nbsp;Prometheus&lt;/h2&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pull-based simplicity:&lt;/strong&gt; Prometheus scrapes metrics from &lt;span class="caps"&gt;HTTP&lt;/span&gt; endpoints. This means your application does not need to know where Prometheus lives—it just&amp;nbsp;exposes &lt;code&gt;/metrics&lt;/code&gt; and Prometheus discovers it. For homelabs, this eliminates the complexity of push agents failing&amp;nbsp;silently.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Exporters everywhere:&lt;/strong&gt; There is a Prometheus exporter for almost everything: Node Exporter (Linux hardware), cAdvisor (Docker containers), &lt;span class="caps"&gt;SNMP&lt;/span&gt; Exporter (network gear), Blackbox Exporter (probes), and even custom exporters for Pi-hole, AdGuard Home, and&amp;nbsp;Proxmox.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PromQL is powerful:&lt;/strong&gt; The query language is designed for alerting. Queries&amp;nbsp;like &lt;code&gt;rate(node_cpu_seconds_total{mode="user"}[5m])&lt;/code&gt; are intuitive for operations work. Grafana has native PromQL support with&amp;nbsp;autocomplete.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Alertmanager integration:&lt;/strong&gt; Native alerting with routing, silencing, and grouping. You can send alerts to Slack, Telegram, email, or PagerDuty from a single &lt;span class="caps"&gt;YAML&lt;/span&gt;&amp;nbsp;config.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Single binary:&lt;/strong&gt; Prometheus is a single Go binary. It runs in a 50 &lt;span class="caps"&gt;MB&lt;/span&gt; container and starts&amp;nbsp;instantly.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No schema design:&lt;/strong&gt; You do not create tables or define fields. Metrics are self-describing via&amp;nbsp;labels.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Long-term storage is weak:&lt;/strong&gt; Prometheus stores data locally. Default retention is 15 days. For long-term storage, you need Thanos, Mimir, or remote_write to another database—adding&amp;nbsp;complexity.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pull model struggles with short-lived jobs:&lt;/strong&gt; A batch job that runs and exits may not exist when Prometheus scrapes. The Pushgateway solves this but is an anti-pattern if&amp;nbsp;misused.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No event logging:&lt;/strong&gt; Prometheus is for metrics, not logs. You need Loki (or &lt;span class="caps"&gt;ELK&lt;/span&gt;) for logs, which adds another stack&amp;nbsp;component.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cardinality explosion:&lt;/strong&gt; If you create labels with unbounded values (e.g., user IDs), Prometheus memory usage&amp;nbsp;explodes.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Docker/Kubernetes container&amp;nbsp;monitoring&lt;/li&gt;
&lt;li&gt;Alert-driven homelab operations (&amp;#8220;notify me if Plex is&amp;nbsp;down&amp;#8221;)&lt;/li&gt;
&lt;li&gt;Grafana dashboard-centric&amp;nbsp;workflows&lt;/li&gt;
&lt;li&gt;Users who want a pure open-source stack with no vendor&amp;nbsp;lock-in&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;p&gt;Free (Apache 2.0). No commercial tier&amp;nbsp;exists.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Option B:&amp;nbsp;InfluxDB&lt;/h2&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Flexible data model:&lt;/strong&gt; InfluxDB accepts any structured data—metrics, logs, events, sensor readings. You define measurements (tables), tags (indexed metadata), and fields (values). This is ideal for IoT homelabs collecting temperature, power, or humidity data alongside server&amp;nbsp;metrics.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Long-term storage is native:&lt;/strong&gt; InfluxDB v2 has built-in retention policies and downsampling. You can keep raw data for 7 days, then downsample to hourly averages for 1 year, all within the same&amp;nbsp;database.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Telegraf is a Swiss Army knife:&lt;/strong&gt; InfluxData&amp;#8217;s Telegraf agent has 300+ input plugins (&lt;span class="caps"&gt;SNMP&lt;/span&gt;, &lt;span class="caps"&gt;MQTT&lt;/span&gt;, Docker, Proxmox, Pi-hole, etc.) and can output to multiple destinations&amp;nbsp;simultaneously.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;InfluxDB IOx engine:&lt;/strong&gt; InfluxDB v3 (2024+) uses Apache Arrow and Parquet under the hood. Query performance is significantly better for analytical workloads. It also supports &lt;span class="caps"&gt;SQL&lt;/span&gt; queries alongside&amp;nbsp;InfluxQL.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Push model fits IoT:&lt;/strong&gt; Battery-powered &lt;span class="caps"&gt;ESP32&lt;/span&gt; sensors can push metrics via &lt;span class="caps"&gt;HTTP&lt;/span&gt; or &lt;span class="caps"&gt;MQTT&lt;/span&gt;. No need to expose a web server on a&amp;nbsp;microcontroller.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Continuous queries:&lt;/strong&gt; Transform and aggregate data as it arrives. For example, compute a 5-minute average of &lt;span class="caps"&gt;CPU&lt;/span&gt; temperature and store it in a separate retention&amp;nbsp;bucket.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Flux learning curve:&lt;/strong&gt; InfluxDB v2 introduced Flux, a functional query language. It is powerful but unfamiliar to &lt;span class="caps"&gt;SQL&lt;/span&gt; users. InfluxDB v3 supports &lt;span class="caps"&gt;SQL&lt;/span&gt;, which helps, but the transition is&amp;nbsp;confusing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Commercial pressure:&lt;/strong&gt; InfluxData is a venture-backed company. InfluxDB v2&amp;#8217;s open-source future is less certain than Prometheus&amp;#8217;s &lt;span class="caps"&gt;CNCF&lt;/span&gt; governance. The v3 open-source release is incomplete as of&amp;nbsp;2026.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Larger resource footprint:&lt;/strong&gt; InfluxDB v2 with BoltDB uses ~150–300 &lt;span class="caps"&gt;MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;. The IOx engine is more memory-hungry for large&amp;nbsp;datasets.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Smaller Grafana ecosystem:&lt;/strong&gt; While Grafana supports InfluxDB, the community dashboard library is smaller than Prometheus&amp;#8217;s. You will build more dashboards from&amp;nbsp;scratch.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;IoT and sensor data collection (temperature, power,&amp;nbsp;weather)&lt;/li&gt;
&lt;li&gt;Homelabs with mixed data types (metrics + logs +&amp;nbsp;events)&lt;/li&gt;
&lt;li&gt;Users who want built-in retention and downsampling without extra&amp;nbsp;tools&lt;/li&gt;
&lt;li&gt;Long-term trend analysis (&amp;#8220;how did my server&amp;#8217;s power use change over 2&amp;nbsp;years?&amp;#8221;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;p&gt;InfluxDB v2 is open source (&lt;span class="caps"&gt;MIT&lt;/span&gt;). InfluxDB Cloud has a generous free tier (10,000 writes/sec, 30-day retention). InfluxDB Enterprise is&amp;nbsp;paid.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Option C:&amp;nbsp;VictoriaMetrics&lt;/h2&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Prometheus-compatible &lt;span class="caps"&gt;API&lt;/span&gt;:&lt;/strong&gt; Drop-in replacement for Prometheus with better resource efficiency and native&amp;nbsp;clustering.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Long-term storage:&lt;/strong&gt; Built-in retention, downsampling, and compression. No Thanos&amp;nbsp;needed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Single-node scalable:&lt;/strong&gt; Handles millions of metrics on a single instance. Suitable for homelabs that outgrow&amp;nbsp;Prometheus.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Smaller ecosystem:&lt;/strong&gt; Fewer exporters and community dashboards designed specifically for&amp;nbsp;VictoriaMetrics.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Not &lt;span class="caps"&gt;CNCF&lt;/span&gt;:&lt;/strong&gt; Commercial backing by VictoriaMetrics Inc. raises long-term open-source&amp;nbsp;concerns.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Homelabs that started with Prometheus but need long-term storage and better&amp;nbsp;compression&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Comparison&amp;nbsp;Matrix&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Criteria&lt;/th&gt;
&lt;th&gt;Prometheus&lt;/th&gt;
&lt;th&gt;InfluxDB v2&lt;/th&gt;
&lt;th&gt;VictoriaMetrics&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Setup complexity&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resource use (idle)&lt;/td&gt;
&lt;td&gt;~50 &lt;span class="caps"&gt;MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;~150 &lt;span class="caps"&gt;MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;~80 &lt;span class="caps"&gt;MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Query language&lt;/td&gt;
&lt;td&gt;PromQL&lt;/td&gt;
&lt;td&gt;Flux / InfluxQL&lt;/td&gt;
&lt;td&gt;PromQL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Long-term storage&lt;/td&gt;
&lt;td&gt;Weak (needs Thanos)&lt;/td&gt;
&lt;td&gt;Native&lt;/td&gt;
&lt;td&gt;Native&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IoT/sensor fit&lt;/td&gt;
&lt;td&gt;Poor&lt;/td&gt;
&lt;td&gt;Excellent&lt;/td&gt;
&lt;td&gt;Poor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Alerting&lt;/td&gt;
&lt;td&gt;Alertmanager (native)&lt;/td&gt;
&lt;td&gt;Kapacitor / external&lt;/td&gt;
&lt;td&gt;Alertmanager (compatible)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Grafana support&lt;/td&gt;
&lt;td&gt;Excellent&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data compression&lt;/td&gt;
&lt;td&gt;Moderate&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;td&gt;Excellent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Open-source governance&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;CNCF&lt;/span&gt; (strong)&lt;/td&gt;
&lt;td&gt;InfluxData (commercial)&lt;/td&gt;
&lt;td&gt;VictoriaMetrics Inc.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Which Should You&amp;nbsp;Choose?&lt;/h2&gt;
&lt;h3&gt;Scenario 1: Docker/Kubernetes Container&amp;nbsp;Monitoring&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose Prometheus.&lt;/strong&gt; The cAdvisor + Node Exporter + Prometheus + Grafana stack is the de facto standard. Every container image you pull likely has&amp;nbsp;a &lt;code&gt;/metrics&lt;/code&gt; endpoint or an exporter. Alertmanager gives you native alerting for container&amp;nbsp;health.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Prometheus scrape config for Docker&lt;/span&gt;
&lt;span class="nt"&gt;scrape_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;cadvisor&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;cadvisor:8080&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;job_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#39;node-exporter&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;static_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;node-exporter:9100&amp;#39;&lt;/span&gt;&lt;span class="p p-Indicator"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Scenario 2: IoT + Server Metrics&amp;nbsp;Together&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose InfluxDB.&lt;/strong&gt; If you are collecting temperature from ESP32s, power from smart plugs, and &lt;span class="caps"&gt;CPU&lt;/span&gt; from servers, InfluxDB&amp;#8217;s flexible schema is superior. Telegraf can ingest all of these with pre-built&amp;nbsp;plugins.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Telegraf config snippet&lt;/span&gt;
&lt;span class="k"&gt;[[inputs.mqtt_consumer]]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;servers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;tcp://mosquitto:1883&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;topics&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;sensors/+/temperature&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;data_format&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;value&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;data_type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;float&amp;quot;&lt;/span&gt;

&lt;span class="k"&gt;[[inputs.prometheus]]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;http://node-exporter:9100/metrics&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Scenario 3: You Want One Stack to Rule Them&amp;nbsp;All&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Choose Prometheus + Loki.&lt;/strong&gt; For metrics, Prometheus. For logs, Loki. Both are Grafana-native. Both are pull-based. This is the Grafana Stack (formerly &lt;span class="caps"&gt;TIG&lt;/span&gt; stack), and it is the most cohesive observability experience in a&amp;nbsp;homelab.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Migration&amp;nbsp;Path&lt;/h2&gt;
&lt;h3&gt;Prometheus to&amp;nbsp;InfluxDB&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Deploy Telegraf with&amp;nbsp;the &lt;code&gt;prometheus&lt;/code&gt; input&amp;nbsp;plugin&lt;/li&gt;
&lt;li&gt;Point Telegraf at your existing Prometheus&amp;nbsp;exporters&lt;/li&gt;
&lt;li&gt;Write Telegraf output to&amp;nbsp;InfluxDB&lt;/li&gt;
&lt;li&gt;Gradually migrate Grafana dashboards to&amp;nbsp;InfluxQL/Flux&lt;/li&gt;
&lt;li&gt;Decommission Prometheus when dashboards are&amp;nbsp;migrated&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;InfluxDB to&amp;nbsp;Prometheus&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Deploy Prometheus with&amp;nbsp;the &lt;code&gt;influxdb_exporter&lt;/code&gt; (if you have InfluxDB line protocol&amp;nbsp;sources)&lt;/li&gt;
&lt;li&gt;For IoT sources, switch to the Prometheus pushgateway or use &lt;span class="caps"&gt;MQTT&lt;/span&gt; + a&amp;nbsp;bridge&lt;/li&gt;
&lt;li&gt;Rebuild Grafana dashboards in&amp;nbsp;PromQL&lt;/li&gt;
&lt;li&gt;Migrate Alertmanager&amp;nbsp;rules&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;The&amp;nbsp;Verdict&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;Recommendation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Container monitoring&lt;/td&gt;
&lt;td&gt;Prometheus&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IoT + sensor data&lt;/td&gt;
&lt;td&gt;InfluxDB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Long-term trends&lt;/td&gt;
&lt;td&gt;InfluxDB or VictoriaMetrics&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pure open-source preference&lt;/td&gt;
&lt;td&gt;Prometheus&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Grafana-native stack&lt;/td&gt;
&lt;td&gt;Prometheus + Loki&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mixed metrics/logs/events&lt;/td&gt;
&lt;td&gt;InfluxDB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Beginner-friendly&lt;/td&gt;
&lt;td&gt;Prometheus (better docs)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Our recommendation:&lt;/strong&gt; For a typical homelab running Docker containers, &lt;strong&gt;Prometheus&lt;/strong&gt; is the safer default. It has better documentation, a larger community, and native integration with Alertmanager. If your homelab includes IoT sensors, temperature probes, or non-&lt;span class="caps"&gt;HTTP&lt;/span&gt; data sources, &lt;strong&gt;InfluxDB&lt;/strong&gt; is the more natural&amp;nbsp;fit.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Prometheus and InfluxDB are both excellent time-series databases, but they serve different homelab philosophies. Prometheus is the pull-based, metric-centric, cloud-native choice. InfluxDB is the push-based, flexible-schema, IoT-friendly choice. Most homelabbers will be happy with Prometheus + Grafana. Those with sensor networks or long-term storage needs should evaluate&amp;nbsp;InfluxDB.&lt;/p&gt;
&lt;h3&gt;Ready to Get&amp;nbsp;Started?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Prometheus quick&amp;nbsp;start:&lt;/strong&gt; &lt;code&gt;docker run -p 9090:9090 prom/prometheus&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;InfluxDB quick&amp;nbsp;start:&lt;/strong&gt; &lt;code&gt;docker run -p 8086:8086 influxdb:2.7&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Grafana (for&amp;nbsp;either):&lt;/strong&gt; &lt;code&gt;docker run -p 3000:3000 grafana/grafana&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Monitoring hardware:&lt;/strong&gt; Mini PCs for dedicated monitoring nodes&amp;nbsp;(Amazon)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Grafana Cloud:&lt;/strong&gt; Free tier available; paid plans for advanced features&amp;nbsp;(referral)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt;:&lt;/strong&gt; Hetzner, Netcup for offsite monitoring&amp;nbsp;(referral)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;prometheus-setup&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;prometheus-monitoring-homelab.md&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grafana-setup&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;grafana-docker-compose.md&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;alerting&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;prometheus-alertmanager-setup.md&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker-monitoring&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;docker-monitoring-grafana-prometheus.md&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] Prometheus or InfluxDB? Cast your vote and tell us&amp;nbsp;why.&lt;/li&gt;
&lt;li&gt;[newsletter] Get our quarterly monitoring stack recommendations and Grafana dashboard&amp;nbsp;templates.&lt;/li&gt;
&lt;li&gt;[internal_link] Ready to deploy? Read our &lt;a href="https://steadypub.com/2026/06/prometheus-monitoring-homelab/"&gt;Prometheus monitoring guide&lt;/a&gt;&amp;nbsp;next.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Comparisons"/><category term="homelab"/><category term="prometheus"/><category term="influxdb"/><category term="self-hosted"/><category term="monitoring"/></entry><entry><title>Proxmox Hardware Requirements 2026: The Ultimate Self-Hosted Guide for 2026</title><link href="https://steadypub.com/2026/06/proxmox-hardware-requirements-2026/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T06:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/proxmox-hardware-requirements-2026/</id><summary type="html">&lt;p&gt;Real &lt;span class="caps"&gt;CPU&lt;/span&gt;, &lt;span class="caps"&gt;RAM&lt;/span&gt;, storage, and network requirements for Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; 8.2 in 2026. Includes hardware tiers, &lt;span class="caps"&gt;BIOS&lt;/span&gt; settings, and tested build configurations from $200 to&amp;nbsp;$2000+.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~14 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab and self-hosting enthusiasts planning a Proxmox&amp;nbsp;build&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Are Proxmox Hardware Requirements in&amp;nbsp;2026?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Proxmox Virtual Environment (&lt;span class="caps"&gt;VE&lt;/span&gt;) 8.2 is a Debian-based, open-source hypervisor that supports both &lt;span class="caps"&gt;KVM&lt;/span&gt; virtual machines and &lt;span class="caps"&gt;LXC&lt;/span&gt; containers. Unlike VMware ESXi, Proxmox has no artificial hardware compatibility list (&lt;span class="caps"&gt;HCL&lt;/span&gt;) restrictions, but it does have practical minimums for a usable homelab&amp;nbsp;experience.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; 8.2 official minimums:&lt;/strong&gt;
- 64-bit x86 &lt;span class="caps"&gt;CPU&lt;/span&gt; with Intel &lt;span class="caps"&gt;VT&lt;/span&gt;/&lt;span class="caps"&gt;AMD&lt;/span&gt;-V support (mandatory for &lt;span class="caps"&gt;KVM&lt;/span&gt;)
- 2 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; (4 &lt;span class="caps"&gt;GB&lt;/span&gt;+ recommended for a single-node lab)
- 32 &lt;span class="caps"&gt;GB&lt;/span&gt; storage (&lt;span class="caps"&gt;SSD&lt;/span&gt; strongly recommended)
- 1x Gigabit Ethernet &lt;span class="caps"&gt;NIC&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;These minimums will boot the installer. They will not run a useful homelab. This guide covers the &lt;em&gt;real&lt;/em&gt; requirements for running 5–20 VMs, &lt;span class="caps"&gt;ZFS&lt;/span&gt; storage, and &lt;span class="caps"&gt;GPU&lt;/span&gt;&amp;nbsp;passthrough.&lt;/p&gt;
&lt;h3&gt;Why 2026 Is&amp;nbsp;Different&lt;/h3&gt;
&lt;p&gt;The 2024–2025 Broadcom/VMware pricing shock pushed thousands of homelabbers to Proxmox. That influx raised the bar for documentation quality. Meanwhile, Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; 8.2 (released 2024) added enhanced Ceph support, improved &lt;span class="caps"&gt;ZFS&lt;/span&gt; defaults, and better &lt;span class="caps"&gt;AMD&lt;/span&gt; Ryzen power management. The hardware landscape has also shifted: Intel N100/N305 mini PCs are viable for light labs, and used &lt;span class="caps"&gt;DDR4&lt;/span&gt;-era enterprise servers are cheaper than&amp;nbsp;ever.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Real Hardware Requirements by&amp;nbsp;Tier&lt;/h2&gt;
&lt;h3&gt;Tier 1: Entry Mini &lt;span class="caps"&gt;PC&lt;/span&gt; Lab&amp;nbsp;($200–$400)&lt;/h3&gt;
&lt;p&gt;Best for: 1–2 Linux VMs, 3–5 &lt;span class="caps"&gt;LXC&lt;/span&gt; containers, learning Proxmox&amp;nbsp;basics&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Requirement&lt;/th&gt;
&lt;th&gt;Example Hardware&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Intel N100, N305, or &lt;span class="caps"&gt;AMD&lt;/span&gt; Ryzen 3 3200U&lt;/td&gt;
&lt;td&gt;Minisforum &lt;span class="caps"&gt;UN100L&lt;/span&gt;, Beelink U59&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;16 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;DDR4&lt;/span&gt;/&lt;span class="caps"&gt;DDR5&lt;/span&gt; (single &lt;span class="caps"&gt;SODIMM&lt;/span&gt; okay)&lt;/td&gt;
&lt;td&gt;Crucial 16 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;DDR5&lt;/span&gt;-4800 &lt;span class="caps"&gt;SODIMM&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;256 &lt;span class="caps"&gt;GB&lt;/span&gt; NVMe &lt;span class="caps"&gt;SSD&lt;/span&gt; (boot + &lt;span class="caps"&gt;VM&lt;/span&gt; disk)&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;WD&lt;/span&gt; Blue &lt;span class="caps"&gt;SN580&lt;/span&gt; 500 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;NIC&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1x 2.5 GbE (realtek or Intel i226)&lt;/td&gt;
&lt;td&gt;Built-in on most mini PCs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Power&lt;/td&gt;
&lt;td&gt;12–19 V &lt;span class="caps"&gt;DC&lt;/span&gt;, 30–65 W wall adapter&lt;/td&gt;
&lt;td&gt;Included with unit&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Reality check:&lt;/strong&gt; The Intel N100 is surprisingly capable for light labs. It runs 4 threads at up to 3.4 GHz, supports &lt;span class="caps"&gt;VT&lt;/span&gt;-x, &lt;span class="caps"&gt;VT&lt;/span&gt;-d, and &lt;span class="caps"&gt;AES&lt;/span&gt;-&lt;span class="caps"&gt;NI&lt;/span&gt;. With 16 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; and a fast NVMe, you can run Proxmox + 3–4 &lt;span class="caps"&gt;LXC&lt;/span&gt; containers (Pi-hole, AdGuard, WireGuard) simultaneously. &lt;span class="caps"&gt;KVM&lt;/span&gt; VMs are limited by the 4-thread count—expect 1–2 idle&amp;nbsp;VMs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;BIOS&lt;/span&gt; quirks to know:&lt;/strong&gt;
- Disable &amp;#8220;Secure Boot&amp;#8221; (Proxmox uses its own signed shim, but Secure Boot often causes installer hangs)
- Enable &amp;#8220;&lt;span class="caps"&gt;VT&lt;/span&gt;-x&amp;#8221; / &amp;#8220;Virtualization Technology&amp;#8221; (sometimes called &lt;span class="caps"&gt;SVM&lt;/span&gt; on &lt;span class="caps"&gt;AMD&lt;/span&gt;)
- Enable &amp;#8220;&lt;span class="caps"&gt;VT&lt;/span&gt;-d&amp;#8221; / &amp;#8220;&lt;span class="caps"&gt;IOMMU&lt;/span&gt;&amp;#8221; if you ever want &lt;span class="caps"&gt;GPU&lt;/span&gt; passthrough (even on N100, this works for Quick Sync)
- Disable &amp;#8220;Fast Boot&amp;#8221; so &lt;span class="caps"&gt;USB&lt;/span&gt; installer is consistently&amp;nbsp;detected&lt;/p&gt;
&lt;h3&gt;Tier 2: Serious Homelab Server&amp;nbsp;($500–$900)&lt;/h3&gt;
&lt;p&gt;Best for: 5–8 VMs, &lt;span class="caps"&gt;ZFS&lt;/span&gt; storage pools, hardware transcoding,&amp;nbsp;pfSense/OPNsense&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Requirement&lt;/th&gt;
&lt;th&gt;Example Hardware&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Intel i5-12400 / i5-13400 or &lt;span class="caps"&gt;AMD&lt;/span&gt; Ryzen 5 5600X&lt;/td&gt;
&lt;td&gt;6C/12T, 65 W &lt;span class="caps"&gt;TDP&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;32–64 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;DDR4&lt;/span&gt;-3200 &lt;span class="caps"&gt;ECC&lt;/span&gt; (optional but recommended)&lt;/td&gt;
&lt;td&gt;Kingston 32 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;ECC&lt;/span&gt; &lt;span class="caps"&gt;UDIMM&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;500 &lt;span class="caps"&gt;GB&lt;/span&gt; NVMe boot + 2×4 &lt;span class="caps"&gt;TB&lt;/span&gt; &lt;span class="caps"&gt;SATA&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt; for &lt;span class="caps"&gt;ZFS&lt;/span&gt; mirror&lt;/td&gt;
&lt;td&gt;Samsung 870 &lt;span class="caps"&gt;QVO&lt;/span&gt; 4 &lt;span class="caps"&gt;TB&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;NIC&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;2x 2.5 GbE or 1x 10 GbE &lt;span class="caps"&gt;SFP&lt;/span&gt;+&lt;/td&gt;
&lt;td&gt;Intel i226-V, Mellanox ConnectX-3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Power&lt;/td&gt;
&lt;td&gt;Standard &lt;span class="caps"&gt;ATX&lt;/span&gt; &lt;span class="caps"&gt;PSU&lt;/span&gt;, 300–450 W&lt;/td&gt;
&lt;td&gt;Be Quiet! Pure Power 11 400 W&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Why this tier matters:&lt;/strong&gt; 32 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; is the sweet spot for a multi-&lt;span class="caps"&gt;VM&lt;/span&gt; lab. You can run a Windows Server &lt;span class="caps"&gt;VM&lt;/span&gt; (4 &lt;span class="caps"&gt;GB&lt;/span&gt;), a Linux dev box (4 &lt;span class="caps"&gt;GB&lt;/span&gt;), a pfSense router (2 &lt;span class="caps"&gt;GB&lt;/span&gt;), a Nextcloud &lt;span class="caps"&gt;LXC&lt;/span&gt; (4 &lt;span class="caps"&gt;GB&lt;/span&gt;), and still have headroom. &lt;span class="caps"&gt;ZFS&lt;/span&gt; likes &lt;span class="caps"&gt;RAM&lt;/span&gt;—allocate 1 &lt;span class="caps"&gt;GB&lt;/span&gt; per &lt;span class="caps"&gt;TB&lt;/span&gt; of raw storage as a rule of thumb, but 32 &lt;span class="caps"&gt;GB&lt;/span&gt; handles a 2×4 &lt;span class="caps"&gt;TB&lt;/span&gt; mirror&amp;nbsp;comfortably.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Quick Sync note:&lt;/strong&gt; Intel 12th-gen and newer &lt;span class="caps"&gt;UHD&lt;/span&gt; P770 graphics support &lt;span class="caps"&gt;AV1&lt;/span&gt;, &lt;span class="caps"&gt;HEVC&lt;/span&gt;, and &lt;span class="caps"&gt;VP9&lt;/span&gt; hardware transcoding in Jellyfin/Plex. Enable it by passing the iGPU through to a Jellyfin &lt;span class="caps"&gt;LXC&lt;/span&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Add to LXC container config (e.g., /etc/pve/lxc/100.conf)&lt;/span&gt;
lxc.cgroup2.devices.allow:&lt;span class="w"&gt; &lt;/span&gt;c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;226&lt;/span&gt;:0&lt;span class="w"&gt; &lt;/span&gt;rwm
lxc.cgroup2.devices.allow:&lt;span class="w"&gt; &lt;/span&gt;c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;226&lt;/span&gt;:128&lt;span class="w"&gt; &lt;/span&gt;rwm
lxc.mount.entry:&lt;span class="w"&gt; &lt;/span&gt;/dev/dri&lt;span class="w"&gt; &lt;/span&gt;dev/dri&lt;span class="w"&gt; &lt;/span&gt;none&lt;span class="w"&gt; &lt;/span&gt;bind,optional,create&lt;span class="o"&gt;=&lt;/span&gt;dir
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tier 3: Enterprise-Grade Used Rack Server ($300–$800&amp;nbsp;used)&lt;/h3&gt;
&lt;p&gt;Best for: 10–20 VMs, Ceph clusters, nested virtualization, raw compute&amp;nbsp;power&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Requirement&lt;/th&gt;
&lt;th&gt;Example Hardware&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;2× Intel Xeon E5-2680 v4 (14C/28T each) or E5-2697 v3&lt;/td&gt;
&lt;td&gt;Dell R730, &lt;span class="caps"&gt;HP&lt;/span&gt; DL380p Gen9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;128–256 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;DDR4&lt;/span&gt; &lt;span class="caps"&gt;ECC&lt;/span&gt; &lt;span class="caps"&gt;RDIMM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Samsung 16 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;DDR4&lt;/span&gt;-2400 &lt;span class="caps"&gt;RDIMM&lt;/span&gt; ×8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;2× 240 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt; boot (&lt;span class="caps"&gt;RAID&lt;/span&gt;-1) + 4× 1 &lt;span class="caps"&gt;TB&lt;/span&gt; &lt;span class="caps"&gt;SATA&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt; (&lt;span class="caps"&gt;ZFS&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;Dell &lt;span class="caps"&gt;BOSS&lt;/span&gt;-S1 or Intel S4500&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;NIC&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;2× 1 GbE onboard + 10 GbE &lt;span class="caps"&gt;SFP&lt;/span&gt;+ add-on card&lt;/td&gt;
&lt;td&gt;Intel X520-&lt;span class="caps"&gt;DA2&lt;/span&gt;, Mellanox &lt;span class="caps"&gt;CX&lt;/span&gt;-3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Power&lt;/td&gt;
&lt;td&gt;Dual redundant &lt;span class="caps"&gt;PSU&lt;/span&gt;, 750–1100 W&lt;/td&gt;
&lt;td&gt;Included with chassis&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;The used server reality:&lt;/strong&gt; A Dell R730 with dual E5-2680 v4 CPUs and 128 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; costs $300–$500 on eBay in 2026. It will idle at 120–150 W, which translates to $120–$200/year in electricity at $0.15/kWh. Noise is the bigger issue— expect 35–40 dB(A) at 1 meter, which is audible in a home office. You can replace fans with Noctua &lt;span class="caps"&gt;NF&lt;/span&gt;-A4x20 or use iDRAC fan control scripts to tame&amp;nbsp;it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;R730 iDRAC quiet fan script (run on Proxmox&amp;nbsp;host):&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Install ipmitool&lt;/span&gt;
apt&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;ipmitool

&lt;span class="c1"&gt;# Set fan speed to 15% (silent but watch temps)&lt;/span&gt;
ipmitool&lt;span class="w"&gt; &lt;/span&gt;raw&lt;span class="w"&gt; &lt;/span&gt;0x30&lt;span class="w"&gt; &lt;/span&gt;0x30&lt;span class="w"&gt; &lt;/span&gt;0x02&lt;span class="w"&gt; &lt;/span&gt;0xff&lt;span class="w"&gt; &lt;/span&gt;0x0f

&lt;span class="c1"&gt;# Return to automatic control&lt;/span&gt;
ipmitool&lt;span class="w"&gt; &lt;/span&gt;raw&lt;span class="w"&gt; &lt;/span&gt;0x30&lt;span class="w"&gt; &lt;/span&gt;0x30&lt;span class="w"&gt; &lt;/span&gt;0x02&lt;span class="w"&gt; &lt;/span&gt;0xff&lt;span class="w"&gt; &lt;/span&gt;0x00
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tier 4: Modern Rack Build&amp;nbsp;($1200–$2500)&lt;/h3&gt;
&lt;p&gt;Best for: High-density &lt;span class="caps"&gt;VM&lt;/span&gt; hosting, 10 GbE+ networking, all-flash &lt;span class="caps"&gt;ZFS&lt;/span&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Requirement&lt;/th&gt;
&lt;th&gt;Example Hardware&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;AMD&lt;/span&gt; Ryzen 9 7900X or Intel i7-13700K&lt;/td&gt;
&lt;td&gt;12C/24T or 16C/24T&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;128 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;DDR5&lt;/span&gt;-5600 &lt;span class="caps"&gt;ECC&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Kingston 64 &lt;span class="caps"&gt;GB&lt;/span&gt; ×2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;1 &lt;span class="caps"&gt;TB&lt;/span&gt; NVMe boot + 4× 2 &lt;span class="caps"&gt;TB&lt;/span&gt; NVMe (&lt;span class="caps"&gt;ZFS&lt;/span&gt; &lt;span class="caps"&gt;RAID&lt;/span&gt;-Z1)&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;WD&lt;/span&gt; Black &lt;span class="caps"&gt;SN850X&lt;/span&gt;, Samsung 990 Pro&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;NIC&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Dual 10 GbE &lt;span class="caps"&gt;SFP&lt;/span&gt;+ or 25 GbE&lt;/td&gt;
&lt;td&gt;Mellanox ConnectX-4 Lx, Intel X710&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chassis&lt;/td&gt;
&lt;td&gt;2U short-depth rack case&lt;/td&gt;
&lt;td&gt;SilverStone &lt;span class="caps"&gt;RM23&lt;/span&gt;-502, Plinkusa &lt;span class="caps"&gt;IPC&lt;/span&gt;-2U&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Storage Architecture Deep&amp;nbsp;Dive&lt;/h2&gt;
&lt;h3&gt;&lt;span class="caps"&gt;ZFS&lt;/span&gt; vs &lt;span class="caps"&gt;LVM&lt;/span&gt;-thin vs&amp;nbsp;Ceph&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;ZFS&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;LVM&lt;/span&gt;-thin&lt;/th&gt;
&lt;th&gt;Ceph&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Snapshots&lt;/td&gt;
&lt;td&gt;Instant, space-efficient&lt;/td&gt;
&lt;td&gt;Copy-on-write, slower&lt;/td&gt;
&lt;td&gt;Distributed, instant&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compression&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;LZ4&lt;/span&gt;, Zstd, &lt;span class="caps"&gt;GZIP&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;None (on volume)&lt;/td&gt;
&lt;td&gt;None (on pool)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deduplication&lt;/td&gt;
&lt;td&gt;Yes (high &lt;span class="caps"&gt;RAM&lt;/span&gt; cost)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes (&lt;span class="caps"&gt;RADOS&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RAID&lt;/span&gt; options&lt;/td&gt;
&lt;td&gt;Mirror, &lt;span class="caps"&gt;RAID&lt;/span&gt;-Z1/2/3&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;RAID&lt;/span&gt; via mdadm&lt;/td&gt;
&lt;td&gt;Replicated or &lt;span class="caps"&gt;EC&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Homelab fit&lt;/td&gt;
&lt;td&gt;Boot pools, &lt;span class="caps"&gt;VM&lt;/span&gt; disks&lt;/td&gt;
&lt;td&gt;Simple setups&lt;/td&gt;
&lt;td&gt;3+ nodes only&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Recommendation for single-node labs:&lt;/strong&gt; Use &lt;span class="caps"&gt;ZFS&lt;/span&gt; on the boot disk (Proxmox installer defaults to this). Create a separate &lt;span class="caps"&gt;ZFS&lt;/span&gt; pool for &lt;span class="caps"&gt;VM&lt;/span&gt; storage on additional disks. For a 2-disk setup,&amp;nbsp;use &lt;code&gt;mirror&lt;/code&gt; for redundancy. For 4+&amp;nbsp;disks, &lt;code&gt;RAID-Z1&lt;/code&gt; gives better space&amp;nbsp;efficiency.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Create a ZFS pool on two SATA SSDs&lt;/span&gt;
zpool&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;vmstore&lt;span class="w"&gt; &lt;/span&gt;mirror&lt;span class="w"&gt; &lt;/span&gt;/dev/sda&lt;span class="w"&gt; &lt;/span&gt;/dev/sdb

&lt;span class="c1"&gt;# Set compression and enable auto-trim&lt;/span&gt;
zfs&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;compression&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;lz4&lt;span class="w"&gt; &lt;/span&gt;vmstore
zfs&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;atime&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;off&lt;span class="w"&gt; &lt;/span&gt;vmstore
zpool&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;autotrim&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;on&lt;span class="w"&gt; &lt;/span&gt;vmstore
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;NVMe Wear and&amp;nbsp;Endurance&lt;/h3&gt;
&lt;p&gt;Homelab write amplification is real—each &lt;span class="caps"&gt;VM&lt;/span&gt; snapshot, each container image pull, each &lt;span class="caps"&gt;ZFS&lt;/span&gt; scrub adds writes. For a boot drive, aim for a &lt;span class="caps"&gt;DRAM&lt;/span&gt;-equipped &lt;span class="caps"&gt;SSD&lt;/span&gt; with 300+ &lt;span class="caps"&gt;TBW&lt;/span&gt; (terabytes written). For a pure &lt;span class="caps"&gt;VM&lt;/span&gt; store, &lt;span class="caps"&gt;QLC&lt;/span&gt; drives like the Samsung 870 &lt;span class="caps"&gt;QVO&lt;/span&gt; are acceptable if you keep backups, but &lt;span class="caps"&gt;TLC&lt;/span&gt; drives (&lt;span class="caps"&gt;WD&lt;/span&gt; Blue &lt;span class="caps"&gt;SN580&lt;/span&gt;, Crucial P3) are&amp;nbsp;safer.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;span class="caps"&gt;SSD&lt;/span&gt; Tier&lt;/th&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Endurance (&lt;span class="caps"&gt;TBW&lt;/span&gt;)&lt;/th&gt;
&lt;th&gt;Price/&lt;span class="caps"&gt;TB&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Good For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Budget &lt;span class="caps"&gt;QLC&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Samsung 870 &lt;span class="caps"&gt;QVO&lt;/span&gt; 4 &lt;span class="caps"&gt;TB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1440 &lt;span class="caps"&gt;TBW&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$55&lt;/td&gt;
&lt;td&gt;Cold storage, backups&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mainstream &lt;span class="caps"&gt;TLC&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;WD&lt;/span&gt; Blue &lt;span class="caps"&gt;SN580&lt;/span&gt; 2 &lt;span class="caps"&gt;TB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;900 &lt;span class="caps"&gt;TBW&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$65&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;VM&lt;/span&gt; store, boot&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;High-end &lt;span class="caps"&gt;TLC&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Samsung 990 Pro 2 &lt;span class="caps"&gt;TB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1200 &lt;span class="caps"&gt;TBW&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$110&lt;/td&gt;
&lt;td&gt;Heavy write workloads&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Enterprise U.2&lt;/td&gt;
&lt;td&gt;Intel P4510 2 &lt;span class="caps"&gt;TB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;4200 &lt;span class="caps"&gt;TBW&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$80 used&lt;/td&gt;
&lt;td&gt;Ceph, databases&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Networking&amp;nbsp;Requirements&lt;/h2&gt;
&lt;h3&gt;The &lt;span class="caps"&gt;NIC&lt;/span&gt;&amp;nbsp;Hierarchy&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;span class="caps"&gt;NIC&lt;/span&gt; Type&lt;/th&gt;
&lt;th&gt;Speed&lt;/th&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;Price (Used)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Realtek &lt;span class="caps"&gt;RTL8111&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;1 GbE&lt;/td&gt;
&lt;td&gt;Basic, works &lt;span class="caps"&gt;OOB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$0 (built-in)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Intel i210/i211&lt;/td&gt;
&lt;td&gt;1 GbE&lt;/td&gt;
&lt;td&gt;Reliable, good driver&lt;/td&gt;
&lt;td&gt;$0 (built-in)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Intel i226-V&lt;/td&gt;
&lt;td&gt;2.5 GbE&lt;/td&gt;
&lt;td&gt;Mini PCs, modern boards&lt;/td&gt;
&lt;td&gt;$0 (built-in)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Intel X520-&lt;span class="caps"&gt;DA2&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;10 GbE &lt;span class="caps"&gt;SFP&lt;/span&gt;+&lt;/td&gt;
&lt;td&gt;Workhorse &lt;span class="caps"&gt;NIC&lt;/span&gt;, &lt;span class="caps"&gt;SR&lt;/span&gt;-&lt;span class="caps"&gt;IOV&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$25–$40&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mellanox ConnectX-3&lt;/td&gt;
&lt;td&gt;10 GbE &lt;span class="caps"&gt;SFP&lt;/span&gt;+&lt;/td&gt;
&lt;td&gt;Cheapest 10 GbE, RoCE&lt;/td&gt;
&lt;td&gt;$20–$30&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Intel X710-&lt;span class="caps"&gt;DA2&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;10 GbE &lt;span class="caps"&gt;SFP&lt;/span&gt;+&lt;/td&gt;
&lt;td&gt;Modern, stable, power-efficient&lt;/td&gt;
&lt;td&gt;$60–$90&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mellanox ConnectX-4&lt;/td&gt;
&lt;td&gt;25 GbE &lt;span class="caps"&gt;SFP28&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Future-proofing, &lt;span class="caps"&gt;RDMA&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;$80–$120&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Proxmox networking tip:&lt;/strong&gt; Use Linux bridges&amp;nbsp;(&lt;code&gt;vmbr0&lt;/code&gt;, &lt;code&gt;vmbr1&lt;/code&gt;) for &lt;span class="caps"&gt;VM&lt;/span&gt; connectivity. For VLANs, set the bridge as &lt;span class="caps"&gt;VLAN&lt;/span&gt;-aware and tag individual&amp;nbsp;VMs:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# /etc/network/interfaces snippet&lt;/span&gt;
auto&lt;span class="w"&gt; &lt;/span&gt;vmbr0
iface&lt;span class="w"&gt; &lt;/span&gt;vmbr0&lt;span class="w"&gt; &lt;/span&gt;inet&lt;span class="w"&gt; &lt;/span&gt;static
&lt;span class="w"&gt;    &lt;/span&gt;address&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.1.10/24
&lt;span class="w"&gt;    &lt;/span&gt;gateway&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.1.1
&lt;span class="w"&gt;    &lt;/span&gt;bridge-ports&lt;span class="w"&gt; &lt;/span&gt;eno1
&lt;span class="w"&gt;    &lt;/span&gt;bridge-vlan-aware&lt;span class="w"&gt; &lt;/span&gt;yes
&lt;span class="w"&gt;    &lt;/span&gt;bridge-vids&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;-4094

&lt;span class="c1"&gt;# Then in a VM config, add:&lt;/span&gt;
&lt;span class="c1"&gt;# net0: virtio,bridge=vmbr0,tag=10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Frequently Asked&amp;nbsp;Questions&lt;/h2&gt;
&lt;h3&gt;Is &lt;span class="caps"&gt;ECC&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; Required for&amp;nbsp;Proxmox?&lt;/h3&gt;
&lt;p&gt;No, but strongly recommended for &lt;span class="caps"&gt;ZFS&lt;/span&gt;. &lt;span class="caps"&gt;ZFS&lt;/span&gt; checksums protect against bit rot, but if corrupted data sits in &lt;span class="caps"&gt;RAM&lt;/span&gt; before being written, &lt;span class="caps"&gt;ZFS&lt;/span&gt; will happily checksum the corrupted data. &lt;span class="caps"&gt;ECC&lt;/span&gt; prevents this &amp;#8220;Scrub of Death.&amp;#8221; For non-&lt;span class="caps"&gt;ZFS&lt;/span&gt; setups (&lt;span class="caps"&gt;LVM&lt;/span&gt;-thin), non-&lt;span class="caps"&gt;ECC&lt;/span&gt; is&amp;nbsp;acceptable.&lt;/p&gt;
&lt;h3&gt;Can I Run Proxmox on a Raspberry&amp;nbsp;Pi?&lt;/h3&gt;
&lt;p&gt;No. Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; requires x86_64. For &lt;span class="caps"&gt;ARM&lt;/span&gt; clusters, look into Kubernetes on Raspberry Pi or Proxmox&amp;#8217;s experimental &lt;span class="caps"&gt;ARM&lt;/span&gt; port (not&amp;nbsp;production-ready).&lt;/p&gt;
&lt;h3&gt;How Much Power Does a Proxmox Homelab&amp;nbsp;Use?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Mini &lt;span class="caps"&gt;PC&lt;/span&gt; (N100): 6–15 W&amp;nbsp;idle&lt;/li&gt;
&lt;li&gt;Tower build (i5-12400): 35–60 W&amp;nbsp;idle&lt;/li&gt;
&lt;li&gt;Used rack server (R730): 120–180 W&amp;nbsp;idle&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At $0.15/kWh, an R730 costs $160–$240/year in electricity alone. A mini &lt;span class="caps"&gt;PC&lt;/span&gt; costs&amp;nbsp;$8–$20/year.&lt;/p&gt;
&lt;h3&gt;Do I Need a &lt;span class="caps"&gt;RAID&lt;/span&gt;&amp;nbsp;Controller?&lt;/h3&gt;
&lt;p&gt;No. Proxmox prefers &lt;span class="caps"&gt;HBA&lt;/span&gt; (Host Bus Adapter) or direct &lt;span class="caps"&gt;SATA&lt;/span&gt;/NVMe. Avoid consumer &lt;span class="caps"&gt;RAID&lt;/span&gt; controllers (fake &lt;span class="caps"&gt;RAID&lt;/span&gt;) and avoid hardware &lt;span class="caps"&gt;RAID&lt;/span&gt; for &lt;span class="caps"&gt;ZFS&lt;/span&gt;—&lt;span class="caps"&gt;ZFS&lt;/span&gt; wants direct disk access. Use an &lt;span class="caps"&gt;LSI&lt;/span&gt; 9211-8i (flashed to &lt;span class="caps"&gt;IT&lt;/span&gt; mode) or equivalent for &lt;span class="caps"&gt;SAS&lt;/span&gt;/&lt;span class="caps"&gt;SATA&lt;/span&gt;&amp;nbsp;drives.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; 8.2 runs on almost any 64-bit hardware, but a &lt;em&gt;good&lt;/em&gt; homelab experience requires at least an Intel N100 with 16 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; and an NVMe &lt;span class="caps"&gt;SSD&lt;/span&gt;. For serious multi-&lt;span class="caps"&gt;VM&lt;/span&gt; workloads, target 32–64 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, a 6-core modern &lt;span class="caps"&gt;CPU&lt;/span&gt;, and &lt;span class="caps"&gt;ZFS&lt;/span&gt; on SSDs. The used enterprise market (Dell R730, &lt;span class="caps"&gt;HP&lt;/span&gt; DL380p) offers unbeatable compute-per-dollar but trades noise and power draw for&amp;nbsp;performance.&lt;/p&gt;
&lt;h3&gt;Our&amp;nbsp;Recommendations&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Budget&lt;/th&gt;
&lt;th&gt;Best Build&lt;/th&gt;
&lt;th&gt;Expected VMs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;$250&lt;/td&gt;
&lt;td&gt;Intel N100 mini &lt;span class="caps"&gt;PC&lt;/span&gt; + 16 &lt;span class="caps"&gt;GB&lt;/span&gt; + 512 &lt;span class="caps"&gt;GB&lt;/span&gt; NVMe&lt;/td&gt;
&lt;td&gt;3–5 &lt;span class="caps"&gt;LXC&lt;/span&gt;, 1–2 VMs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$600&lt;/td&gt;
&lt;td&gt;i5-12400 tower + 32 &lt;span class="caps"&gt;GB&lt;/span&gt; + 2×4 &lt;span class="caps"&gt;TB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;8–10 VMs, &lt;span class="caps"&gt;ZFS&lt;/span&gt;, router&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$500 used&lt;/td&gt;
&lt;td&gt;Dell R730 + 128 &lt;span class="caps"&gt;GB&lt;/span&gt; + 4×1 &lt;span class="caps"&gt;TB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;15–20 VMs, Ceph-ready&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$1500&lt;/td&gt;
&lt;td&gt;Ryzen 9 7900X + 128 &lt;span class="caps"&gt;GB&lt;/span&gt; + 4×2 &lt;span class="caps"&gt;TB&lt;/span&gt; NVMe&lt;/td&gt;
&lt;td&gt;20+ VMs, 10 GbE, all-flash&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mini PCs:&lt;/strong&gt; Minisforum, Beelink, GMKtec (Amazon/AliExpress affiliate&amp;nbsp;programs)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;:&lt;/strong&gt; Crucial, Kingston (Amazon&amp;nbsp;Associates)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SSDs:&lt;/strong&gt; Samsung, &lt;span class="caps"&gt;WD&lt;/span&gt;, Intel (Amazon&amp;nbsp;Associates)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Used servers:&lt;/strong&gt; SaveMyServer, TekBoost, eBay Partner&amp;nbsp;Network&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;NICs:&lt;/strong&gt; Intel, Mellanox (Amazon&amp;nbsp;Associates)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;hardware-tiers&lt;/code&gt; → related: &amp;#8220;mini-pc-vs-rack-server&amp;#8221;&amp;nbsp;comparison&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage-architecture&lt;/code&gt; → setup:&amp;nbsp;&amp;#8220;proxmox-zfs-setup-guide&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;networking&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;homelab-networking-basics&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;used-servers&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;used-server-hardware-for-homelab&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] What&amp;#8217;s your Proxmox hardware setup? Share your build specs&amp;nbsp;below!&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for our monthly homelab hardware deals roundup and new build&amp;nbsp;guides.&lt;/li&gt;
&lt;li&gt;[internal_link] Ready to install? Read our &lt;a href="https://steadypub.com/2026/06/proxmox-beginner-guide-2026/"&gt;Proxmox beginner guide&lt;/a&gt;&amp;nbsp;next.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Tool Guides"/><category term="homelab"/><category term="proxmox hardware requirements 2026"/><category term="self-hosted"/></entry><entry><title>Proxmox vs ESXi: A Head-to-Head Comparison for Homelab Virtualization</title><link href="https://steadypub.com/2026/06/proxmox-vs-esxi/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T10:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/proxmox-vs-esxi/</id><summary type="html">&lt;p&gt;Compare Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; and VMware ESXi for homelab use. Licensing, performance, features, and migration paths after Broadcom&amp;#8217;s VMware&amp;nbsp;changes.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~12 minutes&lt;br&gt;
&lt;strong&gt;Audience:&lt;/strong&gt; Homelabbers choosing between Proxmox and ESXi for&amp;nbsp;virtualization&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The Landscape in&amp;nbsp;2026&lt;/h2&gt;
&lt;p&gt;VMware ESXi dominated enterprise virtualization for two decades. In 2023, Broadcom acquired VMware and killed the free ESXi tier, triggering a mass exodus. Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; — open-source, free, and feature-rich — has become the default choice for new homelab&amp;nbsp;builds.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Architecture&amp;nbsp;Comparison&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;VMware ESXi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hypervisor&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;KVM&lt;/span&gt; (full VMs) + &lt;span class="caps"&gt;LXC&lt;/span&gt; (containers)&lt;/td&gt;
&lt;td&gt;Type-1 bare metal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Containers&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Native &lt;span class="caps"&gt;LXC&lt;/span&gt; support&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Web &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Built-in, no client needed&lt;/td&gt;
&lt;td&gt;vSphere Client (separate)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;API&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;REST&lt;/span&gt; &lt;span class="caps"&gt;API&lt;/span&gt; (full)&lt;/td&gt;
&lt;td&gt;vSphere &lt;span class="caps"&gt;API&lt;/span&gt; (limited in free)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Clustering&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Up to 32 nodes (free)&lt;/td&gt;
&lt;td&gt;vCenter required (paid)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;ZFS&lt;/span&gt;, Ceph, &lt;span class="caps"&gt;LVM&lt;/span&gt;, &lt;span class="caps"&gt;NFS&lt;/span&gt;, iSCSI&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;VMFS&lt;/span&gt;, &lt;span class="caps"&gt;NFS&lt;/span&gt;, iSCSI, vSAN (paid)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Backup&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Built-in vzdump&lt;/td&gt;
&lt;td&gt;vSphere Data Protection (paid)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;High Availability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Built-in (3+ nodes)&lt;/td&gt;
&lt;td&gt;vSphere &lt;span class="caps"&gt;HA&lt;/span&gt; (paid)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Live Migration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;KVM&lt;/span&gt; live migration (shared storage)&lt;/td&gt;
&lt;td&gt;vMotion (paid)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Guest &lt;span class="caps"&gt;OS&lt;/span&gt; support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Linux, Windows, &lt;span class="caps"&gt;BSD&lt;/span&gt;, Solaris&lt;/td&gt;
&lt;td&gt;Linux, Windows, &lt;span class="caps"&gt;BSD&lt;/span&gt;, macOS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PCIe passthrough&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Full &lt;span class="caps"&gt;GPU&lt;/span&gt;/PCIe passthrough&lt;/td&gt;
&lt;td&gt;Full &lt;span class="caps"&gt;GPU&lt;/span&gt;/PCIe passthrough&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Nested virtualization&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Supported&lt;/td&gt;
&lt;td&gt;Supported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Max VMs per host&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;100+ (depends on &lt;span class="caps"&gt;RAM&lt;/span&gt;)&lt;/td&gt;
&lt;td&gt;100+ (depends on &lt;span class="caps"&gt;RAM&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Max vCPUs per &lt;span class="caps"&gt;VM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;768&lt;/td&gt;
&lt;td&gt;768 (vSphere 8)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Max &lt;span class="caps"&gt;RAM&lt;/span&gt; per &lt;span class="caps"&gt;VM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;24TB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;24TB&lt;/span&gt; (vSphere 8)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Licensing &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;Cost&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Edition&lt;/th&gt;
&lt;th&gt;Proxmox&lt;/th&gt;
&lt;th&gt;ESXi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Free tier&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fully functional, no limits&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Discontinued Dec 2023&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Paid support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~$95–$380/year per 2 CPUs&lt;/td&gt;
&lt;td&gt;~$1,200+–$4,500/&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Trial&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Unlimited (free anyway)&lt;/td&gt;
&lt;td&gt;60-day vSphere trial&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Subscription&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Optional; no feature gating&lt;/td&gt;
&lt;td&gt;Required for most features&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Key point:&lt;/strong&gt; Proxmox&amp;#8217;s free version is the &lt;strong&gt;full product&lt;/strong&gt;. ESXi free is dead, and even paid VMware is now bundled into expensive&amp;nbsp;suites.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Performance&amp;nbsp;Benchmarks&lt;/h2&gt;
&lt;h3&gt;&lt;span class="caps"&gt;KVM&lt;/span&gt; vs ESXi&amp;nbsp;Overhead&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test&lt;/th&gt;
&lt;th&gt;Proxmox (&lt;span class="caps"&gt;KVM&lt;/span&gt;)&lt;/th&gt;
&lt;th&gt;ESXi&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt; overhead&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~1–2%&lt;/td&gt;
&lt;td&gt;~1–2%&lt;/td&gt;
&lt;td&gt;Negligible difference&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Memory overhead&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~2–4%&lt;/td&gt;
&lt;td&gt;~2–4%&lt;/td&gt;
&lt;td&gt;Both efficient&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Disk I/O (virtio)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~95% bare metal&lt;/td&gt;
&lt;td&gt;~92% bare metal&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;KVM&lt;/span&gt; virtio slightly faster&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Network I/O (virtio-net)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~90% bare metal&lt;/td&gt;
&lt;td&gt;~88% bare metal&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;KVM&lt;/span&gt; virtio-net optimized&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;VM&lt;/span&gt; boot time&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;12s&lt;/td&gt;
&lt;td&gt;10s&lt;/td&gt;
&lt;td&gt;ESXi slightly faster&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Live migration downtime&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;50–100ms&lt;/td&gt;
&lt;td&gt;0–50ms&lt;/td&gt;
&lt;td&gt;vMotion more polished&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;em&gt;Benchmarks from Phoronix and community testing on identical hardware (Intel i5-12400, &lt;span class="caps"&gt;32GB&lt;/span&gt; &lt;span class="caps"&gt;DDR4&lt;/span&gt;, NVMe &lt;span class="caps"&gt;SSD&lt;/span&gt;)&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Storage&amp;nbsp;Comparison&lt;/h2&gt;
&lt;h3&gt;Proxmox Storage&amp;nbsp;Options&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Storage Type&lt;/th&gt;
&lt;th&gt;Performance&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;ZFS&lt;/span&gt; (local)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Excellent&lt;/td&gt;
&lt;td&gt;Snapshots, compression, &lt;span class="caps"&gt;RAID&lt;/span&gt;-Z&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;LVM&lt;/span&gt;-thin&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;td&gt;Simple local storage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ceph&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Good (distributed)&lt;/td&gt;
&lt;td&gt;Multi-node shared storage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;NFS&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Moderate&lt;/td&gt;
&lt;td&gt;Shared storage, backups&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;iSCSI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Moderate&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;SAN&lt;/span&gt; integration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Proxmox Backup Server&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;Dedicated backup target&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;ESXi Storage&amp;nbsp;Options&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Storage Type&lt;/th&gt;
&lt;th&gt;Performance&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;VMFS&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;td&gt;Local disks, vSAN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;NFS&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Moderate&lt;/td&gt;
&lt;td&gt;Shared storage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;iSCSI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Moderate&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;SAN&lt;/span&gt; integration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;vSAN&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Good (distributed)&lt;/td&gt;
&lt;td&gt;Hyperconverged (paid)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Web &lt;span class="caps"&gt;UI&lt;/span&gt;&amp;nbsp;Comparison&lt;/h2&gt;
&lt;h3&gt;Proxmox Web &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Single pane:&lt;/strong&gt; VMs, containers, storage, backups,&amp;nbsp;clustering&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;NoVNC console:&lt;/strong&gt; Built-in browser&amp;nbsp;console&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;SPICE&lt;/span&gt; console:&lt;/strong&gt; High-performance remote&amp;nbsp;display&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;REST&lt;/span&gt; &lt;span class="caps"&gt;API&lt;/span&gt;:&lt;/strong&gt; Every &lt;span class="caps"&gt;UI&lt;/span&gt; action is &lt;span class="caps"&gt;API&lt;/span&gt;-callable&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dark mode:&lt;/strong&gt; Native dark&amp;nbsp;theme&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Responsive:&lt;/strong&gt; Works on&amp;nbsp;tablets&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;ESXi Host Client&amp;nbsp;(Free/Embedded)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Limited scope:&lt;/strong&gt; Single host&amp;nbsp;only&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;vSphere Client:&lt;/strong&gt; Requires Windows or&amp;nbsp;vCenter&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flash deprecation:&lt;/strong&gt; Old Web Client killed in vSphere&amp;nbsp;7&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;HTML5&lt;/span&gt; Host Client:&lt;/strong&gt; Functional but&amp;nbsp;limited&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Docker &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; Container&amp;nbsp;Support&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Proxmox&lt;/th&gt;
&lt;th&gt;ESXi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;LXC&lt;/span&gt; containers&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Native, first-class&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Docker in &lt;span class="caps"&gt;VM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Works perfectly&lt;/td&gt;
&lt;td&gt;Works perfectly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Docker in &lt;span class="caps"&gt;LXC&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Supported (privileged/unprivileged)&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Kubernetes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;VMs or &lt;span class="caps"&gt;LXC&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;VMs only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Turnkey templates&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;100+ pre-built &lt;span class="caps"&gt;LXC&lt;/span&gt; templates&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Proxmox&amp;#8217;s &lt;span class="caps"&gt;LXC&lt;/span&gt; support is a &lt;strong&gt;major advantage&lt;/strong&gt; for homelabbers. &lt;span class="caps"&gt;LXC&lt;/span&gt; containers use a fraction of the resources of a full &lt;span class="caps"&gt;VM&lt;/span&gt;, making them ideal for running multiple&amp;nbsp;services.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Backup &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;Recovery&lt;/h2&gt;
&lt;h3&gt;Proxmox&amp;nbsp;vzdump&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Full VM backup&lt;/span&gt;
vzdump&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--mode&lt;span class="w"&gt; &lt;/span&gt;snapshot&lt;span class="w"&gt; &lt;/span&gt;--compress&lt;span class="w"&gt; &lt;/span&gt;zstd&lt;span class="w"&gt; &lt;/span&gt;--storage&lt;span class="w"&gt; &lt;/span&gt;local-backup

&lt;span class="c1"&gt;# Backup all VMs&lt;/span&gt;
vzdump&lt;span class="w"&gt; &lt;/span&gt;--all&lt;span class="w"&gt; &lt;/span&gt;--mode&lt;span class="w"&gt; &lt;/span&gt;snapshot&lt;span class="w"&gt; &lt;/span&gt;--compress&lt;span class="w"&gt; &lt;/span&gt;zstd

&lt;span class="c1"&gt;# Restore&lt;/span&gt;
qmrestore&lt;span class="w"&gt; &lt;/span&gt;/var/lib/vz/dump/vzdump-qemu-9000-2026_06_05-00_00_00.vma.zst&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;ESXi (Paid&amp;nbsp;Only)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# ESXi free had no backup API&lt;/span&gt;
&lt;span class="c1"&gt;# Required paid Veeam, vSphere Data Protection, or ghettoVCB&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Proxmox Backup Server&lt;/strong&gt; (free) is a dedicated backup solution that supports deduplication, encryption, and incremental&amp;nbsp;backups.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;When to Choose&amp;nbsp;Proxmox&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Homelabbers, small businesses, budget-conscious&amp;nbsp;users&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ideal if:&lt;/strong&gt; You want free, full-featured virtualization with no&amp;nbsp;limits&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Strength:&lt;/strong&gt; Free, open-source, &lt;span class="caps"&gt;LXC&lt;/span&gt; containers, &lt;span class="caps"&gt;ZFS&lt;/span&gt;, Ceph,&amp;nbsp;community&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tradeoff:&lt;/strong&gt; Less enterprise polish than&amp;nbsp;VMware&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;When to Choose ESXi&amp;nbsp;(Paid)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Enterprises with existing VMware&amp;nbsp;infrastructure&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ideal if:&lt;/strong&gt; You need vMotion, &lt;span class="caps"&gt;DRS&lt;/span&gt;, vSAN, and enterprise&amp;nbsp;support&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Strength:&lt;/strong&gt; Mature ecosystem, enterprise certifications,&amp;nbsp;vMotion&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tradeoff:&lt;/strong&gt; Extremely expensive&amp;nbsp;post-Broadcom&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Migration Path: ESXi to&amp;nbsp;Proxmox&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Step 1: Export VM from ESXi&lt;/span&gt;
ovftool&lt;span class="w"&gt; &lt;/span&gt;vi://root@esxi-host.local/VM_Name&lt;span class="w"&gt; &lt;/span&gt;/tmp/VM_Name.ova

&lt;span class="c1"&gt;# Step 2: Import to Proxmox&lt;/span&gt;
qm&lt;span class="w"&gt; &lt;/span&gt;importovf&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/tmp/VM_Name.ova&lt;span class="w"&gt; &lt;/span&gt;local-lvm

&lt;span class="c1"&gt;# Step 3: Reconfigure networking&lt;/span&gt;
&lt;span class="c1"&gt;# Edit /etc/network/interfaces to match ESXi port groups&lt;/span&gt;

&lt;span class="c1"&gt;# Step 4: Install QEMU Guest Agent&lt;/span&gt;
&lt;span class="c1"&gt;# Linux: apt install qemu-guest-agent&lt;/span&gt;
&lt;span class="c1"&gt;# Windows: Install from virtio-win ISO&lt;/span&gt;

&lt;span class="c1"&gt;# Step 5: Start VM and verify&lt;/span&gt;
qm&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;9000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; is the &lt;strong&gt;clear winner for homelabbers&lt;/strong&gt; in 2026. ESXi free is dead, and paid VMware is now prohibitively expensive for most users. Proxmox offers equivalent performance, superior container support, and a vibrant open-source community — all at zero&amp;nbsp;cost.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Download Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; &lt;span class="caps"&gt;ISO&lt;/span&gt;:&lt;/strong&gt;&amp;nbsp;https://www.proxmox.com/en/downloads&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Install on bare metal or &lt;span class="caps"&gt;VM&lt;/span&gt;&lt;/strong&gt; to&amp;nbsp;test&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Read our Proxmox beginner guide&lt;/strong&gt; for a complete setup&amp;nbsp;walkthrough&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mini PCs:&lt;/strong&gt; Minisforum &lt;span class="caps"&gt;MS&lt;/span&gt;-01, Beelink &lt;span class="caps"&gt;SER7&lt;/span&gt;, Intel &lt;span class="caps"&gt;NUC&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Storage HBAs:&lt;/strong&gt; &lt;span class="caps"&gt;LSI&lt;/span&gt; 9211-8i, Broadcom&amp;nbsp;9300-8i&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;NICs:&lt;/strong&gt; Intel i225/i226, Mellanox&amp;nbsp;ConnectX-3&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;UPS&lt;/span&gt;:&lt;/strong&gt; &lt;span class="caps"&gt;APC&lt;/span&gt; Back-&lt;span class="caps"&gt;UPS&lt;/span&gt; Pro, CyberPower &lt;span class="caps"&gt;CP1500&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Networking:&lt;/strong&gt; UniFi, &lt;span class="caps"&gt;TP&lt;/span&gt;-Link&amp;nbsp;Omada&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal&amp;nbsp;Linking&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;proxmox-guide&lt;/code&gt; → &lt;code&gt;proxmox-beginner-guide-2026.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;esxi-alternative&lt;/code&gt; → &lt;code&gt;vmware-esxi-free-alternative.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hardware&lt;/code&gt; → &lt;code&gt;best-mini-pc-for-homelab.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt; → &lt;code&gt;proxmox-zfs-storage-guide.md&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Did you migrate from ESXi to Proxmox?&lt;/strong&gt; Share your experience in the&amp;nbsp;comments.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subscribe&lt;/strong&gt; for more homelab virtualization guides and migration&amp;nbsp;tutorials.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Comparisons"/><category term="proxmox vs esxi"/><category term="homelab virtualization"/><category term="proxmox vs vmware"/><category term="self-hosted hypervisor"/><category term="kvm vs esxi"/></entry><entry><title>Proxmox vs ESXi for Homelab: The Honest 2026 Comparison</title><link href="https://steadypub.com/2026/06/proxmox-vs-esxi-for-homelab/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T10:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/proxmox-vs-esxi-for-homelab/</id><summary type="html">&lt;p&gt;A side-by-side comparison of Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; and VMware ESXi for homelab use. Covers licensing, performance, features, community support, and the Broadcom&amp;nbsp;fallout.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~15 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab and self-hosting&amp;nbsp;enthusiasts&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; and VMware ESXi are the two dominant hypervisors for homelab virtualization. For over a decade, ESXi was the default choice due to its enterprise pedigree and free tier. In 2026, that has changed. Broadcom&amp;#8217;s acquisition of VMware eliminated the free ESXi license, raised prices, and alienated the homelab community. Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; — open-source, Debian-based, and fully free — has become the new standard. This comparison evaluates both platforms on the criteria that matter to homelab&amp;nbsp;operators.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Key Differences at a&amp;nbsp;Glance&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;VMware ESXi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;License&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;AGPL&lt;/span&gt; (fully free)&lt;/td&gt;
&lt;td&gt;Commercial (subscription required)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;td&gt;$350+/year (minimum)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hypervisor type&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Type 1 (&lt;span class="caps"&gt;KVM&lt;/span&gt;) + &lt;span class="caps"&gt;LXC&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Type 1 (bare metal)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Web &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Built-in, no plugins needed&lt;/td&gt;
&lt;td&gt;vSphere Client or Host Client&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Container support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Native &lt;span class="caps"&gt;LXC&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;None (requires Tanzu/VMware addons)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;ZFS&lt;/span&gt;, Ceph, &lt;span class="caps"&gt;LVM&lt;/span&gt;, &lt;span class="caps"&gt;NFS&lt;/span&gt;, iSCSI&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;VMFS&lt;/span&gt;, &lt;span class="caps"&gt;NFS&lt;/span&gt;, iSCSI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Backup&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Built-in vzdump&lt;/td&gt;
&lt;td&gt;vSphere Data Protection (paid)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Clustering&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; Cluster (free)&lt;/td&gt;
&lt;td&gt;vCenter Server (paid)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Community size&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Large, growing rapidly&lt;/td&gt;
&lt;td&gt;Shrinking in homelab space&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hardware compatibility&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Very broad (any x86_64)&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;HCL&lt;/span&gt; restricted; &lt;span class="caps"&gt;DIY&lt;/span&gt; builds often unsupported&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;: The Open-Source&amp;nbsp;Winner&lt;/h2&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Zero cost&lt;/strong&gt;: No licensing fees, no feature gates, no subscription required for&amp;nbsp;updates&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;KVM&lt;/span&gt; + &lt;span class="caps"&gt;LXC&lt;/span&gt;&lt;/strong&gt;: Run full VMs and lightweight containers on the same&amp;nbsp;host&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;ZFS&lt;/span&gt; native&lt;/strong&gt;: Built-in &lt;span class="caps"&gt;ZFS&lt;/span&gt; support with snapshots, compression, and&amp;nbsp;deduplication&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ceph integration&lt;/strong&gt;: Build a hyperconverged cluster with distributed&amp;nbsp;storage&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Active development&lt;/strong&gt;: Quarterly releases, responsive forums, and extensive&amp;nbsp;documentation&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Broadcom-proof&lt;/strong&gt;: No risk of sudden licensing changes or product&amp;nbsp;discontinuation&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Learning curve&lt;/strong&gt;: The &lt;span class="caps"&gt;UI&lt;/span&gt; is powerful but less polished than&amp;nbsp;vSphere&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No official enterprise support&lt;/strong&gt; (without subscription): The community forum is the primary support&amp;nbsp;channel&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Backup is file-based&lt;/strong&gt;: vzdump produces tar archives; incremental backup requires Proxmox Backup&amp;nbsp;Server&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;p&gt;Homelab operators, small businesses, and anyone who values freedom, cost control, and container&amp;nbsp;flexibility.&lt;/p&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;p&gt;Free. Optional subscription (€95/year per &lt;span class="caps"&gt;CPU&lt;/span&gt; socket) provides enterprise repository access and support. The no-subscription repository is fully&amp;nbsp;functional.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;VMware ESXi: The Enterprise&amp;nbsp;Legacy&lt;/h2&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Polished &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/strong&gt;: vSphere Client is the industry standard for datacenter&amp;nbsp;management&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enterprise ecosystem&lt;/strong&gt;: Integrates with vSAN, &lt;span class="caps"&gt;NSX&lt;/span&gt;, vRealize, and thousands of third-party&amp;nbsp;tools&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Performance&lt;/strong&gt;: ESXi has a mature, optimized scheduler and memory&amp;nbsp;management&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Certification value&lt;/strong&gt;: VMware certifications (&lt;span class="caps"&gt;VCP&lt;/span&gt;, &lt;span class="caps"&gt;VCAP&lt;/span&gt;) are still sought-after in enterprise &lt;span class="caps"&gt;IT&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Large existing knowledge base&lt;/strong&gt;: Decades of documentation, blog posts, and video&amp;nbsp;tutorials&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No free tier&lt;/strong&gt;: The ESXi free license was eliminated in 2024. Minimum cost is now hundreds of dollars per&amp;nbsp;year&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hardware compatibility list (&lt;span class="caps"&gt;HCL&lt;/span&gt;)&lt;/strong&gt;: Many consumer NICs, &lt;span class="caps"&gt;SATA&lt;/span&gt; controllers, and &lt;span class="caps"&gt;RAID&lt;/span&gt; cards are&amp;nbsp;unsupported&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No native containers&lt;/strong&gt;: &lt;span class="caps"&gt;LXC&lt;/span&gt;/Docker containers require a &lt;span class="caps"&gt;VM&lt;/span&gt; or separate&amp;nbsp;host&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Community exodus&lt;/strong&gt;: The homelab community is migrating to Proxmox, reducing peer&amp;nbsp;support&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vendor lock-in&lt;/strong&gt;: VMware file formats (&lt;span class="caps"&gt;VMDK&lt;/span&gt;) and APIs are&amp;nbsp;proprietary&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;p&gt;Enterprise environments with existing VMware investments, or users pursuing VMware&amp;nbsp;certifications.&lt;/p&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;p&gt;VMware Cloud Foundation: $350+/year per core. vSphere Standard: $1,300+/year per &lt;span class="caps"&gt;CPU&lt;/span&gt;. No free homelab option&amp;nbsp;remains.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Detailed&amp;nbsp;Comparison&lt;/h2&gt;
&lt;h3&gt;Scenario 1: Beginner&amp;nbsp;Homelab&lt;/h3&gt;
&lt;p&gt;A user with an old desktop, 16 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, and a 1 &lt;span class="caps"&gt;TB&lt;/span&gt; &lt;span class="caps"&gt;SSD&lt;/span&gt; wants to run a few VMs and learn&amp;nbsp;virtualization.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Proxmox&lt;/strong&gt;: Install from a &lt;span class="caps"&gt;USB&lt;/span&gt; stick in 10 minutes. Create a &lt;span class="caps"&gt;VM&lt;/span&gt; via the web &lt;span class="caps"&gt;UI&lt;/span&gt;. No license key, no restrictions. Native &lt;span class="caps"&gt;LXC&lt;/span&gt; containers run Docker apps with minimal&amp;nbsp;overhead.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ESXi&lt;/strong&gt;: Download the installer (requires Broadcom account). Check the &lt;span class="caps"&gt;HCL&lt;/span&gt; for hardware compatibility. Install and enter a paid license key. Create a datastore and &lt;span class="caps"&gt;VM&lt;/span&gt;. No container&amp;nbsp;support.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Winner&lt;/strong&gt;: Proxmox. Free, no hardware restrictions, and &lt;span class="caps"&gt;LXC&lt;/span&gt;&amp;nbsp;support.&lt;/p&gt;
&lt;h3&gt;Scenario 2: Small Business&amp;nbsp;Server&lt;/h3&gt;
&lt;p&gt;A 5-person business needs a virtualization host for a Windows domain controller, a file server, and a web&amp;nbsp;app.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Proxmox&lt;/strong&gt;: Run all three on a single host. Use &lt;span class="caps"&gt;ZFS&lt;/span&gt; for the file server. Backup with vzdump to a &lt;span class="caps"&gt;NAS&lt;/span&gt;. Scale to a 2-node cluster&amp;nbsp;later.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ESXi&lt;/strong&gt;: Requires vSphere Standard or Essentials Plus. vCenter is needed for centralized management. Backup requires Veeam or similar&amp;nbsp;(paid).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Winner&lt;/strong&gt;: Proxmox. Cost savings of&amp;nbsp;$3,000+/year.&lt;/p&gt;
&lt;h3&gt;Scenario 3: Certification&amp;nbsp;Study&lt;/h3&gt;
&lt;p&gt;An &lt;span class="caps"&gt;IT&lt;/span&gt; professional studying for the &lt;span class="caps"&gt;VCP&lt;/span&gt;-&lt;span class="caps"&gt;DCV&lt;/span&gt; exam needs hands-on VMware&amp;nbsp;experience.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Proxmox&lt;/strong&gt;: Does not help with VMware certification. Concepts are similar but the &lt;span class="caps"&gt;UI&lt;/span&gt; and &lt;span class="caps"&gt;CLI&lt;/span&gt; are&amp;nbsp;different.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ESXi&lt;/strong&gt;: Required for VMware certification labs. Consider the VMware Workstation or Fusion evaluation, or a temporary &lt;span class="caps"&gt;VMUG&lt;/span&gt; Advantage subscription&amp;nbsp;($200/year).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Winner&lt;/strong&gt;: ESXi (but only for certification&amp;nbsp;purposes).&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Migration: ESXi to&amp;nbsp;Proxmox&lt;/h2&gt;
&lt;h3&gt;Step 1: Export VMs from&amp;nbsp;ESXi&lt;/h3&gt;
&lt;p&gt;Power off the &lt;span class="caps"&gt;VM&lt;/span&gt; and export as &lt;span class="caps"&gt;OVA&lt;/span&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Via ESXi Host Client&lt;/span&gt;
&lt;span class="c1"&gt;# Virtual Machines → Select VM → Actions → Export → Download OVA&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Step 2: Import to&amp;nbsp;Proxmox&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Upload the OVA to Proxmox (via SCP or the web UI)&lt;/span&gt;
&lt;span class="c1"&gt;# In Proxmox shell:&lt;/span&gt;
qemu-img&lt;span class="w"&gt; &lt;/span&gt;convert&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;vmdk&lt;span class="w"&gt; &lt;/span&gt;-O&lt;span class="w"&gt; &lt;/span&gt;qcow2&lt;span class="w"&gt; &lt;/span&gt;my-vm-disk1.vmdk&lt;span class="w"&gt; &lt;/span&gt;/var/lib/vz/images/100/vm-100-disk-1.qcow2

&lt;span class="c1"&gt;# Or use the web UI: Create VM → Import → Select OVA&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Step 3: Reconfigure&amp;nbsp;Networking&lt;/h3&gt;
&lt;p&gt;Proxmox uses Linux bridges&amp;nbsp;(&lt;code&gt;vmbr0&lt;/code&gt;). Map the ESXi port group to a Proxmox bridge and update the &lt;span class="caps"&gt;VM&lt;/span&gt;&amp;#8217;s network&amp;nbsp;adapter.&lt;/p&gt;
&lt;h3&gt;Step 4: Verify and&amp;nbsp;Optimize&lt;/h3&gt;
&lt;p&gt;Install &lt;span class="caps"&gt;QEMU&lt;/span&gt; guest agents, remove VMware tools, and update the &lt;span class="caps"&gt;VM&lt;/span&gt;&amp;#8217;s disk controller to VirtIO for better&amp;nbsp;performance.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Frequently Asked&amp;nbsp;Questions&lt;/h2&gt;
&lt;h3&gt;Is Proxmox really free for unlimited&amp;nbsp;use?&lt;/h3&gt;
&lt;p&gt;Yes. The &lt;span class="caps"&gt;AGPL&lt;/span&gt; license guarantees this. The optional subscription provides stable updates and support. The no-subscription repository is free and receives the same&amp;nbsp;software.&lt;/p&gt;
&lt;h3&gt;Can I run Proxmox on a mini &lt;span class="caps"&gt;PC&lt;/span&gt;?&lt;/h3&gt;
&lt;p&gt;Yes. Intel N100, N305, and &lt;span class="caps"&gt;AMD&lt;/span&gt; Ryzen mini PCs are popular Proxmox hosts. Ensure &lt;span class="caps"&gt;VT&lt;/span&gt;-x/&lt;span class="caps"&gt;AMD&lt;/span&gt;-V and &lt;span class="caps"&gt;IOMMU&lt;/span&gt; are enabled in &lt;span class="caps"&gt;BIOS&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;What about VMware Workstation or&amp;nbsp;Fusion?&lt;/h3&gt;
&lt;p&gt;VMware Workstation and Fusion are desktop hypervisors, not bare-metal Type 1 hypervisors like ESXi. They are still sold by Broadcom but are not suitable for a 24/7 homelab&amp;nbsp;server.&lt;/p&gt;
&lt;h3&gt;Does Proxmox support &lt;span class="caps"&gt;GPU&lt;/span&gt;&amp;nbsp;passthrough?&lt;/h3&gt;
&lt;p&gt;Yes. Proxmox has excellent &lt;span class="caps"&gt;GPU&lt;/span&gt; passthrough (PCIe passthrough) support for Intel iGPU, &lt;span class="caps"&gt;AMD&lt;/span&gt;, and &lt;span class="caps"&gt;NVIDIA&lt;/span&gt; cards. This is popular for Jellyfin transcoding, &lt;span class="caps"&gt;AI&lt;/span&gt; workloads, and Windows gaming&amp;nbsp;VMs.&lt;/p&gt;
&lt;h3&gt;Can I mix Proxmox and ESXi in the same&amp;nbsp;network?&lt;/h3&gt;
&lt;p&gt;Yes. They are independent hypervisors. Use a shared storage backend (&lt;span class="caps"&gt;NFS&lt;/span&gt; or iSCSI) if VMs need to migrate between&amp;nbsp;them.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;For homelab use in 2026, Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; is the clear winner. It is free, open-source, supports containers natively, and has a growing community. VMware ESXi remains relevant for enterprise certification and existing VMware shops, but the elimination of the free tier and Broadcom&amp;#8217;s pricing make it impractical for&amp;nbsp;hobbyists.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Download the Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt; &lt;span class="caps"&gt;ISO&lt;/span&gt; and install it on your&amp;nbsp;hardware&lt;/li&gt;
&lt;li&gt;Import your ESXi VMs using the &lt;span class="caps"&gt;OVA&lt;/span&gt;&amp;nbsp;method&lt;/li&gt;
&lt;li&gt;Join the Proxmox community forum and&amp;nbsp;r/homelab&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;installation&lt;/strong&gt;: hardware — Mini PCs, server motherboards, &lt;span class="caps"&gt;NAS&lt;/span&gt;&amp;nbsp;drives&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;integration&lt;/strong&gt;: tool — Proxmox Backup Server subscriptions, &lt;span class="caps"&gt;UPS&lt;/span&gt;&amp;nbsp;units&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;alternatives&lt;/strong&gt;: tool — &lt;span class="caps"&gt;XCP&lt;/span&gt;-ng (another open-source Xen&amp;nbsp;hypervisor)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;installation&lt;/code&gt; → setup_guide: &lt;a href="https://steadypub.com/2026/06/proxmox-beginner-guide-2026/"&gt;Proxmox beginner&amp;nbsp;guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;integration&lt;/code&gt; → related_guide: &lt;a href="https://steadypub.com/2026/06/migrate-from-esxi-to-proxmox/"&gt;Migrate from ESXi to&amp;nbsp;Proxmox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;alternatives&lt;/code&gt; → comparison: &lt;a href="https://steadypub.com/2026/06/proxmox-vs-virtualbox-for-beginners/"&gt;Proxmox vs&amp;nbsp;VirtualBox&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] Did you migrate from ESXi to Proxmox? What was your&amp;nbsp;experience?&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for weekly virtualization and homelab&amp;nbsp;guides.&lt;/li&gt;
&lt;li&gt;[internal_link] Next: read our &lt;a href="https://steadypub.com/2026/06/proxmox-beginner-guide-2026/"&gt;Proxmox beginner guide for&amp;nbsp;2026&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Comparisons"/><category term="proxmox"/><category term="esxi"/><category term="vmware"/><category term="homelab"/><category term="virtualization"/><category term="comparison"/></entry><entry><title>Self-Hosted Alternatives to Google Services: A Complete 2026 Migration Guide</title><link href="https://steadypub.com/2026/06/self-hosted-alternatives-to-google-services/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T06:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/self-hosted-alternatives-to-google-services/</id><summary type="html">&lt;p&gt;The complete 2026 de-Googling roadmap: replace Gmail, Drive, Photos, Calendar, and more with open-source, self-hosted alternatives you&amp;nbsp;control.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~15 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Privacy-conscious users and homelabbers ready to&amp;nbsp;de-Google&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Does &amp;#8220;Self-Hosted Alternatives to Google Services&amp;#8221;&amp;nbsp;Mean?&lt;/h2&gt;
&lt;h3&gt;What Exactly Is&amp;nbsp;It?&lt;/h3&gt;
&lt;p&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;De-Googling&amp;#8221; is the process of replacing Google&amp;#8217;s cloud services with software you run on your own hardware or a &lt;span class="caps"&gt;VPS&lt;/span&gt;. Instead of Gmail, you run a mail server. Instead of Google Drive, you run Nextcloud. The trade-off is operational responsibility: you handle backups, security updates, and uptime in exchange for data sovereignty and zero algorithmic&amp;nbsp;surveillance.&lt;/p&gt;
&lt;h3&gt;Why It Matters in&amp;nbsp;2026&lt;/h3&gt;
&lt;p&gt;Google&amp;#8217;s data-harvesting practices are well-documented, but the practical risks have escalated:
- &lt;strong&gt;Account bans:&lt;/strong&gt; Automated systems can lock you out of Gmail, Drive, and Photos simultaneously with no human recourse.
- &lt;strong&gt;Storage pricing:&lt;/strong&gt; Google Workspace pricing increased 20–30% between 2023 and 2025.
- &lt;strong&gt;&lt;span class="caps"&gt;AI&lt;/span&gt; training:&lt;/strong&gt; Google&amp;#8217;s 2024 privacy policy updates explicitly allow &lt;span class="caps"&gt;AI&lt;/span&gt; training on Workspace data unless explicitly opted out.
- &lt;strong&gt;Geopolitical access:&lt;/strong&gt; Google services are blocked or restricted in several regions; self-hosted alternatives are&amp;nbsp;jurisdiction-independent.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The Google Service Replacement&amp;nbsp;Matrix&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Google Service&lt;/th&gt;
&lt;th&gt;Self-Hosted Alternative&lt;/th&gt;
&lt;th&gt;Effort&lt;/th&gt;
&lt;th&gt;Mobile Support&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Gmail&lt;/td&gt;
&lt;td&gt;Mailcow / Mail-in-a-Box&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;IMAP&lt;/span&gt; clients&lt;/td&gt;
&lt;td&gt;Requires domain, &lt;span class="caps"&gt;SPF&lt;/span&gt;/&lt;span class="caps"&gt;DKIM&lt;/span&gt;/&lt;span class="caps"&gt;DMARC&lt;/span&gt; setup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Drive&lt;/td&gt;
&lt;td&gt;Nextcloud&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;iOS/Android apps&lt;/td&gt;
&lt;td&gt;Full-text search, collaborative editing via OnlyOffice&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Photos&lt;/td&gt;
&lt;td&gt;Immich&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;iOS/Android auto-upload&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;AI&lt;/span&gt; face recognition, similar &lt;span class="caps"&gt;UX&lt;/span&gt; to Google Photos&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Calendar&lt;/td&gt;
&lt;td&gt;Nextcloud Calendar + DAVx⁵&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;CalDAV sync&lt;/td&gt;
&lt;td&gt;Works with native Android/iOS calendar apps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Contacts&lt;/td&gt;
&lt;td&gt;Nextcloud Contacts&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;CardDAV sync&lt;/td&gt;
&lt;td&gt;Native sync on most phones&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Docs/Sheets&lt;/td&gt;
&lt;td&gt;OnlyOffice / Collabora&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Web apps&lt;/td&gt;
&lt;td&gt;Real-time collaboration, &lt;span class="caps"&gt;DOCX&lt;/span&gt;/&lt;span class="caps"&gt;XLSX&lt;/span&gt; compatibility&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Maps&lt;/td&gt;
&lt;td&gt;None (self-hosted maps are niche)&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;OsmAnd, Organic Maps&lt;/td&gt;
&lt;td&gt;These are offline-first &lt;span class="caps"&gt;FOSS&lt;/span&gt; apps, not self-hosted&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Keep&lt;/td&gt;
&lt;td&gt;Joplin / Nextcloud Notes&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;All platforms&lt;/td&gt;
&lt;td&gt;Joplin has &lt;span class="caps"&gt;E2EE&lt;/span&gt;; Nextcloud Notes is simpler&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;YouTube&lt;/td&gt;
&lt;td&gt;None (hosting video is expensive)&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;NewPipe, LibreTube&lt;/td&gt;
&lt;td&gt;Client-side alternatives; hosting is not practical for most&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Authenticator&lt;/td&gt;
&lt;td&gt;Vaultwarden / &lt;span class="caps"&gt;2FAS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;All platforms&lt;/td&gt;
&lt;td&gt;Vaultwarden is self-hosted Bitwarden with &lt;span class="caps"&gt;TOTP&lt;/span&gt; support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Analytics&lt;/td&gt;
&lt;td&gt;Umami / Plausible&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;Privacy-first, no cookie banner needed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Search&lt;/td&gt;
&lt;td&gt;SearXNG&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Web app&lt;/td&gt;
&lt;td&gt;Metasearch engine aggregating multiple backends&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Quick Start: Phased Deployment&amp;nbsp;Strategy&lt;/h2&gt;
&lt;p&gt;If you prefer a structured approach, here is a phased migration&amp;nbsp;plan:&lt;/p&gt;
&lt;h3&gt;Phase 1: File Sync and Photos (Week&amp;nbsp;1)&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Deploy Nextcloud (file sync + calendar +&amp;nbsp;contacts)&lt;/li&gt;
&lt;li&gt;Deploy Immich&amp;nbsp;(photos)&lt;/li&gt;
&lt;li&gt;Install mobile apps and enable&amp;nbsp;auto-upload&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Phase 2: Communication (Week&amp;nbsp;2–3)&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Add Nextcloud Calendar and Contacts (or sync with&amp;nbsp;DAVx⁵)&lt;/li&gt;
&lt;li&gt;Deploy Jitsi Meet or enable Nextcloud&amp;nbsp;Talk&lt;/li&gt;
&lt;li&gt;Set up Vaultwarden for password management + &lt;span class="caps"&gt;TOTP&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Phase 3: Advanced (Month&amp;nbsp;2)&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Attempt Mailcow if you have a clean &lt;span class="caps"&gt;IP&lt;/span&gt; and&amp;nbsp;domain&lt;/li&gt;
&lt;li&gt;Add Jellyfin for media and TubeSync for YouTube&amp;nbsp;archival&lt;/li&gt;
&lt;li&gt;Deploy SearXNG for private&amp;nbsp;search&lt;/li&gt;
&lt;li&gt;Set up Umami for privacy-first&amp;nbsp;analytics&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Core Migration&amp;nbsp;Principles&lt;/h2&gt;
&lt;h3&gt;Principle 1: Start with Storage, Not&amp;nbsp;Email&lt;/h3&gt;
&lt;p&gt;Email is the hardest service to self-host correctly. Spam filtering, &lt;span class="caps"&gt;IP&lt;/span&gt; reputation, reverse &lt;span class="caps"&gt;DNS&lt;/span&gt;, and &lt;span class="caps"&gt;TLS&lt;/span&gt; certificate management create a steep learning curve. Most failed de-Googling attempts start with email and end in&amp;nbsp;frustration.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Better path:&lt;/strong&gt;
1. Nextcloud (file storage + calendar + contacts)
2. Immich (photos)
3. Vaultwarden (passwords + &lt;span class="caps"&gt;TOTP&lt;/span&gt;)
4. Mailcow&amp;nbsp;(email)&lt;/p&gt;
&lt;h3&gt;Principle 2: Use a &lt;span class="caps"&gt;VPS&lt;/span&gt; for Public-Facing&amp;nbsp;Services&lt;/h3&gt;
&lt;p&gt;Running a mail server from a residential &lt;span class="caps"&gt;IP&lt;/span&gt; is nearly impossible today. Most residential IPs are on blocklists, and dynamic &lt;span class="caps"&gt;DNS&lt;/span&gt; does not resolve the reputation problem. Use a &lt;span class="caps"&gt;VPS&lt;/span&gt; (Hetzner, Netcup, &lt;span class="caps"&gt;OVH&lt;/span&gt;) with a static &lt;span class="caps"&gt;IP&lt;/span&gt; and proper reverse &lt;span class="caps"&gt;DNS&lt;/span&gt; for:
- Mail servers (&lt;span class="caps"&gt;SMTP&lt;/span&gt;)
- Public Nextcloud instances (if you want external access)
- SearXNG (so you don&amp;#8217;t hammer search APIs from a residential &lt;span class="caps"&gt;IP&lt;/span&gt;)&lt;/p&gt;
&lt;p&gt;Keep private services (Immich, Jellyfin, monitoring) on your home network behind a &lt;span class="caps"&gt;VPN&lt;/span&gt; or reverse&amp;nbsp;proxy.&lt;/p&gt;
&lt;h3&gt;Principle 3: Backup Everything.&amp;nbsp;Twice.&lt;/h3&gt;
&lt;p&gt;Self-hosted means you are the sysadmin. When a disk fails, there is no Google support to call. Implement a 3-2-1 backup strategy:
- &lt;strong&gt;3&lt;/strong&gt; copies of your data
- &lt;strong&gt;2&lt;/strong&gt; different media types (local &lt;span class="caps"&gt;SSD&lt;/span&gt; + cloud)
- &lt;strong&gt;1&lt;/strong&gt; offsite&amp;nbsp;copy&lt;/p&gt;
&lt;p&gt;For Nextcloud, use the &lt;a href="https://apps.nextcloud.com/apps/backup"&gt;Nextcloud Backup app&lt;/a&gt; or Restic to Backblaze B2. For Immich, back up the PostgreSQL database and&amp;nbsp;the &lt;code&gt;upload&lt;/code&gt; directory&amp;nbsp;separately.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Deep Dive: Nextcloud as Your Google Drive&amp;nbsp;Replacement&lt;/h2&gt;
&lt;h3&gt;Why Nextcloud in&amp;nbsp;2026?&lt;/h3&gt;
&lt;p&gt;Nextcloud 30 (released late 2025) added:
- &lt;strong&gt;&lt;span class="caps"&gt;AI&lt;/span&gt;-powered full-text search&lt;/strong&gt; (via Nextcloud Assistant + local &lt;span class="caps"&gt;LLM&lt;/span&gt; integration)
- &lt;strong&gt;Improved OnlyOffice integration&lt;/strong&gt; (real-time collaborative editing without a separate server)
- &lt;strong&gt;End-to-end encryption&lt;/strong&gt; for client-side encrypted folders
- &lt;strong&gt;Object storage support&lt;/strong&gt; (S3-compatible backends for infinite&amp;nbsp;scale)&lt;/p&gt;
&lt;h3&gt;Hardware&amp;nbsp;Requirements&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Users&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Storage&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1–2&lt;/td&gt;
&lt;td&gt;2 cores&lt;/td&gt;
&lt;td&gt;4 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;100 &lt;span class="caps"&gt;GB&lt;/span&gt;+&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;LXC&lt;/span&gt; or Docker on a mini &lt;span class="caps"&gt;PC&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3–5&lt;/td&gt;
&lt;td&gt;4 cores&lt;/td&gt;
&lt;td&gt;8 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;500 &lt;span class="caps"&gt;GB&lt;/span&gt;+&lt;/td&gt;
&lt;td&gt;Dedicated &lt;span class="caps"&gt;VM&lt;/span&gt;, &lt;span class="caps"&gt;SSD&lt;/span&gt; required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10+&lt;/td&gt;
&lt;td&gt;4+ cores&lt;/td&gt;
&lt;td&gt;16 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;2 &lt;span class="caps"&gt;TB&lt;/span&gt;+&lt;/td&gt;
&lt;td&gt;PostgreSQL recommended over SQLite&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Quick Docker Compose&amp;nbsp;Setup&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# docker-compose.yml&lt;/span&gt;
&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;nextcloud&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud:30-apache&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8080:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./nextcloud:/var/www/html&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./data:/var/www/html/data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;NEXTCLOUD_ADMIN_USER=admin&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;NEXTCLOUD_ADMIN_PASSWORD=CHANGEME&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;NEXTCLOUD_TRUSTED_DOMAINS=cloud.yourdomain.com&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;OVERWRITEPROTOCOL=https&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;db&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;mariadb:10.11&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud_db&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./db:/var/lib/mysql&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_ROOT_PASSWORD=CHANGEME&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_DATABASE=nextcloud&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_USER=nextcloud&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MYSQL_PASSWORD=CHANGEME&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis:7-alpine&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud_redis&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;cron&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud:30-apache&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud_cron&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./nextcloud:/var/www/html&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;entrypoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/cron.sh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Post-install checklist:&lt;/strong&gt;
1. Enable &lt;span class="caps"&gt;HTTPS&lt;/span&gt; (via reverse proxy or Let&amp;#8217;s Encrypt)
2. Install the &amp;#8220;Default encryption module&amp;#8221; app
3. Configure Redis for file locking (prevents conflicts)
4. Set up a background job cron job (not &lt;span class="caps"&gt;AJAX&lt;/span&gt;)
5. Install OnlyOffice or Collabora for document&amp;nbsp;editing&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Deep Dive: Immich as Your Google Photos&amp;nbsp;Replacement&lt;/h2&gt;
&lt;h3&gt;Why Immich Over Nextcloud&amp;nbsp;Photos?&lt;/h3&gt;
&lt;p&gt;Nextcloud&amp;#8217;s built-in Photos app is fine for basic browsing, but Immich is the undisputed Google Photos replacement in 2026:
- &lt;strong&gt;Automatic mobile upload&lt;/strong&gt; (background sync on iOS/Android)
- &lt;strong&gt;&lt;span class="caps"&gt;AI&lt;/span&gt; face recognition&lt;/strong&gt; (runs locally via TensorFlow Lite)
- &lt;strong&gt;Duplicate detection&lt;/strong&gt; ( perceptual hashing)
- &lt;strong&gt;Timeline view&lt;/strong&gt; (identical to Google Photos)
- &lt;strong&gt;External library support&lt;/strong&gt; (mount existing &lt;span class="caps"&gt;NAS&lt;/span&gt; folders)
- &lt;strong&gt;&lt;span class="caps"&gt;RAW&lt;/span&gt; support&lt;/strong&gt; (Canon, Sony,&amp;nbsp;Nikon)&lt;/p&gt;
&lt;h3&gt;Hardware&amp;nbsp;Requirements&lt;/h3&gt;
&lt;p&gt;Immich is more demanding than Nextcloud because of the &lt;span class="caps"&gt;AI&lt;/span&gt;/&lt;span class="caps"&gt;ML&lt;/span&gt;&amp;nbsp;pipeline:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Users&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Storage&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;GPU&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1–2&lt;/td&gt;
&lt;td&gt;4 cores&lt;/td&gt;
&lt;td&gt;8 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;500 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Optional (speeds up &lt;span class="caps"&gt;ML&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3–5&lt;/td&gt;
&lt;td&gt;6 cores&lt;/td&gt;
&lt;td&gt;16 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;2 &lt;span class="caps"&gt;TB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Intel Quick Sync or &lt;span class="caps"&gt;NVIDIA&lt;/span&gt; T400&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10+&lt;/td&gt;
&lt;td&gt;8+ cores&lt;/td&gt;
&lt;td&gt;32 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;5 &lt;span class="caps"&gt;TB&lt;/span&gt;+&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;NVIDIA&lt;/span&gt; &lt;span class="caps"&gt;RTX&lt;/span&gt; A2000 or better&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Quick Docker Compose&amp;nbsp;Setup&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# docker-compose.yml&lt;/span&gt;
&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;immich-server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ghcr.io/immich-app/immich-server:release&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;immich_server&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;2283:2283&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./upload:/usr/src/app/upload&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/etc/localtime:/etc/localtime:ro&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;DB_HOSTNAME=immich_db&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;DB_USERNAME=immich&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;DB_PASSWORD=CHANGEME&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;DB_DATABASE_NAME=immich&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;REDIS_HOSTNAME=immich_redis&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;db&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;immich-machine-learning&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ghcr.io/immich-app/immich-machine-learning:release&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;immich_ml&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./model-cache:/cache&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;DB_HOSTNAME=immich_db&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;DB_USERNAME=immich&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;DB_PASSWORD=CHANGEME&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;DB_DATABASE_NAME=immich&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;tensorchord/pgvecto-rs:pg16-v0.2.0&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;immich_db&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;./pgdata:/var/lib/postgresql/data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;POSTGRES_USER=immich&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;POSTGRES_PASSWORD=CHANGEME&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;POSTGRES_DB=immich&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis:7-alpine&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;immich_redis&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Common Migration&amp;nbsp;Mistakes&lt;/h2&gt;
&lt;h3&gt;Mistake 1: Trying to Replace Everything at&amp;nbsp;Once&lt;/h3&gt;
&lt;p&gt;Google&amp;#8217;s ecosystem is deeply integrated. Shared Google Docs links, Calendar invites, and Google Meet calls are hard to replace simultaneously. Migrate one service at a time, starting with non-critical data (photos, files), then move to collaborative tools, and tackle email&amp;nbsp;last.&lt;/p&gt;
&lt;h3&gt;Mistake 2: Ignoring Mobile &lt;span class="caps"&gt;UX&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Your family members won&amp;#8217;t use a service with a clunky mobile experience. Nextcloud and Immich both have polished mobile apps. Test the mobile workflow before declaring a migration&amp;nbsp;complete.&lt;/p&gt;
&lt;h3&gt;Mistake 3: No Offsite&amp;nbsp;Backup&lt;/h3&gt;
&lt;p&gt;A self-hosted &lt;span class="caps"&gt;NAS&lt;/span&gt; with &lt;span class="caps"&gt;RAID&lt;/span&gt;-1 is not a backup. If your house floods, both disks fail. Backblaze B2, Wasabi, or Hetzner Storage Box are cheap offsite&amp;nbsp;options:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Restic backup to B2 (run via cron)&lt;/span&gt;
restic&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="w"&gt; &lt;/span&gt;b2:bucket-name&lt;span class="w"&gt; &lt;/span&gt;backup&lt;span class="w"&gt; &lt;/span&gt;/mnt/nextcloud-data
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;De-Googling is a marathon, not a sprint. The 2026 self-hosted stack is mature enough to replace most Google services with minimal friction: Nextcloud for files/calendar/contacts, Immich for photos, Vaultwarden for passwords, and Mailcow for email. The key is starting with the easiest wins (storage) and building operational confidence before tackling the hardest&amp;nbsp;(email).&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Set up a Nextcloud instance (Docker or &lt;span class="caps"&gt;LXC&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;Install the Nextcloud mobile app and sync your&amp;nbsp;calendar/contacts&lt;/li&gt;
&lt;li&gt;Deploy Immich and import your Google Photos Takeout&amp;nbsp;archive&lt;/li&gt;
&lt;li&gt;Configure a backup strategy (Restic + Backblaze&amp;nbsp;B2)&lt;/li&gt;
&lt;li&gt;Once stable, plan the email migration (Mailcow or a privacy-first provider like Proton Mail as a&amp;nbsp;bridge)&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;VPS&lt;/span&gt;/hosting:&lt;/strong&gt; Hetzner, Netcup, &lt;span class="caps"&gt;OVH&lt;/span&gt; (referral&amp;nbsp;programs)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hardware:&lt;/strong&gt; Mini PCs for home hosting (Amazon,&amp;nbsp;AliExpress)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Storage:&lt;/strong&gt; Backblaze B2, Wasabi (affiliate/referral&amp;nbsp;programs)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Domains:&lt;/strong&gt; Namecheap, Porkbun (affiliate&amp;nbsp;programs)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;nextcloud-setup&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;nextcloud-docker-compose.md&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;immich-setup&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;immich-docker-compose-setup.md&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mail-setup&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;self-hosted-email-server-guide.md&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;backup-strategy&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;homelab-backup-strategy.md&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] Which Google service was the hardest for you to replace? Share your de-Googling journey&amp;nbsp;below.&lt;/li&gt;
&lt;li&gt;[newsletter] Get our monthly &amp;#8220;Self-Hosted Stack&amp;#8221; newsletter with security updates, new app releases, and migration&amp;nbsp;tips.&lt;/li&gt;
&lt;li&gt;[internal_link] Ready to set up Nextcloud? Read our &lt;a href="https://steadypub.com/2026/06/nextcloud-docker-compose/"&gt;step-by-step Docker guide&lt;/a&gt;&amp;nbsp;next.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Concepts"/><category term="self hosted alternatives to google services"/><category term="homelab"/><category term="self-hosted"/><category term="degoogle"/></entry><entry><title>Best Self-Hosted Cloud Storage for Your Homelab in 2026</title><link href="https://steadypub.com/2026/06/self-hosted-cloud-storage/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T06:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/self-hosted-cloud-storage/</id><summary type="html">&lt;p&gt;The best self-hosted cloud storage solutions for 2026 compared: Nextcloud, Seafile, ownCloud, and Syncthing. Real specs, performance, and setup&amp;nbsp;advice.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~14 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelabbers choosing a file sync and share&amp;nbsp;platform&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why Self-Hosted Cloud Storage Matters for Your&amp;nbsp;Homelab&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Cloud storage is the gateway drug of self-hosting. It is the first service most people replace because it is tangible: you can see your files, sync them across devices, and share links without trusting Google, Dropbox, or Microsoft. A self-hosted cloud storage platform turns your &lt;span class="caps"&gt;NAS&lt;/span&gt; or mini &lt;span class="caps"&gt;PC&lt;/span&gt; into a private Dropbox with no storage limits, no &lt;span class="caps"&gt;AI&lt;/span&gt; scanning, and no subscription&amp;nbsp;fees.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What self-hosted cloud storage does:&lt;/strong&gt;
- File sync across Windows, macOS, Linux, iOS, and Android
- Web-based file manager with previews, thumbnails, and full-text search
- Share links with expiration dates and passwords
- Collaborative editing (via OnlyOffice or Collabora)
- End-to-end encryption for sensitive folders
- Versioning and trash recovery
- External storage mounts (S3, &lt;span class="caps"&gt;SMB&lt;/span&gt;, &lt;span class="caps"&gt;FTP&lt;/span&gt;,&amp;nbsp;WebDAV)&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Evaluation&amp;nbsp;Criteria&lt;/h2&gt;
&lt;h3&gt;Price-to-Performance&lt;/h3&gt;
&lt;p&gt;All options here are free and open source. The &amp;#8220;cost&amp;#8221; is hardware and your time. Nextcloud is the most demanding; Syncthing is the&amp;nbsp;lightest.&lt;/p&gt;
&lt;h3&gt;Feature&amp;nbsp;Set&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Nextcloud&lt;/th&gt;
&lt;th&gt;Seafile&lt;/th&gt;
&lt;th&gt;ownCloud&lt;/th&gt;
&lt;th&gt;Syncthing&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;File sync&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes (only sync)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Web &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No (only Web &lt;span class="caps"&gt;UI&lt;/span&gt; for status)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mobile apps&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Collaborative editing&lt;/td&gt;
&lt;td&gt;Yes (OnlyOffice)&lt;/td&gt;
&lt;td&gt;Yes (OnlyOffice)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;End-to-end encryption&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes (device-level)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;External storage&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Full-text search&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Apps/extensions&lt;/td&gt;
&lt;td&gt;300+&lt;/td&gt;
&lt;td&gt;Few&lt;/td&gt;
&lt;td&gt;50+&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resource use&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Very Low&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Community &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;Support&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Nextcloud:&lt;/strong&gt; Largest community. Extensive documentation, forums, Reddit, and enterprise&amp;nbsp;support.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Seafile:&lt;/strong&gt; Smaller but dedicated. Chinese origins; excellent performance&amp;nbsp;engineering.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ownCloud:&lt;/strong&gt; The original. Forked into Nextcloud in 2016. Still maintained but smaller&amp;nbsp;community.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Syncthing:&lt;/strong&gt; Massive community. No central server; pure&amp;nbsp;peer-to-peer.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;#1:&amp;nbsp;Nextcloud&lt;/h2&gt;
&lt;h3&gt;Why It Tops Our&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;Nextcloud is the undisputed leader in self-hosted cloud storage. It is a full collaboration platform: files, calendars, contacts, mail, notes, tasks, and video calls. The app ecosystem (300+ apps) means you can extend it into almost anything. Nextcloud 30 (late 2025) added &lt;span class="caps"&gt;AI&lt;/span&gt;-powered full-text search and improved mobile upload&amp;nbsp;performance.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;License&lt;/td&gt;
&lt;td&gt;AGPLv3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Language&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;PHP&lt;/span&gt; / JavaScript&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database&lt;/td&gt;
&lt;td&gt;MariaDB, MySQL, PostgreSQL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Web server&lt;/td&gt;
&lt;td&gt;Apache, Nginx&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage backend&lt;/td&gt;
&lt;td&gt;Local, S3, Swift, Azure, &lt;span class="caps"&gt;SFTP&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Max file size&lt;/td&gt;
&lt;td&gt;2 &lt;span class="caps"&gt;GB&lt;/span&gt; (default), unlimited with chunking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mobile sync&lt;/td&gt;
&lt;td&gt;iOS, Android, auto-upload&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desktop sync&lt;/td&gt;
&lt;td&gt;Windows, macOS, Linux&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ecosystem:&lt;/strong&gt; 300+ apps. Install OnlyOffice, Draw.io, Jitsi, and Notes from the app&amp;nbsp;store.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mobile auto-upload:&lt;/strong&gt; Nextcloud&amp;#8217;s mobile app uploads photos instantly with &lt;span class="caps"&gt;HEIC&lt;/span&gt;/&lt;span class="caps"&gt;RAW&lt;/span&gt;&amp;nbsp;support.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;External storage:&lt;/strong&gt; Mount your existing &lt;span class="caps"&gt;NAS&lt;/span&gt;, S3 bucket, or &lt;span class="caps"&gt;FTP&lt;/span&gt; server as a&amp;nbsp;folder.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Collaboration:&lt;/strong&gt; Real-time document editing via OnlyOffice or Collabora&amp;nbsp;Online.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security:&lt;/strong&gt; Server-side encryption, &lt;span class="caps"&gt;E2EE&lt;/span&gt; folders, brute-force protection, and &lt;span class="caps"&gt;2FA&lt;/span&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Resource hungry:&lt;/strong&gt; Needs 4 &lt;span class="caps"&gt;GB&lt;/span&gt;+ &lt;span class="caps"&gt;RAM&lt;/span&gt; for a responsive experience with 5+&amp;nbsp;users.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;PHP&lt;/span&gt; complexity:&lt;/strong&gt; Tuning &lt;span class="caps"&gt;PHP&lt;/span&gt;-&lt;span class="caps"&gt;FPM&lt;/span&gt;, OPcache, and Redis is required for&amp;nbsp;performance.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Upgrade fragility:&lt;/strong&gt; Major version upgrades can break apps or&amp;nbsp;themes.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Users who want a full collaboration&amp;nbsp;platform&lt;/li&gt;
&lt;li&gt;Families sharing calendars, photos, and&amp;nbsp;documents&lt;/li&gt;
&lt;li&gt;Power users who want app&amp;nbsp;extensibility&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;p&gt;Free (AGPLv3). Nextcloud GmbH sells enterprise support, but the community edition is fully&amp;nbsp;featured.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;#2:&amp;nbsp;Seafile&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;Seafile is the performance champion. It was built by a team in China with a focus on speed and reliability. Seafile&amp;#8217;s sync protocol is block-level (like rsync), meaning it only transfers changed blocks of a file. A 1 &lt;span class="caps"&gt;GB&lt;/span&gt; file with a 1 &lt;span class="caps"&gt;MB&lt;/span&gt; change transfers only 1 &lt;span class="caps"&gt;MB&lt;/span&gt;, not the entire&amp;nbsp;file.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;License&lt;/td&gt;
&lt;td&gt;AGPLv3 (Community) / Proprietary (Pro)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Language&lt;/td&gt;
&lt;td&gt;C / Python&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database&lt;/td&gt;
&lt;td&gt;SQLite, MariaDB, MySQL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Web server&lt;/td&gt;
&lt;td&gt;Nginx (recommended)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage backend&lt;/td&gt;
&lt;td&gt;Local, S3, Ceph, Alibaba &lt;span class="caps"&gt;OSS&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Max file size&lt;/td&gt;
&lt;td&gt;Unlimited&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mobile sync&lt;/td&gt;
&lt;td&gt;iOS, Android&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desktop sync&lt;/td&gt;
&lt;td&gt;Windows, macOS, Linux&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Speed:&lt;/strong&gt; Block-level sync is dramatically faster than Nextcloud&amp;#8217;s file-level sync for large&amp;nbsp;files.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reliability:&lt;/strong&gt; Seafile&amp;#8217;s sync engine is more robust. It handles large libraries (100K+ files) without&amp;nbsp;choking.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Library model:&lt;/strong&gt; Data is organized into &amp;#8220;libraries&amp;#8221; (like Git repositories) with independent sync&amp;nbsp;rules.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lightweight:&lt;/strong&gt; The Seafile server uses less &lt;span class="caps"&gt;RAM&lt;/span&gt; than&amp;nbsp;Nextcloud.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Smaller ecosystem:&lt;/strong&gt; No app store. No built-in calendar or&amp;nbsp;contacts.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Web &lt;span class="caps"&gt;UI&lt;/span&gt; is basic:&lt;/strong&gt; Functional but not polished. The desktop client is the primary&amp;nbsp;interface.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pro features:&lt;/strong&gt; Some enterprise features (&lt;span class="caps"&gt;LDAP&lt;/span&gt;, &lt;span class="caps"&gt;SSO&lt;/span&gt;, advanced search) are in the paid Pro&amp;nbsp;edition.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Users who prioritize sync speed over&amp;nbsp;features&lt;/li&gt;
&lt;li&gt;Large file collections (video, &lt;span class="caps"&gt;RAW&lt;/span&gt; photos, &lt;span class="caps"&gt;CAD&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;Users who want Git-like library&amp;nbsp;versioning&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;p&gt;Community edition is free. Pro edition is ~$100/year for 10&amp;nbsp;users.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;#3:&amp;nbsp;ownCloud&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;ownCloud is the original self-hosted cloud storage platform. It was forked into Nextcloud in 2016 after a licensing dispute. ownCloud Infinite Scale (oCIS) is a complete rewrite in Go, designed for Kubernetes and massive scale. It is lighter than Nextcloud but less&amp;nbsp;mature.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;License&lt;/td&gt;
&lt;td&gt;AGPLv3 (Community) / Proprietary (Enterprise)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Language&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;PHP&lt;/span&gt; (classic) / Go (oCIS)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database&lt;/td&gt;
&lt;td&gt;MariaDB, MySQL, PostgreSQL (classic) / None (oCIS)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage backend&lt;/td&gt;
&lt;td&gt;Local, S3, Swift, Windows Network Drive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Max file size&lt;/td&gt;
&lt;td&gt;Unlimited&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mobile sync&lt;/td&gt;
&lt;td&gt;iOS, Android&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desktop sync&lt;/td&gt;
&lt;td&gt;Windows, macOS, Linux&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;oCIS is modern:&lt;/strong&gt; Go-based, no &lt;span class="caps"&gt;PHP&lt;/span&gt;, no database required. Starts&amp;nbsp;instantly.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Kubernetes-native:&lt;/strong&gt; Designed for containers from the ground&amp;nbsp;up.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enterprise backing:&lt;/strong&gt; ownCloud GmbH has a long track record in the &lt;span class="caps"&gt;EU&lt;/span&gt; public&amp;nbsp;sector.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Smaller community:&lt;/strong&gt; The Nextcloud fork took most developers and&amp;nbsp;users.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;App ecosystem:&lt;/strong&gt; Much smaller than&amp;nbsp;Nextcloud.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;oCIS is new:&lt;/strong&gt; Some features from classic ownCloud are missing in&amp;nbsp;oCIS.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Enterprise users who need vendor&amp;nbsp;support&lt;/li&gt;
&lt;li&gt;Kubernetes-native&amp;nbsp;deployments&lt;/li&gt;
&lt;li&gt;Users who want a lighter alternative to&amp;nbsp;Nextcloud&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;p&gt;Community edition is free. Enterprise edition is paid per&amp;nbsp;user.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;#4:&amp;nbsp;Syncthing&lt;/h2&gt;
&lt;h3&gt;Why It Made the&amp;nbsp;List&lt;/h3&gt;
&lt;p&gt;Syncthing is not a &amp;#8220;cloud storage&amp;#8221; platform in the traditional sense. It is a continuous file synchronization program. There is no central server. Your devices talk directly to each other. It is peer-to-peer, encrypted, and incredibly&amp;nbsp;lightweight.&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;License&lt;/td&gt;
&lt;td&gt;MPLv2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Language&lt;/td&gt;
&lt;td&gt;Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database&lt;/td&gt;
&lt;td&gt;LevelDB (embedded)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage backend&lt;/td&gt;
&lt;td&gt;Local only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Max file size&lt;/td&gt;
&lt;td&gt;Unlimited&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mobile sync&lt;/td&gt;
&lt;td&gt;Android (official), iOS (via Möbius Sync)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desktop sync&lt;/td&gt;
&lt;td&gt;Windows, macOS, Linux, &lt;span class="caps"&gt;BSD&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No server needed:&lt;/strong&gt; Perfect for a 2–4 device sync without a homelab&amp;nbsp;server.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Privacy:&lt;/strong&gt; No central server means no metadata exposure. Block-level encrypted&amp;nbsp;sync.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lightweight:&lt;/strong&gt; Uses ~50 &lt;span class="caps"&gt;MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; per device. Runs on a Raspberry&amp;nbsp;Pi.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Conflict handling:&lt;/strong&gt; Renames conflicting files as &amp;#8220;filename.sync-conflict&amp;#8221; instead of&amp;nbsp;overwriting.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No web file manager:&lt;/strong&gt; Syncthing is pure sync. No sharing links, no public&amp;nbsp;URLs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No collaboration:&lt;/strong&gt; No document editing, no calendars, no&amp;nbsp;contacts.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Device discovery:&lt;/strong&gt; Relies on global discovery servers. Firewalls can block peer&amp;nbsp;discovery.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Best&amp;nbsp;For&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Users who want sync without a&amp;nbsp;server&lt;/li&gt;
&lt;li&gt;Privacy&amp;nbsp;purists&lt;/li&gt;
&lt;li&gt;Small setups (2–4&amp;nbsp;devices)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pricing&lt;/h3&gt;
&lt;p&gt;Free (MPLv2). Fully open&amp;nbsp;source.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Quick Comparison&amp;nbsp;Table&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt; Use&lt;/th&gt;
&lt;th&gt;Mobile App&lt;/th&gt;
&lt;th&gt;Collaboration&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;E2EE&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Nextcloud&lt;/td&gt;
&lt;td&gt;Full collaboration&lt;/td&gt;
&lt;td&gt;4 &lt;span class="caps"&gt;GB&lt;/span&gt;+&lt;/td&gt;
&lt;td&gt;Excellent&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Seafile&lt;/td&gt;
&lt;td&gt;Speed &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; large files&lt;/td&gt;
&lt;td&gt;2 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;td&gt;Via OnlyOffice&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ownCloud&lt;/td&gt;
&lt;td&gt;Enterprise/K8s&lt;/td&gt;
&lt;td&gt;2 &lt;span class="caps"&gt;GB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Syncthing&lt;/td&gt;
&lt;td&gt;Pure sync, no server&lt;/td&gt;
&lt;td&gt;50 &lt;span class="caps"&gt;MB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Android&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Use Redis for File&amp;nbsp;Locking&lt;/h3&gt;
&lt;p&gt;Nextcloud and ownCloud both use file locking to prevent conflicts. Without Redis, locking is stored in the database and is slow. Install Redis and configure it&amp;nbsp;in &lt;code&gt;config.php&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="x"&gt;&amp;#39;filelocking.enabled&amp;#39; =&amp;gt; true,&lt;/span&gt;
&lt;span class="x"&gt;&amp;#39;memcache.locking&amp;#39; =&amp;gt; &amp;#39;\OC\Memcache\Redis&amp;#39;,&lt;/span&gt;
&lt;span class="x"&gt;&amp;#39;redis&amp;#39; =&amp;gt; [&lt;/span&gt;
&lt;span class="x"&gt;    &amp;#39;host&amp;#39; =&amp;gt; &amp;#39;localhost&amp;#39;,&lt;/span&gt;
&lt;span class="x"&gt;    &amp;#39;port&amp;#39; =&amp;gt; 6379,&lt;/span&gt;
&lt;span class="x"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Tip 2: External Storage + S3 for Infinite&amp;nbsp;Scale&lt;/h3&gt;
&lt;p&gt;If you outgrow local storage, mount an S3-compatible bucket (Wasabi, Backblaze B2, Hetzner Storage Box) as external storage. Nextcloud and Seafile both support S3 as a primary or external backend. This gives you &amp;#8220;infinite&amp;#8221; storage without buying more&amp;nbsp;disks.&lt;/p&gt;
&lt;h3&gt;Tip 3: Chunk Large&amp;nbsp;Files&lt;/h3&gt;
&lt;p&gt;Nextcloud&amp;#8217;s default max upload is 2 &lt;span class="caps"&gt;GB&lt;/span&gt;. For large video files, increase &lt;span class="caps"&gt;PHP&lt;/span&gt;&amp;nbsp;limits:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;; php.ini&lt;/span&gt;
&lt;span class="na"&gt;upload_max_filesize&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;16G&lt;/span&gt;
&lt;span class="na"&gt;post_max_size&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;16G&lt;/span&gt;
&lt;span class="na"&gt;max_execution_time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;3600&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Nextcloud is the best general-purpose self-hosted cloud storage for 2026. Seafile is the speed king for large files. ownCloud Infinite Scale is promising for Kubernetes. Syncthing is the zero-infrastructure choice. Most homelabbers should start with Nextcloud for its ecosystem and migrate to Seafile if sync performance becomes a&amp;nbsp;bottleneck.&lt;/p&gt;
&lt;h3&gt;Our&amp;nbsp;Recommendation&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Need&lt;/th&gt;
&lt;th&gt;Recommendation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Family collaboration&lt;/td&gt;
&lt;td&gt;Nextcloud&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Video/photo editing&lt;/td&gt;
&lt;td&gt;Seafile&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kubernetes-native&lt;/td&gt;
&lt;td&gt;ownCloud Infinite Scale&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Minimal infrastructure&lt;/td&gt;
&lt;td&gt;Syncthing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Enterprise support&lt;/td&gt;
&lt;td&gt;ownCloud Enterprise&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mini PCs/&lt;span class="caps"&gt;NAS&lt;/span&gt;:&lt;/strong&gt; Synology, &lt;span class="caps"&gt;QNAP&lt;/span&gt;, Minisforum&amp;nbsp;(Amazon)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Storage:&lt;/strong&gt; &lt;span class="caps"&gt;WD&lt;/span&gt;, Samsung, Crucial SSDs&amp;nbsp;(Amazon)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cloud backup:&lt;/strong&gt; Wasabi, Backblaze B2&amp;nbsp;(referral)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;nextcloud-setup&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;nextcloud-docker-compose.md&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nextcloud-comparison&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;nextcloud-vs-owncloud.md&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sync-only&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;syncthing-homelab-guide.md&amp;#8221;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;external-storage&lt;/code&gt; → guide:&amp;nbsp;&amp;#8220;s3-backup-homelab.md&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] What cloud storage platform runs your homelab? Nextcloud, Seafile, or something&amp;nbsp;else?&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for our file sync performance benchmarks and app&amp;nbsp;roundups.&lt;/li&gt;
&lt;li&gt;[internal_link] Ready to deploy Nextcloud? Read our &lt;a href="https://steadypub.com/2026/06/nextcloud-docker-compose/"&gt;Docker Compose guide&lt;/a&gt;&amp;nbsp;next.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Guides"/><category term="self hosted cloud storage"/><category term="homelab"/><category term="self-hosted"/><category term="nextcloud"/><category term="seafile"/></entry><entry><title>Self-Hosted Cloud Storage with Nextcloud: The Ultimate Guide for 2026</title><link href="https://steadypub.com/2026/06/self-hosted-cloud-storage-nextcloud/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T10:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/self-hosted-cloud-storage-nextcloud/</id><summary type="html">&lt;p&gt;Deploy Nextcloud for private cloud storage in your homelab. Covers Docker Compose setup, performance tuning, external storage, and mobile/desktop&amp;nbsp;sync.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~15 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab and self-hosting&amp;nbsp;enthusiasts&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is&amp;nbsp;Nextcloud?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Nextcloud is a self-hosted platform for file sync, sharing, and collaboration. It provides Dropbox-style file storage, document editing (via Collabora or OnlyOffice), calendars, contacts, and a plugin ecosystem — all under your own control. Nextcloud is open-source (&lt;span class="caps"&gt;AGPL&lt;/span&gt;) and runs on Linux, Docker, or as a snap package. It is the dominant choice for privacy-conscious users who want cloud functionality without surrendering data to a&amp;nbsp;third-party.&lt;/p&gt;
&lt;h3&gt;A Brief&amp;nbsp;History&lt;/h3&gt;
&lt;p&gt;Nextcloud was forked from ownCloud in 2016 by founder Frank Karlitschek and core developers. The fork was driven by disagreements over open-source principles and enterprise licensing. Since then, Nextcloud has grown into a 400+ employee company with a thriving open-source community. It ships quarterly releases, a long-term support (&lt;span class="caps"&gt;LTS&lt;/span&gt;) track, and a stable App Store with hundreds of&amp;nbsp;integrations.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why Use Nextcloud in Your&amp;nbsp;Homelab?&lt;/h2&gt;
&lt;h3&gt;Data Sovereignty and&amp;nbsp;Privacy&lt;/h3&gt;
&lt;p&gt;Your files never leave your hardware. Unlike Google Drive or OneDrive, there is no &lt;span class="caps"&gt;AI&lt;/span&gt; scanning, no advertising profiling, and no surprise terms-of-service changes. For sensitive documents, family photos, or professional archives, this is the primary&amp;nbsp;draw.&lt;/p&gt;
&lt;h3&gt;Full Feature Parity with Commercial&amp;nbsp;Clouds&lt;/h3&gt;
&lt;p&gt;Nextcloud offers file versioning, trash retention, shared links with expiration, end-to-end encryption (&lt;span class="caps"&gt;E2EE&lt;/span&gt;), and client-side encryption. The mobile apps (iOS/Android) support auto-upload of photos, offline folders, and two-factor authentication. Desktop clients sync with Windows, macOS, and&amp;nbsp;Linux.&lt;/p&gt;
&lt;h3&gt;Extensible via&amp;nbsp;Apps&lt;/h3&gt;
&lt;p&gt;The App Store includes integrations&amp;nbsp;for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Calendar &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; Contacts&lt;/strong&gt;&amp;nbsp;(CardDAV/CalDAV)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Notes&lt;/strong&gt;&amp;nbsp;(Markdown)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tasks&lt;/strong&gt; (Nextcloud&amp;nbsp;Deck)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Passwords&lt;/strong&gt; (browser extension&amp;nbsp;compatible)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Talk&lt;/strong&gt; (self-hosted video&amp;nbsp;conferencing)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mail&lt;/strong&gt; (&lt;span class="caps"&gt;IMAP&lt;/span&gt;&amp;nbsp;client)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This turns a simple file server into a full personal or family productivity&amp;nbsp;hub.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;h3&gt;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;A Linux server with 2+ vCPUs, 4 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, and 50 &lt;span class="caps"&gt;GB&lt;/span&gt;+&amp;nbsp;storage&lt;/li&gt;
&lt;li&gt;Docker and Docker&amp;nbsp;Compose&lt;/li&gt;
&lt;li&gt;A domain name (for &lt;span class="caps"&gt;HTTPS&lt;/span&gt; via Let&amp;#8217;s&amp;nbsp;Encrypt)&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;SMTP&lt;/span&gt; server or relay (for notifications and password&amp;nbsp;resets)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Method 1: Docker Compose&amp;nbsp;(Recommended)&lt;/h3&gt;
&lt;p&gt;The official Nextcloud Docker image is well-maintained and supports environment-variable configuration. The Compose stack below includes Nextcloud, PostgreSQL, Redis (for caching), and a reverse proxy (Traefik or Nginx Proxy&amp;nbsp;Manager).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;postgres:15-alpine&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud-db&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;db-data:/var/lib/postgresql/data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;POSTGRES_DB=nextcloud&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;POSTGRES_USER=nextcloud&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;POSTGRES_PASSWORD=***&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis:7-alpine&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud-redis&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud-app&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8080:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud-data:/var/www/html&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;POSTGRES_HOST=db&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;POSTGRES_DB=nextcloud&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;POSTGRES_USER=nextcloud&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;POSTGRES_PASSWORD=***&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;NEXTCLOUD_ADMIN_USER=admin&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;NEXTCLOUD_ADMIN_PASSWORD=***&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;NEXTCLOUD_TRUSTED_DOMAINS=cloud.yourdomain.com&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;OVERWRITEPROTOCOL=https&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;REDIS_HOST=redis&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;db&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;cron&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud-cron&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud-data:/var/www/html:ro&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;entrypoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;/cron.sh&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;db&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;redis&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;db-data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;nextcloud-data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Deploy:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then complete the web setup&amp;nbsp;at &lt;code&gt;http://your-server:8080&lt;/code&gt; or configure Traefik for &lt;span class="caps"&gt;HTTPS&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;Method 2: Bare Metal / &lt;span class="caps"&gt;VM&lt;/span&gt;&amp;nbsp;Installation&lt;/h3&gt;
&lt;p&gt;On a fresh Ubuntu 24.04&amp;nbsp;server:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Install required packages&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;update
sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;apache2&lt;span class="w"&gt; &lt;/span&gt;libapache2-mod-php&lt;span class="w"&gt; &lt;/span&gt;php-gd&lt;span class="w"&gt; &lt;/span&gt;php-mysql&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;php-curl&lt;span class="w"&gt; &lt;/span&gt;php-mbstring&lt;span class="w"&gt; &lt;/span&gt;php-intl&lt;span class="w"&gt; &lt;/span&gt;php-gmp&lt;span class="w"&gt; &lt;/span&gt;php-bcmath&lt;span class="w"&gt; &lt;/span&gt;php-xml&lt;span class="w"&gt; &lt;/span&gt;php-zip&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;php-imagick&lt;span class="w"&gt; &lt;/span&gt;php-opcache&lt;span class="w"&gt; &lt;/span&gt;php-apcu&lt;span class="w"&gt; &lt;/span&gt;redis-server&lt;span class="w"&gt; &lt;/span&gt;php-redis

&lt;span class="c1"&gt;# Download Nextcloud&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/var/www
sudo&lt;span class="w"&gt; &lt;/span&gt;wget&lt;span class="w"&gt; &lt;/span&gt;https://download.nextcloud.com/server/releases/latest.tar.bz2
sudo&lt;span class="w"&gt; &lt;/span&gt;tar&lt;span class="w"&gt; &lt;/span&gt;-xjf&lt;span class="w"&gt; &lt;/span&gt;latest.tar.bz2
sudo&lt;span class="w"&gt; &lt;/span&gt;chown&lt;span class="w"&gt; &lt;/span&gt;-R&lt;span class="w"&gt; &lt;/span&gt;www-data:www-data&lt;span class="w"&gt; &lt;/span&gt;nextcloud

&lt;span class="c1"&gt;# Configure Apache&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;a2enmod&lt;span class="w"&gt; &lt;/span&gt;rewrite&lt;span class="w"&gt; &lt;/span&gt;headers&lt;span class="w"&gt; &lt;/span&gt;env&lt;span class="w"&gt; &lt;/span&gt;dir&lt;span class="w"&gt; &lt;/span&gt;mime&lt;span class="w"&gt; &lt;/span&gt;ssl
sudo&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;restart&lt;span class="w"&gt; &lt;/span&gt;apache2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is more work but offers maximum performance on high-throughput&amp;nbsp;hardware.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Basic Setup and&amp;nbsp;Configuration&lt;/h2&gt;
&lt;h3&gt;Step 1: Initial&amp;nbsp;Wizard&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Navigate to your Nextcloud &lt;span class="caps"&gt;URL&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Create an admin&amp;nbsp;account&lt;/li&gt;
&lt;li&gt;Select PostgreSQL as the&amp;nbsp;database&lt;/li&gt;
&lt;li&gt;Enter the database credentials from your Compose&amp;nbsp;file&lt;/li&gt;
&lt;li&gt;Finish the&amp;nbsp;installation&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Step 2: Enable Redis and&amp;nbsp;OPcache&lt;/h3&gt;
&lt;p&gt;Add&amp;nbsp;to &lt;code&gt;config/config.php&lt;/code&gt; (via the Nextcloud data&amp;nbsp;volume):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="x"&gt;&amp;#39;filelocking.enabled&amp;#39; =&amp;gt; true,&lt;/span&gt;
&lt;span class="x"&gt;&amp;#39;memcache.locking&amp;#39; =&amp;gt; &amp;#39;\OC\Memcache\Redis&amp;#39;,&lt;/span&gt;
&lt;span class="x"&gt;&amp;#39;memcache.local&amp;#39; =&amp;gt; &amp;#39;\OC\Memcache\APCu&amp;#39;,&lt;/span&gt;
&lt;span class="x"&gt;&amp;#39;redis&amp;#39; =&amp;gt; [&lt;/span&gt;
&lt;span class="x"&gt;    &amp;#39;host&amp;#39; =&amp;gt; &amp;#39;redis&amp;#39;,&lt;/span&gt;
&lt;span class="x"&gt;    &amp;#39;port&amp;#39; =&amp;gt; 6379,&lt;/span&gt;
&lt;span class="x"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Verify in &lt;strong&gt;Settings&lt;/strong&gt; → &lt;strong&gt;Administration&lt;/strong&gt; → &lt;strong&gt;Overview&lt;/strong&gt; that no warnings&amp;nbsp;remain.&lt;/p&gt;
&lt;h3&gt;Step 3: Configure &lt;span class="caps"&gt;SMTP&lt;/span&gt; for&amp;nbsp;Email&lt;/h3&gt;
&lt;p&gt;In &lt;strong&gt;Settings&lt;/strong&gt; → &lt;strong&gt;Basic settings&lt;/strong&gt; → &lt;strong&gt;Email server&lt;/strong&gt;,&amp;nbsp;configure:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Mode: &lt;span class="caps"&gt;SMTP&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Encryption: &lt;span class="caps"&gt;STARTTLS&lt;/span&gt; or &lt;span class="caps"&gt;SSL&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;From&amp;nbsp;address: &lt;code&gt;noreply@yourdomain.com&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Server: &lt;code&gt;smtp.gmail.com&lt;/code&gt; (or your&amp;nbsp;provider)&lt;/li&gt;
&lt;li&gt;Port: &lt;code&gt;587&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Credentials: your &lt;span class="caps"&gt;SMTP&lt;/span&gt; user and&amp;nbsp;password&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Use an app-specific password if using Gmail. Without &lt;span class="caps"&gt;SMTP&lt;/span&gt;, password resets and share notifications will not&amp;nbsp;work.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Advanced&amp;nbsp;Features&lt;/h2&gt;
&lt;h3&gt;External Storage&amp;nbsp;Integration&lt;/h3&gt;
&lt;p&gt;Nextcloud can mount &lt;span class="caps"&gt;SMB&lt;/span&gt;/&lt;span class="caps"&gt;CIFS&lt;/span&gt;, &lt;span class="caps"&gt;NFS&lt;/span&gt;, &lt;span class="caps"&gt;SFTP&lt;/span&gt;, Amazon S3, and WebDAV as external storage. This is useful if your data lives on a &lt;span class="caps"&gt;NAS&lt;/span&gt; and you want Nextcloud to act as a&amp;nbsp;frontend.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Enable the &lt;strong&gt;External Storage Support&lt;/strong&gt; app in &lt;strong&gt;Apps&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Go to &lt;strong&gt;Settings&lt;/strong&gt; → &lt;strong&gt;Administration&lt;/strong&gt; → &lt;strong&gt;External&amp;nbsp;Storage&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Add a mount point&amp;nbsp;(e.g., &lt;code&gt;/mnt/nas&lt;/code&gt; via &lt;span class="caps"&gt;SMB&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;Set quota and visibility per user&amp;nbsp;group&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Example: Mount a TrueNAS &lt;span class="caps"&gt;SMB&lt;/span&gt;&amp;nbsp;share:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;Folder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;NAS&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;Media&lt;/span&gt;
&lt;span class="nx"&gt;Storage&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;SMB&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;CIFS&lt;/span&gt;
&lt;span class="nx"&gt;Authentication&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Log&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;save&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;database&lt;/span&gt;
&lt;span class="nx"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m m-Double"&gt;192.168.1.10&lt;/span&gt;
&lt;span class="nx"&gt;Share&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;media&lt;/span&gt;
&lt;span class="nx"&gt;Domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;WORKGROUP&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;End-to-End Encryption (&lt;span class="caps"&gt;E2EE&lt;/span&gt;)&lt;/h3&gt;
&lt;p&gt;For files that must remain unreadable even if the server is compromised, enable the &lt;strong&gt;End-to-End Encryption&lt;/strong&gt; app. This encrypts files on the client before upload. The server only sees ciphertext. Recovery is impossible if you lose your mnemonic key — back it&amp;nbsp;up.&lt;/p&gt;
&lt;h3&gt;Collabora Online /&amp;nbsp;OnlyOffice&lt;/h3&gt;
&lt;p&gt;For document editing, deploy a Collabora Online server alongside&amp;nbsp;Nextcloud:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;collabora&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;collabora/code:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;nextcloud-collabora&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;9980:9980&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;domain=cloud.yourdomain.com&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;dictionaries=en_US&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;cap_add&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;MKNOD&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then in Nextcloud, install the &lt;strong&gt;Collabora Online&lt;/strong&gt; app and set the server &lt;span class="caps"&gt;URL&lt;/span&gt;&amp;nbsp;to &lt;code&gt;https://collabora.yourdomain.com&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Two-Factor&amp;nbsp;Authentication&lt;/h3&gt;
&lt;p&gt;Install the &lt;strong&gt;Two-Factor &lt;span class="caps"&gt;TOTP&lt;/span&gt;&lt;/strong&gt; app and enforce &lt;span class="caps"&gt;2FA&lt;/span&gt; for all admin users. In &lt;strong&gt;Settings&lt;/strong&gt; → &lt;strong&gt;Security&lt;/strong&gt; → &lt;strong&gt;Two-Factor Authentication&lt;/strong&gt;, scan the &lt;span class="caps"&gt;QR&lt;/span&gt; code with Authy, Google Authenticator, or a hardware key (via&amp;nbsp;WebAuthn).&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Integrating with Your&amp;nbsp;Homelab&lt;/h2&gt;
&lt;h3&gt;Backup&amp;nbsp;Strategy&lt;/h3&gt;
&lt;p&gt;Back up both the database and the data&amp;nbsp;volume:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Backup PostgreSQL&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;nextcloud-db&lt;span class="w"&gt; &lt;/span&gt;pg_dump&lt;span class="w"&gt; &lt;/span&gt;-U&lt;span class="w"&gt; &lt;/span&gt;nextcloud&lt;span class="w"&gt; &lt;/span&gt;nextcloud&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;nextcloud-db-backup.sql

&lt;span class="c1"&gt;# Backup data volume&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;--rm&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;nextcloud-data:/data&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;:/backup&lt;span class="w"&gt; &lt;/span&gt;alpine&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;tar&lt;span class="w"&gt; &lt;/span&gt;czf&lt;span class="w"&gt; &lt;/span&gt;/backup/nextcloud-data-backup.tar.gz&lt;span class="w"&gt; &lt;/span&gt;-C&lt;span class="w"&gt; &lt;/span&gt;/data&lt;span class="w"&gt; &lt;/span&gt;.

&lt;span class="c1"&gt;# Backup config&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;cp&lt;span class="w"&gt; &lt;/span&gt;nextcloud-app:/var/www/html/config/config.php&lt;span class="w"&gt; &lt;/span&gt;./config.php
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Automate with cron or a backup container&amp;nbsp;like &lt;code&gt;offen/docker-volume-backup&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Reverse Proxy and &lt;span class="caps"&gt;HTTPS&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Do not expose Nextcloud over &lt;span class="caps"&gt;HTTP&lt;/span&gt;. Use Traefik or Nginx Proxy Manager with a valid Let&amp;#8217;s Encrypt&amp;nbsp;certificate:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.enable=true&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.nextcloud.rule=Host(`cloud.yourdomain.com`)&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.routers.nextcloud.tls.certresolver=letsencrypt&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;traefik.http.services.nextcloud.loadbalancer.server.port=80&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Also&amp;nbsp;add &lt;code&gt;overwrite.cli.url&lt;/code&gt; and &lt;code&gt;overwriteprotocol&lt;/code&gt; in &lt;code&gt;config.php&lt;/code&gt; to avoid mixed-content&amp;nbsp;warnings.&lt;/p&gt;
&lt;h3&gt;Object Storage as Primary&amp;nbsp;Storage&lt;/h3&gt;
&lt;p&gt;For large-scale deployments, use S3-compatible storage (MinIO, Wasabi, Backblaze B2) as the primary storage&amp;nbsp;backend:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="x"&gt;&amp;#39;objectstore&amp;#39; =&amp;gt; [&lt;/span&gt;
&lt;span class="x"&gt;    &amp;#39;class&amp;#39; =&amp;gt; &amp;#39;\\OC\\Files\\ObjectStore\\S3&amp;#39;,&lt;/span&gt;
&lt;span class="x"&gt;    &amp;#39;arguments&amp;#39; =&amp;gt; [&lt;/span&gt;
&lt;span class="x"&gt;        &amp;#39;bucket&amp;#39; =&amp;gt; &amp;#39;nextcloud&amp;#39;,&lt;/span&gt;
&lt;span class="x"&gt;        &amp;#39;autocreate&amp;#39; =&amp;gt; true,&lt;/span&gt;
&lt;span class="x"&gt;        &amp;#39;key&amp;#39; =&amp;gt; &amp;#39;YOUR_ACCESS_KEY&amp;#39;,&lt;/span&gt;
&lt;span class="x"&gt;        &amp;#39;secret&amp;#39; =&amp;gt; &amp;#39;YOUR_SECRET_KEY&amp;#39;,&lt;/span&gt;
&lt;span class="x"&gt;        &amp;#39;hostname&amp;#39; =&amp;gt; &amp;#39;s3.wasabisys.com&amp;#39;,&lt;/span&gt;
&lt;span class="x"&gt;        &amp;#39;port&amp;#39; =&amp;gt; 443,&lt;/span&gt;
&lt;span class="x"&gt;        &amp;#39;use_ssl&amp;#39; =&amp;gt; true,&lt;/span&gt;
&lt;span class="x"&gt;        &amp;#39;region&amp;#39; =&amp;gt; &amp;#39;us-east-1&amp;#39;,&lt;/span&gt;
&lt;span class="x"&gt;        &amp;#39;use_path_style&amp;#39; =&amp;gt; true,&lt;/span&gt;
&lt;span class="x"&gt;    ],&lt;/span&gt;
&lt;span class="x"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Alternatives to&amp;nbsp;Consider&lt;/h2&gt;
&lt;h3&gt;ownCloud&lt;/h3&gt;
&lt;p&gt;ownCloud is the predecessor of Nextcloud. It still exists but has a more restrictive open-source license (ownCloud Commercial License for some features). Use it only if you need specific enterprise integrations not available in&amp;nbsp;Nextcloud.&lt;/p&gt;
&lt;h3&gt;Seafile&lt;/h3&gt;
&lt;p&gt;Seafile is a lightweight file sync and share solution with a focus on performance and reliability. It uses a block-based storage engine and syncs faster than Nextcloud for large datasets. However, it has a smaller app ecosystem and no built-in office&amp;nbsp;suite.&lt;/p&gt;
&lt;h3&gt;File Browser&amp;nbsp;(filebrowser/filebrowser)&lt;/h3&gt;
&lt;p&gt;For a minimal, no-database file manager, File Browser is a single-binary Go application. It provides upload, download, rename, and share links. No database, no complex setup. Ideal for a simple &amp;#8220;file drop&amp;#8221;&amp;nbsp;service.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;Apps&lt;/th&gt;
&lt;th&gt;Performance&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Nextcloud&lt;/td&gt;
&lt;td&gt;Full productivity suite&lt;/td&gt;
&lt;td&gt;Many&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ownCloud&lt;/td&gt;
&lt;td&gt;Enterprise compliance&lt;/td&gt;
&lt;td&gt;Many&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Seafile&lt;/td&gt;
&lt;td&gt;Fast sync, large files&lt;/td&gt;
&lt;td&gt;Few&lt;/td&gt;
&lt;td&gt;Very High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;File Browser&lt;/td&gt;
&lt;td&gt;Minimal file sharing&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Very High&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Frequently Asked&amp;nbsp;Questions&lt;/h2&gt;
&lt;h3&gt;How much storage do I need for&amp;nbsp;Nextcloud?&lt;/h3&gt;
&lt;p&gt;Plan for at least 2x your current data size. Nextcloud stores file versions, trash, thumbnails, and app data. If you have 100 &lt;span class="caps"&gt;GB&lt;/span&gt; of files, allocate 250 &lt;span class="caps"&gt;GB&lt;/span&gt;. For growth, use external storage or object storage&amp;nbsp;backends.&lt;/p&gt;
&lt;h3&gt;Can I run Nextcloud on a Raspberry&amp;nbsp;Pi?&lt;/h3&gt;
&lt;p&gt;Yes, but with caveats. Use an external &lt;span class="caps"&gt;SSD&lt;/span&gt; (not &lt;span class="caps"&gt;SD&lt;/span&gt; card), limit the number of apps, and use SQLite or a lightweight MariaDB instead of PostgreSQL. Performance is acceptable for 1–3 users but not for heavy&amp;nbsp;collaboration.&lt;/p&gt;
&lt;h3&gt;How do I update&amp;nbsp;Nextcloud?&lt;/h3&gt;
&lt;p&gt;For Docker deployments, update the image tag and recreate the container. For major versions, run the built-in updater via the web &lt;span class="caps"&gt;UI&lt;/span&gt;&amp;nbsp;or &lt;code&gt;occ upgrade&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="w"&gt; &lt;/span&gt;www-data&lt;span class="w"&gt; &lt;/span&gt;nextcloud-app&lt;span class="w"&gt; &lt;/span&gt;php&lt;span class="w"&gt; &lt;/span&gt;occ&lt;span class="w"&gt; &lt;/span&gt;upgrade
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Always back up before&amp;nbsp;upgrading.&lt;/p&gt;
&lt;h3&gt;Is Nextcloud truly&amp;nbsp;secure?&lt;/h3&gt;
&lt;p&gt;Nextcloud has a dedicated security team, a bug bounty program, and regular audits. Enable &lt;span class="caps"&gt;HTTPS&lt;/span&gt;, &lt;span class="caps"&gt;2FA&lt;/span&gt;, server-side encryption, and keep the instance updated. The weakest link is usually the administrator, not the&amp;nbsp;software.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Nextcloud is the most mature, feature-rich self-hosted cloud storage platform available. It combines file sync, collaboration, communication, and extensibility in a single package. With Docker, it deploys in minutes. With Redis, PostgreSQL, and a proper reverse proxy, it scales to family or small-team use. For anyone serious about data privacy, Nextcloud is the default&amp;nbsp;choice.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Install the mobile apps and enable&amp;nbsp;auto-upload&lt;/li&gt;
&lt;li&gt;Configure external storage for your &lt;span class="caps"&gt;NAS&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Deploy Collabora or OnlyOffice for document&amp;nbsp;editing&lt;/li&gt;
&lt;li&gt;Set up automated backups to a second&amp;nbsp;location&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;installation&lt;/strong&gt;: hosting — &lt;span class="caps"&gt;VPS&lt;/span&gt; or dedicated server for remote Nextcloud&amp;nbsp;hosting&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;integration&lt;/strong&gt;: tool — OnlyOffice or Collabora commercial&amp;nbsp;licenses&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;alternatives&lt;/strong&gt;: tool — &lt;span class="caps"&gt;NAS&lt;/span&gt; hardware (Synology, &lt;span class="caps"&gt;QNAP&lt;/span&gt;,&amp;nbsp;TrueNAS)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;installation&lt;/code&gt; → setup_guide: &lt;a href="https://steadypub.com/2026/06/docker-compose-for-beginners/"&gt;Docker Compose for&amp;nbsp;beginners&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;integration&lt;/code&gt; → related_guide: &lt;a href="https://steadypub.com/2026/06/nextcloud-vs-owncloud/"&gt;Nextcloud vs ownCloud&amp;nbsp;comparison&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;alternatives&lt;/code&gt; → comparison: &lt;a href="https://steadypub.com/2026/06/nextcloud-immich-comparison/"&gt;Nextcloud vs Immich for&amp;nbsp;photos&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] What apps do you run in Nextcloud? Share your stack in the&amp;nbsp;comments.&lt;/li&gt;
&lt;li&gt;[newsletter] Subscribe for weekly self-hosting guides and Nextcloud&amp;nbsp;tips.&lt;/li&gt;
&lt;li&gt;[internal_link] Next: compare &lt;a href="https://steadypub.com/2026/06/nextcloud-immich-comparison/"&gt;Nextcloud with Immich for photo&amp;nbsp;management&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Tool Guides"/><category term="nextcloud"/><category term="self-hosted"/><category term="cloud storage"/><category term="homelab"/><category term="nas"/><category term="docker"/></entry><entry><title>Self-Hosted Password Manager Comparison: Vaultwarden, Bitwarden, and KeePassXC</title><link href="https://steadypub.com/2026/06/self-hosted-password-manager-comparison/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T10:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/self-hosted-password-manager-comparison/</id><summary type="html">&lt;p&gt;Compare self-hosted password managers for your homelab. Vaultwarden, official Bitwarden, and KeePassXC evaluated for security, sync, cost, and&amp;nbsp;usability.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~10 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Privacy-conscious users choosing a self-hosted password&amp;nbsp;manager&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Why Self-Host a Password&amp;nbsp;Manager?&lt;/h2&gt;
&lt;p&gt;Cloud password managers (1Password, LastPass, Dashlane) store your credentials on their servers. Self-hosting&amp;nbsp;provides:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Benefit&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data sovereignty&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Your vault stays on your hardware&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Zero subscription&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No monthly fees&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Auditability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;You control the code and updates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;No vendor lock-in&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Export to standard formats anytime&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;No breach exposure&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cloud breaches (LastPass 2022) don&amp;#8217;t affect you&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;The&amp;nbsp;Options&lt;/h2&gt;
&lt;h3&gt;1. Vaultwarden (Unofficial&amp;nbsp;Bitwarden)&lt;/h3&gt;
&lt;p&gt;A lightweight Rust implementation of the Bitwarden server &lt;span class="caps"&gt;API&lt;/span&gt;. Compatible with all official Bitwarden&amp;nbsp;clients.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;License&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;GPL&lt;/span&gt; v3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Language&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Rust&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Resource use&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~&lt;span class="caps"&gt;10MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, negligible &lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Deployment&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Docker (single container)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;API&lt;/span&gt; compatibility&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;100% with Bitwarden clients&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Organizations&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Supported (unlimited users)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;2FA&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;TOTP&lt;/span&gt;, WebAuthn/&lt;span class="caps"&gt;FIDO2&lt;/span&gt;, email&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Attachments&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Supported (local storage)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Send&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Supported (encrypted file sharing)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Emergency access&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Supported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;BIOS&lt;/span&gt;/&lt;span class="caps"&gt;UEFI&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Not applicable&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Missing vs. official Bitwarden:&lt;/strong&gt; &lt;span class="caps"&gt;SSO&lt;/span&gt; integration, &lt;span class="caps"&gt;SCIM&lt;/span&gt;, admin portal (enterprise&amp;nbsp;features)&lt;/p&gt;
&lt;h3&gt;2. Official Bitwarden&amp;nbsp;(Self-Hosted)&lt;/h3&gt;
&lt;p&gt;The official .&lt;span class="caps"&gt;NET&lt;/span&gt;-based server stack. Fully featured but&amp;nbsp;resource-heavy.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;License&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;AGPL&lt;/span&gt; v3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Language&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;.&lt;span class="caps"&gt;NET&lt;/span&gt;/C#&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Resource use&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;2GB&lt;/span&gt;+ &lt;span class="caps"&gt;RAM&lt;/span&gt;, 2+ &lt;span class="caps"&gt;CPU&lt;/span&gt; cores&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Deployment&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Docker Compose (8+ containers)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;API&lt;/span&gt; compatibility&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;100% (native)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$0 (free tier) or $3–5/user/month (paid)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Organizations&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Supported (paid tiers)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;2FA&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;TOTP&lt;/span&gt;, WebAuthn, Duo, email&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;SSO&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;SAML&lt;/span&gt; 2.0, OpenID Connect (paid)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;SCIM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Directory sync (paid)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Admin portal&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Full user/org management&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Events&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Audit logs (paid)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;3. KeePassXC (Desktop +&amp;nbsp;Sync)&lt;/h3&gt;
&lt;p&gt;An offline password manager with optional sync via your own cloud (Nextcloud, Syncthing,&amp;nbsp;etc.).&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;License&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;GPL&lt;/span&gt; v2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Language&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;C++&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Resource use&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~&lt;span class="caps"&gt;50MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; (desktop app)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Deployment&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Native app (no server)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Sync&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Via Nextcloud, Syncthing, rsync, etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Database&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Encrypted .kdbx file (&lt;span class="caps"&gt;AES&lt;/span&gt;-256, Argon2)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;2FA&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;TOTP&lt;/span&gt; generation (built-in)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Passkeys&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Supported (&lt;span class="caps"&gt;FIDO2&lt;/span&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Auto-type&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Global hotkey auto-fill&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Browser&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Extension available (KeePassXC-Browser)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mobile&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;KeePassDX (Android), Strongbox (iOS)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Sharing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Via shared database file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Organizations&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual (shared databases)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Comparison&amp;nbsp;Matrix&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Vaultwarden&lt;/th&gt;
&lt;th&gt;Bitwarden (Official)&lt;/th&gt;
&lt;th&gt;KeePassXC&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Server required&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes (Docker)&lt;/td&gt;
&lt;td&gt;Yes (Docker)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;RAM&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;10MB&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;2GB&lt;/span&gt;+&lt;/td&gt;
&lt;td&gt;0 (desktop only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mobile sync&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Automatic&lt;/td&gt;
&lt;td&gt;Automatic&lt;/td&gt;
&lt;td&gt;Manual/cloud sync&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Browser extension&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Auto-fill&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅ (auto-type)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;TOTP&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;WebAuthn/&lt;span class="caps"&gt;FIDO2&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Passkeys&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;File attachments&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Secure sharing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ (Send)&lt;/td&gt;
&lt;td&gt;✅ (Send)&lt;/td&gt;
&lt;td&gt;❌ (manual)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Organization sharing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌ (manual)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Emergency access&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;SSO&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅ (paid)&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Audit logs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅ (paid)&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Self-hosting complexity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Offline use&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ (needs server)&lt;/td&gt;
&lt;td&gt;❌ (needs server)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Export&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;JSON&lt;/span&gt;, &lt;span class="caps"&gt;CSV&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;JSON&lt;/span&gt;, &lt;span class="caps"&gt;CSV&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;XML&lt;/span&gt;, &lt;span class="caps"&gt;CSV&lt;/span&gt;, &lt;span class="caps"&gt;HTML&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Encryption&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;AES&lt;/span&gt;-256, &lt;span class="caps"&gt;PBKDF2&lt;/span&gt;-&lt;span class="caps"&gt;SHA256&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;AES&lt;/span&gt;-256, &lt;span class="caps"&gt;PBKDF2&lt;/span&gt;-&lt;span class="caps"&gt;SHA256&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;AES&lt;/span&gt;-256, Argon2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Deployment&amp;nbsp;Guides&lt;/h2&gt;
&lt;h3&gt;Vaultwarden Docker&amp;nbsp;Compose&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;vaultwarden&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;vaultwarden/server:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;vaultwarden&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;WEBSOCKET_ENABLED=true&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;SIGNUPS_ALLOWED=true&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ADMIN_TOKEN=***    volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;vw-data:/data&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;80:80&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3012:3012&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unless-stopped&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;vw-data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Official Bitwarden Docker&amp;nbsp;Compose&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Use official Bitwarden installer&lt;/span&gt;
curl&lt;span class="w"&gt; &lt;/span&gt;-Lso&lt;span class="w"&gt; &lt;/span&gt;bitwarden.sh&lt;span class="w"&gt; &lt;/span&gt;https://go.btwrdn.co/bw-sh
chmod&lt;span class="w"&gt; &lt;/span&gt;+x&lt;span class="w"&gt; &lt;/span&gt;bitwarden.sh
./bitwarden.sh&lt;span class="w"&gt; &lt;/span&gt;install
./bitwarden.sh&lt;span class="w"&gt; &lt;/span&gt;start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Requires &lt;span class="caps"&gt;2GB&lt;/span&gt;+ &lt;span class="caps"&gt;RAM&lt;/span&gt;, generates 8+&amp;nbsp;containers&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;KeePassXC&amp;nbsp;Setup&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Linux (Ubuntu/Debian)&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;keepassxc

&lt;span class="c1"&gt;# macOS&lt;/span&gt;
brew&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;--cask&lt;span class="w"&gt; &lt;/span&gt;keepassxc

&lt;span class="c1"&gt;# Windows&lt;/span&gt;
&lt;span class="c1"&gt;# Download from https://keepassxc.org/download/&lt;/span&gt;

&lt;span class="c1"&gt;# Sync via Nextcloud&lt;/span&gt;
&lt;span class="c1"&gt;# Place .kdbx in ~/Nextcloud/Passwords/&lt;/span&gt;
&lt;span class="c1"&gt;# Open from that path on all devices&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Security&amp;nbsp;Comparison&lt;/h2&gt;
&lt;h3&gt;Encryption&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Manager&lt;/th&gt;
&lt;th&gt;Algorithm&lt;/th&gt;
&lt;th&gt;Key Derivation&lt;/th&gt;
&lt;th&gt;Iterations&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Vaultwarden&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;AES&lt;/span&gt;-256&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;PBKDF2&lt;/span&gt;-&lt;span class="caps"&gt;SHA256&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;600,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bitwarden&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;AES&lt;/span&gt;-256&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;PBKDF2&lt;/span&gt;-&lt;span class="caps"&gt;SHA256&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;600,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;KeePassXC&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;AES&lt;/span&gt;-256 / ChaCha20&lt;/td&gt;
&lt;td&gt;Argon2&lt;/td&gt;
&lt;td&gt;Customizable&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Threat&amp;nbsp;Model&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Threat&lt;/th&gt;
&lt;th&gt;Vaultwarden&lt;/th&gt;
&lt;th&gt;Bitwarden&lt;/th&gt;
&lt;th&gt;KeePassXC&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Server breach&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Encrypted vaults safe&lt;/td&gt;
&lt;td&gt;Encrypted vaults safe&lt;/td&gt;
&lt;td&gt;N/A (no server)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Client compromise&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Master password needed&lt;/td&gt;
&lt;td&gt;Master password needed&lt;/td&gt;
&lt;td&gt;Master password needed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cloud provider breach&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Your hardware = your risk&lt;/td&gt;
&lt;td&gt;Your hardware = your risk&lt;/td&gt;
&lt;td&gt;File sync risk only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Developer backdoor&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Open source (auditable)&lt;/td&gt;
&lt;td&gt;Open source (auditable)&lt;/td&gt;
&lt;td&gt;Open source (auditable)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Master password weak&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Brute-forceable&lt;/td&gt;
&lt;td&gt;Brute-forceable&lt;/td&gt;
&lt;td&gt;Brute-forceable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Side-channel&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Mitigated by Rust&lt;/td&gt;
&lt;td&gt;.&lt;span class="caps"&gt;NET&lt;/span&gt; runtime&lt;/td&gt;
&lt;td&gt;Minimal C++ attack surface&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;When to Choose&amp;nbsp;Vaultwarden&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Homelabbers wanting full Bitwarden compatibility at minimal resource&amp;nbsp;cost&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ideal if:&lt;/strong&gt; You have Docker running and want browser/mobile&amp;nbsp;sync&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Strength:&lt;/strong&gt; &lt;span class="caps"&gt;10MB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt;, all Bitwarden features, zero&amp;nbsp;cost&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tradeoff:&lt;/strong&gt; No &lt;span class="caps"&gt;SSO&lt;/span&gt;, no enterprise admin&amp;nbsp;portal&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;When to Choose Official&amp;nbsp;Bitwarden&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Teams needing &lt;span class="caps"&gt;SSO&lt;/span&gt;, &lt;span class="caps"&gt;SCIM&lt;/span&gt;, or audit&amp;nbsp;logs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ideal if:&lt;/strong&gt; You&amp;#8217;re a business or need enterprise&amp;nbsp;features&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Strength:&lt;/strong&gt; Official support, full feature&amp;nbsp;set&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tradeoff:&lt;/strong&gt; &lt;span class="caps"&gt;2GB&lt;/span&gt;+ &lt;span class="caps"&gt;RAM&lt;/span&gt;, complex deployment, paid&amp;nbsp;features&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;When to Choose&amp;nbsp;KeePassXC&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Paranoid users wanting offline-only password&amp;nbsp;storage&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ideal if:&lt;/strong&gt; You don&amp;#8217;t want any server at&amp;nbsp;all&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Strength:&lt;/strong&gt; No server, minimal attack surface, offline by&amp;nbsp;default&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tradeoff:&lt;/strong&gt; Manual sync, no emergency access, no built-in&amp;nbsp;sharing&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;For homelabbers, &lt;strong&gt;Vaultwarden is the sweet spot&lt;/strong&gt;. It offers the full Bitwarden experience (browser extensions, mobile apps, auto-fill, &lt;span class="caps"&gt;TOTP&lt;/span&gt;, passkeys) at 1/200th the &lt;span class="caps"&gt;RAM&lt;/span&gt; cost of the official server. KeePassXC is the choice for offline-only users, and official Bitwarden only makes sense for enterprise&amp;nbsp;features.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Deploy Vaultwarden&lt;/strong&gt; via Docker Compose (see config&amp;nbsp;above)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Install Bitwarden apps&lt;/strong&gt; on all devices (they connect to Vaultwarden&amp;nbsp;seamlessly)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enable &lt;span class="caps"&gt;2FA&lt;/span&gt;&lt;/strong&gt; (WebAuthn/&lt;span class="caps"&gt;FIDO2&lt;/span&gt;&amp;nbsp;preferred)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Set up backups&lt;/strong&gt; of&amp;nbsp;the &lt;code&gt;/data&lt;/code&gt; volume&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;YubiKeys:&lt;/strong&gt; Hardware &lt;span class="caps"&gt;2FA&lt;/span&gt; for&amp;nbsp;Vaultwarden/Bitwarden&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mini PCs:&lt;/strong&gt; Intel N100 for 24/7 Vaultwarden&amp;nbsp;server&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Storage:&lt;/strong&gt; SSDs for&amp;nbsp;backup&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mobile:&lt;/strong&gt; KeePassDX (Android), Strongbox&amp;nbsp;(iOS)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal&amp;nbsp;Linking&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;docker&lt;/code&gt; → &lt;code&gt;docker-compose-tutorial.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;security&lt;/code&gt; → &lt;code&gt;wazuh-siem-setup.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nextcloud&lt;/code&gt; → &lt;code&gt;nextcloud-self-hosted.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;2fa&lt;/code&gt; → &lt;code&gt;two-factor-authentication-guide.md&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Which password manager secures your vault?&lt;/strong&gt; Vaultwarden, KeePassXC, or something&amp;nbsp;else?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subscribe&lt;/strong&gt; for homelab security and privacy&amp;nbsp;guides.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Comparisons"/><category term="self-hosted password manager comparison"/><category term="vaultwarden"/><category term="bitwarden self-hosted"/><category term="keepassxc"/><category term="password manager homelab"/><category term="security"/></entry><entry><title>50+ Essential Self-Hosted Services for Your Homelab (2026)</title><link href="https://steadypub.com/2026/06/self-hosted-services-list/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T10:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/self-hosted-services-list/</id><summary type="html">&lt;p&gt;A curated list of 50+ self-hosted services organized by category. Replace SaaS subscriptions with privacy-first, open-source alternatives you&amp;nbsp;control.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~20 minutes&lt;br&gt;
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab builders, privacy advocates, self-hosting&amp;nbsp;beginners&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Self-hosting replaces cloud SaaS subscriptions with software you run on your own hardware. Benefits&amp;nbsp;include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Data sovereignty:&lt;/strong&gt; Your files stay on your&amp;nbsp;hardware&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Privacy:&lt;/strong&gt; No third-party data&amp;nbsp;mining&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cost savings:&lt;/strong&gt; One-time hardware cost vs. recurring&amp;nbsp;subscriptions&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Learning:&lt;/strong&gt; Hands-on experience with Linux, Docker,&amp;nbsp;networking&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Customization:&lt;/strong&gt; Configure exactly what you&amp;nbsp;need&lt;/li&gt;
&lt;/ul&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;SaaS Replacement&lt;/th&gt;
&lt;th&gt;Self-Hosted Alternative&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cloud Storage&lt;/td&gt;
&lt;td&gt;Google Drive, Dropbox&lt;/td&gt;
&lt;td&gt;Nextcloud, Seafile&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Photos&lt;/td&gt;
&lt;td&gt;Google Photos&lt;/td&gt;
&lt;td&gt;Immich, PhotoPrism&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Password Manager&lt;/td&gt;
&lt;td&gt;1Password, Bitwarden Cloud&lt;/td&gt;
&lt;td&gt;Vaultwarden, KeePass&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Notes&lt;/td&gt;
&lt;td&gt;Notion, Evernote&lt;/td&gt;
&lt;td&gt;Joplin, Trilium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chat&lt;/td&gt;
&lt;td&gt;Slack, Discord&lt;/td&gt;
&lt;td&gt;Mattermost, Rocket.Chat&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Media Server&lt;/td&gt;
&lt;td&gt;Plex (cloud)&lt;/td&gt;
&lt;td&gt;Jellyfin, Plex (self-hosted)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Media &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;Entertainment&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Deployment&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Jellyfin&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Open-source media server&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Free Plex alternative&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Plex&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Media server (free tier)&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;User-friendly, clients everywhere&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Emby&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Media server&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Live &lt;span class="caps"&gt;TV&lt;/span&gt;, &lt;span class="caps"&gt;DVR&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Navidrome&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Music streaming server&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Lightweight Spotify alternative&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Audiobookshelf&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Audiobook &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; podcast server&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Audiobook enthusiasts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Calibre-Web&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;E-book library&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Kindle alternative&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Immich&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Photo backup &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; &lt;span class="caps"&gt;AI&lt;/span&gt; search&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Google Photos replacement&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PhotoPrism&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Photo management with &lt;span class="caps"&gt;AI&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;AI&lt;/span&gt;-powered photo organization&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Stash&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Adult content organizer&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Niche media management&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tube Archivist&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;YouTube archive &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; subscribe&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;YouTube archival&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Productivity &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;Collaboration&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Deployment&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Nextcloud&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;File sync, office, calendar&lt;/td&gt;
&lt;td&gt;Docker / &lt;span class="caps"&gt;LXC&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Full Google Workspace replacement&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;ONLYOFFICE&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Online document editing&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Nextcloud integration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Joplin Server&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Note sync server&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Markdown note taking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Trilium&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hierarchical note knowledge base&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Personal knowledge management&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Outline&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Team wiki &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; knowledge base&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Notion alternative&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;BookStack&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Simple wiki &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; documentation&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Technical documentation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mattermost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Team chat (Slack alternative)&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Enterprise messaging&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rocket.Chat&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Team chat&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Open-source Slack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Zulip&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Threaded team chat&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Organized discussions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Wekan&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Kanban board (Trello alternative)&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Project management&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Focalboard&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Project management&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Notion alternative&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Gitea&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Git hosting (GitHub alternative)&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Self-hosted code repositories&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Forgejo&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Git hosting (Gitea fork)&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Community-driven Git hosting&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Security &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;Privacy&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Deployment&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Vaultwarden&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Bitwarden-compatible password manager&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Password syncing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;KeePassXC&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Offline password manager&lt;/td&gt;
&lt;td&gt;Native&lt;/td&gt;
&lt;td&gt;Air-gapped security&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Pi-hole&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Network-wide ad blocker&lt;/td&gt;
&lt;td&gt;Docker / &lt;span class="caps"&gt;LXC&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt;-based ad blocking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AdGuard Home&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Network-wide ad blocker&lt;/td&gt;
&lt;td&gt;Docker / &lt;span class="caps"&gt;LXC&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Advanced &lt;span class="caps"&gt;DNS&lt;/span&gt; filtering&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Wazuh&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;SIEM&lt;/span&gt; &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; threat detection&lt;/td&gt;
&lt;td&gt;Docker / &lt;span class="caps"&gt;LXC&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Security monitoring&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CrowdSec&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Collaborative intrusion detection&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Community-driven security&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Fail2ban&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Brute-force protection&lt;/td&gt;
&lt;td&gt;Native&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;SSH&lt;/span&gt;/web protection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Authelia&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;SSO&lt;/span&gt; &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; &lt;span class="caps"&gt;2FA&lt;/span&gt; portal&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Reverse proxy authentication&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Authentik&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Identity provider&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Modern &lt;span class="caps"&gt;SSO&lt;/span&gt; for apps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Headscale&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Self-hosted Tailscale control server&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Mesh &lt;span class="caps"&gt;VPN&lt;/span&gt; control&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;WireGuard&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fast &lt;span class="caps"&gt;VPN&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Native&lt;/td&gt;
&lt;td&gt;Simple, fast &lt;span class="caps"&gt;VPN&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OpenVPN&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Full-featured &lt;span class="caps"&gt;VPN&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Native&lt;/td&gt;
&lt;td&gt;Enterprise &lt;span class="caps"&gt;VPN&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Nginx Proxy Manager&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Reverse proxy with &lt;span class="caps"&gt;GUI&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Easy &lt;span class="caps"&gt;SSL&lt;/span&gt; &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; routing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Traefik&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cloud-native reverse proxy&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Container-aware routing&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Infrastructure &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;Monitoring&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Deployment&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Portainer&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Docker container management&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;GUI&lt;/span&gt; for Docker&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dockge&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Docker Compose stack manager&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Simple Compose &lt;span class="caps"&gt;GUI&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Virtualization platform&lt;/td&gt;
&lt;td&gt;Bare metal / &lt;span class="caps"&gt;VM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;KVM&lt;/span&gt; + &lt;span class="caps"&gt;LXC&lt;/span&gt; hypervisor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Grafana&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Metrics visualization&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Dashboards for everything&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Prometheus&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Metrics collection&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Time-series monitoring&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;InfluxDB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Time-series database&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Metrics &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; events storage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Loki&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Log aggregation&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Lightweight log aggregation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Uptime Kuma&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Service uptime monitoring&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Simple status page&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Checkmk&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Infrastructure monitoring&lt;/td&gt;
&lt;td&gt;Docker / &lt;span class="caps"&gt;LXC&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Enterprise monitoring&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Netdata&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Real-time system monitoring&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Per-second metrics&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;** scrutiny**&lt;/td&gt;
&lt;td&gt;Hard drive health monitoring&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;S.M.A.R.T.&lt;/span&gt; dashboards&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Duplicati&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Encrypted backups&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Cloud backup tool&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Proxmox Backup Server&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;VM&lt;/span&gt;/container backup&lt;/td&gt;
&lt;td&gt;Bare metal / &lt;span class="caps"&gt;VM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Proxmox integration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Restic&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Modern backup tool&lt;/td&gt;
&lt;td&gt;Native&lt;/td&gt;
&lt;td&gt;Encrypted deduplicated backups&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;BorgBackup&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Deduplicating archiver&lt;/td&gt;
&lt;td&gt;Native&lt;/td&gt;
&lt;td&gt;Space-efficient backups&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Kopia&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cross-platform backup&lt;/td&gt;
&lt;td&gt;Native / Docker&lt;/td&gt;
&lt;td&gt;Modern snapshot backup&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;&lt;span class="caps"&gt;AI&lt;/span&gt; &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; Machine&amp;nbsp;Learning&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Deployment&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ollama&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Local &lt;span class="caps"&gt;LLM&lt;/span&gt; runner&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Run Llama, Mistral, Phi locally&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OpenWebUI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;ChatGPT-like interface for Ollama&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Web &lt;span class="caps"&gt;UI&lt;/span&gt; for local LLMs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;LocalAI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;OpenAI &lt;span class="caps"&gt;API&lt;/span&gt;-compatible local &lt;span class="caps"&gt;LLM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Drop-in &lt;span class="caps"&gt;API&lt;/span&gt; replacement&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Whisper&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Speech-to-text&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Audio transcription&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Stable Diffusion WebUI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;AI&lt;/span&gt; image generation&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Local image generation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ComfyUI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Node-based image generation&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Advanced &lt;span class="caps"&gt;AI&lt;/span&gt; image workflows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;span class="caps"&gt;TTS&lt;/span&gt; (Coqui)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Text-to-speech&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Voice synthesis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Piper&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fast local &lt;span class="caps"&gt;TTS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Raspberry Pi &lt;span class="caps"&gt;TTS&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Pinokio&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Browser for &lt;span class="caps"&gt;AI&lt;/span&gt; apps&lt;/td&gt;
&lt;td&gt;Native&lt;/td&gt;
&lt;td&gt;Easy &lt;span class="caps"&gt;AI&lt;/span&gt; app launcher&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;LibreChat&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Multi-&lt;span class="caps"&gt;LLM&lt;/span&gt; chat &lt;span class="caps"&gt;UI&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Chat with multiple providers&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Communication&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Deployment&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Synapse&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Matrix homeserver&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Decentralized chat&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dendrite&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Lightweight Matrix server&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Low-resource Matrix&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Element&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Matrix client&lt;/td&gt;
&lt;td&gt;Web / App&lt;/td&gt;
&lt;td&gt;End-to-end encrypted chat&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Jitsi Meet&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Video conferencing&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Self-hosted Zoom&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;BigBlueButton&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Web conferencing&lt;/td&gt;
&lt;td&gt;Bare metal / &lt;span class="caps"&gt;VM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Education-focused&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mattermost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Team messaging&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Slack alternative&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Discourse&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Forum &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; community&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Modern discussion forum&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Flarum&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Lightweight forum&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Simple community forum&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Finance &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; Personal&amp;nbsp;Management&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Deployment&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Firefly &lt;span class="caps"&gt;III&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Personal finance manager&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Budget tracking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Actual Budget&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Envelope budgeting&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;YNAB&lt;/span&gt; alternative&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Home Assistant&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Smart home automation&lt;/td&gt;
&lt;td&gt;Docker / &lt;span class="caps"&gt;OS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Home automation hub&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tandoor&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Recipe manager&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Cookbook &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; meal planning&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mealie&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Recipe &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; meal planner&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Modern recipe manager&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Wallabag&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Read-it-later&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Self-hosted Pocket&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Linkding&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Bookmark manager&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Pinboard alternative&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Shiori&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Simple bookmark manager&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Minimal bookmarks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Paperless-ngx&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Document management&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;OCR&lt;/span&gt; &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; digital filing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Memos&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Note-taking &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; microblog&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Quick notes &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; thoughts&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Development &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;DevOps&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Deployment&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Gitea&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Git hosting&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Lightweight GitHub&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GitLab &lt;span class="caps"&gt;CE&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Full DevOps platform&lt;/td&gt;
&lt;td&gt;Docker / &lt;span class="caps"&gt;VM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;CI&lt;/span&gt;/&lt;span class="caps"&gt;CD&lt;/span&gt; pipelines&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Jenkins&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;CI&lt;/span&gt;/&lt;span class="caps"&gt;CD&lt;/span&gt; automation&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Build automation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Drone &lt;span class="caps"&gt;CI&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Container-native &lt;span class="caps"&gt;CI&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Simple &lt;span class="caps"&gt;CI&lt;/span&gt;/&lt;span class="caps"&gt;CD&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Nexus&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Artifact repository&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Maven/npm/Docker registry&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Harbor&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Container registry&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Secure image registry&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Registry&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Docker image registry&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Simple image storage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Code-Server&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;VS&lt;/span&gt; Code in browser&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Remote development&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Excalidraw&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Collaborative whiteboard&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Diagrams &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; sketches&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Diagrams.net&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Diagramming (draw.io)&lt;/td&gt;
&lt;td&gt;Docker / Web&lt;/td&gt;
&lt;td&gt;Flowcharts &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; architecture&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Plausible&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Privacy analytics&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Google Analytics alternative&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Umami&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Simple analytics&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Lightweight web stats&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Matomo&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Full web analytics&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Google Analytics replacement&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;n8n&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Workflow automation&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Zapier alternative&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Huginn&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Agent-based automation&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;IFTTT&lt;/span&gt; alternative&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Activepieces&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No-code automation&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;Business automation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;How to Choose Your&amp;nbsp;Stack&lt;/h2&gt;
&lt;h3&gt;Beginner Stack (First 5&amp;nbsp;Services)&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Pi-hole&lt;/strong&gt; or &lt;strong&gt;AdGuard Home&lt;/strong&gt; — Network-wide ad&amp;nbsp;blocking&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Portainer&lt;/strong&gt; — Docker management &lt;span class="caps"&gt;GUI&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Jellyfin&lt;/strong&gt; — Media&amp;nbsp;server&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Immich&lt;/strong&gt; or &lt;strong&gt;PhotoPrism&lt;/strong&gt; — Photo&amp;nbsp;backup&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vaultwarden&lt;/strong&gt; — Password&amp;nbsp;manager&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Intermediate Stack (Next&amp;nbsp;10)&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Nextcloud&lt;/strong&gt; — Files &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt;&amp;nbsp;productivity&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Gitea&lt;/strong&gt; — Git&amp;nbsp;hosting&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Grafana + Prometheus&lt;/strong&gt; —&amp;nbsp;Monitoring&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Uptime Kuma&lt;/strong&gt; — Status&amp;nbsp;monitoring&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Paperless-ngx&lt;/strong&gt; — Document&amp;nbsp;management&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Home Assistant&lt;/strong&gt; — Smart&amp;nbsp;home&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Wazuh&lt;/strong&gt; or &lt;strong&gt;CrowdSec&lt;/strong&gt; —&amp;nbsp;Security&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ollama&lt;/strong&gt; — Local &lt;span class="caps"&gt;AI&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Joplin Server&lt;/strong&gt; — Note&amp;nbsp;sync&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BookStack&lt;/strong&gt; —&amp;nbsp;Documentation&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Advanced&amp;nbsp;Stack&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;&lt;/strong&gt; — Virtualization&amp;nbsp;platform&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Kopia/Restic&lt;/strong&gt; — Backup&amp;nbsp;strategy&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Traefik/Nginx&lt;/strong&gt; — Reverse&amp;nbsp;proxy&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Authelia/Authentik&lt;/strong&gt; — &lt;span class="caps"&gt;SSO&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;n8n&lt;/strong&gt; —&amp;nbsp;Automation&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;The self-hosted ecosystem in 2026 offers mature alternatives to nearly every major SaaS product. Start with 5 core services, expand gradually, and build a privacy-first digital infrastructure you fully&amp;nbsp;control.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Pick your first 5&lt;/strong&gt; from the beginner stack&amp;nbsp;above&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Get a mini &lt;span class="caps"&gt;PC&lt;/span&gt; or &lt;span class="caps"&gt;NAS&lt;/span&gt;&lt;/strong&gt; (Intel N100, N305, or used enterprise&amp;nbsp;hardware)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Install Docker&lt;/strong&gt; or Proxmox &lt;span class="caps"&gt;VE&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deploy one service per weekend&lt;/strong&gt; — don&amp;#8217;t&amp;nbsp;rush&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mini PCs:&lt;/strong&gt; Minisforum, Beelink, Intel &lt;span class="caps"&gt;NUC&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;NAS&lt;/span&gt;:&lt;/strong&gt; Synology, &lt;span class="caps"&gt;QNAP&lt;/span&gt;, TrueNAS &lt;span class="caps"&gt;SCALE&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hard drives:&lt;/strong&gt; &lt;span class="caps"&gt;WD&lt;/span&gt; Red, Seagate&amp;nbsp;IronWolf&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Networking:&lt;/strong&gt; UniFi, &lt;span class="caps"&gt;TP&lt;/span&gt;-Link Omada,&amp;nbsp;MikroTik&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;UPS&lt;/span&gt;:&lt;/strong&gt; &lt;span class="caps"&gt;APC&lt;/span&gt;,&amp;nbsp;CyberPower&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Books:&lt;/strong&gt; Self-Hosted Home Server by Sven&amp;nbsp;Woltmann&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal&amp;nbsp;Linking&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;beginner&lt;/code&gt; → &lt;code&gt;home-server-docker-setup.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;proxmox&lt;/code&gt; → &lt;code&gt;proxmox-beginner-guide-2026.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker&lt;/code&gt; → &lt;code&gt;docker-compose-tutorial.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;monitoring&lt;/code&gt; → &lt;code&gt;docker-monitoring-grafana-prometheus.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;security&lt;/code&gt; → &lt;code&gt;wazuh-siem-setup.md&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Which 5 services run your homelab?&lt;/strong&gt; Share your stack in the&amp;nbsp;comments.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subscribe&lt;/strong&gt; for weekly self-hosted app reviews and deployment&amp;nbsp;guides.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Guides"/><category term="self-hosted services list"/><category term="homelab apps"/><category term="self-hosted software"/><category term="open source alternatives"/><category term="homelab stack"/></entry><entry><title>How to Set Up a Ubiquiti Homelab: A Step-by-Step Networking Guide</title><link href="https://steadypub.com/2026/06/ubiquiti-homelab-setup/" rel="alternate"/><published>2026-06-04T20:35:00+07:00</published><updated>2026-06-05T10:00:00+07:00</updated><author><name>SteadyPub Team</name></author><id>tag:steadypub.com,2026-06-04:/2026/06/ubiquiti-homelab-setup/</id><summary type="html">&lt;p&gt;A complete guide to building a Ubiquiti UniFi network for your homelab. Covers router selection, &lt;span class="caps"&gt;AP&lt;/span&gt; placement, &lt;span class="caps"&gt;VLAN&lt;/span&gt; segmentation, and the UniFi Network&amp;nbsp;Application.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Reading time:&lt;/strong&gt; ~15 minutes
&lt;strong&gt;Audience:&lt;/strong&gt; Homelab and self-hosting&amp;nbsp;enthusiasts&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What Is Ubiquiti&amp;nbsp;UniFi?&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Ubiquiti UniFi is a unified networking ecosystem of routers, switches, and wireless access points managed by a single software controller. Unlike consumer mesh systems (Eero, Nest Wifi), UniFi provides enterprise-grade features — VLANs, advanced firewall rules, traffic shaping, deep packet inspection, and detailed analytics — at prosumer prices. It is the most popular networking platform in the homelab community due to its balance of capability, aesthetics, and&amp;nbsp;cost.&lt;/p&gt;
&lt;h3&gt;Key&amp;nbsp;Benefits&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Single Pane of Glass&lt;/strong&gt;: One interface controls routers, switches, and&amp;nbsp;APs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;VLANs and Segmentation&lt;/strong&gt;: Isolate IoT, guests, servers, and management&amp;nbsp;networks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scalability&lt;/strong&gt;: Start with a single router and add APs, cameras, and door access&amp;nbsp;later.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No Subscription Fees&lt;/strong&gt;: The Network Application is free. No cloud dependency&amp;nbsp;required.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;h3&gt;Hardware&amp;nbsp;Requirements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;UniFi Gateway&lt;/strong&gt;: &lt;span class="caps"&gt;UDM&lt;/span&gt; Pro, &lt;span class="caps"&gt;UDM&lt;/span&gt; &lt;span class="caps"&gt;SE&lt;/span&gt;, &lt;span class="caps"&gt;UDR&lt;/span&gt;, or &lt;span class="caps"&gt;USG&lt;/span&gt;&amp;nbsp;(legacy)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Access Point&lt;/strong&gt;: U6 Lite, U6 Pro, U7 Pro, or&amp;nbsp;U6+&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Switch (optional but recommended)&lt;/strong&gt;: &lt;span class="caps"&gt;USW&lt;/span&gt;-8, &lt;span class="caps"&gt;USW&lt;/span&gt;-16, or &lt;span class="caps"&gt;USW&lt;/span&gt;-24&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cloud Key or Self-Hosted Controller&lt;/strong&gt;: For running the UniFi Network&amp;nbsp;Application&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cat6 or Cat6a Ethernet cabling&lt;/strong&gt;: For &lt;span class="caps"&gt;AP&lt;/span&gt; and switch&amp;nbsp;connections&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Knowledge&amp;nbsp;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Basic networking: &lt;span class="caps"&gt;IP&lt;/span&gt; addressing, subnets, &lt;span class="caps"&gt;DHCP&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;VLAN&lt;/span&gt; concepts: tagging, trunking, &lt;span class="caps"&gt;PVID&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Comfortable with the UniFi web &lt;span class="caps"&gt;UI&lt;/span&gt; or mobile&amp;nbsp;app&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Step 1: Choose Your&amp;nbsp;Gateway&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Select the right UniFi gateway for your internet speed, homelab size, and expansion&amp;nbsp;plans.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Gateway&lt;/th&gt;
&lt;th&gt;Max Speed&lt;/th&gt;
&lt;th&gt;PoE&lt;/th&gt;
&lt;th&gt;&lt;span class="caps"&gt;IDS&lt;/span&gt;/&lt;span class="caps"&gt;IPS&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;UDR&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;800 Mbps&lt;/td&gt;
&lt;td&gt;4x PoE&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Small apartments, beginners&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;UDM&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;850 Mbps&lt;/td&gt;
&lt;td&gt;4x&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Medium homes, no rack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;UDM&lt;/span&gt; Pro&lt;/td&gt;
&lt;td&gt;3.5 Gbps&lt;/td&gt;
&lt;td&gt;8x&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Rack homelab, 1 Gbps+ &lt;span class="caps"&gt;WAN&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;UDM&lt;/span&gt; &lt;span class="caps"&gt;SE&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;2.5 Gbps&lt;/td&gt;
&lt;td&gt;8x 2.5GbE&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;10G homelab, future-proofing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;UXG&lt;/span&gt; Pro&lt;/td&gt;
&lt;td&gt;1 Gbps&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Advanced users, external controller&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For most homelabbers, the &lt;strong&gt;&lt;span class="caps"&gt;UDM&lt;/span&gt; Pro&lt;/strong&gt; or &lt;strong&gt;&lt;span class="caps"&gt;UDM&lt;/span&gt; &lt;span class="caps"&gt;SE&lt;/span&gt;&lt;/strong&gt; is the sweet spot. The &lt;span class="caps"&gt;UDM&lt;/span&gt; Pro supports &lt;span class="caps"&gt;IDS&lt;/span&gt;/&lt;span class="caps"&gt;IPS&lt;/span&gt; at 3.5 Gbps, has a built-in controller, and fits in a standard&amp;nbsp;rack.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;#&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;No&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;CLI&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;commands&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;needed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;hardware&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;selection&lt;/span&gt;
#&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Purchase&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Ubiquiti&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Store&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;B&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;H&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;authorized&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;reseller&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 2: Deploy the UniFi Network&amp;nbsp;Application&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Run the UniFi controller to manage your&amp;nbsp;devices.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Option A: Built-in Controller (&lt;span class="caps"&gt;UDM&lt;/span&gt;/&lt;span class="caps"&gt;UDM&lt;/span&gt;&amp;nbsp;Pro)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The &lt;span class="caps"&gt;UDM&lt;/span&gt; Pro has the controller pre-installed. Simply power it on, connect a laptop to a &lt;span class="caps"&gt;LAN&lt;/span&gt; port, and browse&amp;nbsp;to &lt;code&gt;192.168.1.1&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Option B: Self-Hosted Controller&amp;nbsp;(Docker)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you use a &lt;span class="caps"&gt;UXG&lt;/span&gt; Pro or legacy &lt;span class="caps"&gt;USG&lt;/span&gt;, run the controller in&amp;nbsp;Docker:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;

&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;unifi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;jacobalberty/unifi:latest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unifi-controller&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;3478:3478/udp&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;# STUN&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8080:8080&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="c1"&gt;# device communication&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;8443:8443&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="c1"&gt;# web UI&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;10001:10001/udp&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# AP discovery&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;unifi-data:/unifi&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;TZ=Asia/Singapore&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;UNIFI_STDOUT=true&lt;/span&gt;

&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;unifi-data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;up&lt;span class="w"&gt; &lt;/span&gt;-d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Access the &lt;span class="caps"&gt;UI&lt;/span&gt;&amp;nbsp;at &lt;code&gt;https://your-server:8443&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Step 3: Adopt and Configure&amp;nbsp;Devices&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Connect your APs and switches to the gateway and adopt them into the&amp;nbsp;controller.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Connect the &lt;span class="caps"&gt;UDM&lt;/span&gt; Pro to your modem via &lt;span class="caps"&gt;WAN&lt;/span&gt;&amp;nbsp;port&lt;/li&gt;
&lt;li&gt;Connect switches to the &lt;span class="caps"&gt;UDM&lt;/span&gt; Pro &lt;span class="caps"&gt;LAN&lt;/span&gt;&amp;nbsp;ports&lt;/li&gt;
&lt;li&gt;Connect APs to the switch (or &lt;span class="caps"&gt;UDM&lt;/span&gt; Pro PoE&amp;nbsp;ports)&lt;/li&gt;
&lt;li&gt;Power on the APs (via PoE or included&amp;nbsp;injectors)&lt;/li&gt;
&lt;li&gt;In the controller, go to &lt;strong&gt;Devices&lt;/strong&gt; → &lt;strong&gt;Pending&amp;nbsp;Devices&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Adopt&lt;/strong&gt; for each &lt;span class="caps"&gt;AP&lt;/span&gt; and&amp;nbsp;switch&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Optional: Check that APs are on the network&lt;/span&gt;
ping&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.1.20&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# default AP IP before adoption&lt;/span&gt;

&lt;span class="c1"&gt;# Check DHCP leases&lt;/span&gt;
ssh&lt;span class="w"&gt; &lt;/span&gt;root@192.168.1.1
cat&lt;span class="w"&gt; &lt;/span&gt;/var/run/dhcpd.leases
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 4: Configure VLANs and Network&amp;nbsp;Segmentation&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Create isolated networks for IoT, servers, guests, and&amp;nbsp;management.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;Settings&lt;/strong&gt; → &lt;strong&gt;Networks&lt;/strong&gt; → &lt;strong&gt;Create New&amp;nbsp;Network&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Create the following&amp;nbsp;VLANs:&lt;/li&gt;
&lt;/ol&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;span class="caps"&gt;VLAN&lt;/span&gt;&lt;/th&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;th&gt;Subnet&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;LAN&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Trusted devices, workstations&lt;/td&gt;
&lt;td&gt;192.168.1.0/24&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;SERVERS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Homelab servers, &lt;span class="caps"&gt;NAS&lt;/span&gt;, VMs&lt;/td&gt;
&lt;td&gt;192.168.10.0/24&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;IOT&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Smart devices, cameras&lt;/td&gt;
&lt;td&gt;192.168.20.0/24&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;GUEST&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Guest Wi-Fi&lt;/td&gt;
&lt;td&gt;192.168.30.0/24&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;99&lt;/td&gt;
&lt;td&gt;&lt;span class="caps"&gt;MANAGEMENT&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Switches, APs, iLO/&lt;span class="caps"&gt;IPMI&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;192.168.99.0/24&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ol&gt;
&lt;li&gt;Configure firewall&amp;nbsp;rules:&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IoT&lt;/strong&gt; → &lt;strong&gt;&lt;span class="caps"&gt;LAN&lt;/span&gt;&lt;/strong&gt;: Block all (IoT cannot reach trusted&amp;nbsp;devices)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IoT&lt;/strong&gt; → &lt;strong&gt;Internet&lt;/strong&gt;: Allow (IoT needs cloud&amp;nbsp;connectivity)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;LAN&lt;/span&gt;&lt;/strong&gt; → &lt;strong&gt;IoT&lt;/strong&gt;: Allow (Admin can manage&amp;nbsp;IoT)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;GUEST&lt;/span&gt;&lt;/strong&gt; → &lt;strong&gt;All&lt;/strong&gt;: Block except&amp;nbsp;Internet&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# UniFi firewall rules are configured via UI&lt;/span&gt;
&lt;span class="c1"&gt;# No direct CLI needed, but you can SSH to the gateway for debugging&lt;/span&gt;
ssh&lt;span class="w"&gt; &lt;/span&gt;root@192.168.1.1
iptables&lt;span class="w"&gt; &lt;/span&gt;-L&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# View active rules&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2&gt;Step 5: Optimize Wi-Fi&amp;nbsp;Coverage&lt;/h2&gt;
&lt;h3&gt;Objective&lt;/h3&gt;
&lt;p&gt;Configure APs for maximum coverage, throughput, and minimal&amp;nbsp;interference.&lt;/p&gt;
&lt;h3&gt;Step-by-Step&amp;nbsp;Instructions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;In the controller, go to &lt;strong&gt;Devices&lt;/strong&gt; → select your &lt;span class="caps"&gt;AP&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;Channel Width&lt;/strong&gt;: 80 MHz for 5 GHz, 20 MHz for 2.4&amp;nbsp;GHz&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;Channel&lt;/strong&gt;: Use &lt;strong&gt;Auto&lt;/strong&gt; or manually pick channels with a Wi-Fi&amp;nbsp;analyzer&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;Transmit Power&lt;/strong&gt;: Medium for 5 GHz, Low for 2.4&amp;nbsp;GHz&lt;/li&gt;
&lt;li&gt;Enable &lt;strong&gt;&lt;span class="caps"&gt;AI&lt;/span&gt; Roaming&lt;/strong&gt; and &lt;strong&gt;Band&amp;nbsp;Steering&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For multi-&lt;span class="caps"&gt;AP&lt;/span&gt; homes, space APs 10–15 meters apart with some overlap. Use the &lt;strong&gt;Coverage Map&lt;/strong&gt; in the controller to visualize signal&amp;nbsp;strength.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Pro&amp;nbsp;Tips&lt;/h2&gt;
&lt;h3&gt;Tip 1: Use a Separate Management &lt;span class="caps"&gt;VLAN&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Place all network infrastructure (&lt;span class="caps"&gt;UDM&lt;/span&gt;, switches, APs) on &lt;span class="caps"&gt;VLAN&lt;/span&gt; 99. This prevents compromise of your router from a compromised IoT device. In the controller, set &lt;strong&gt;Management &lt;span class="caps"&gt;VLAN&lt;/span&gt;&lt;/strong&gt; to 99 under each device&amp;#8217;s&amp;nbsp;settings.&lt;/p&gt;
&lt;h3&gt;Tip 2: Enable Deep Packet Inspection (&lt;span class="caps"&gt;DPI&lt;/span&gt;)&lt;/h3&gt;
&lt;p&gt;&lt;span class="caps"&gt;DPI&lt;/span&gt; identifies traffic by application (Netflix, YouTube, Steam, BitTorrent). Use it to set traffic rules, prioritize work calls, and identify bandwidth&amp;nbsp;hogs.&lt;/p&gt;
&lt;h3&gt;Tip 3: Backup the&amp;nbsp;Controller&lt;/h3&gt;
&lt;p&gt;UniFi&amp;#8217;s configuration is complex. Set up automatic backups in &lt;strong&gt;Settings&lt;/strong&gt; → &lt;strong&gt;System&lt;/strong&gt; → &lt;strong&gt;Backup&lt;/strong&gt; → &lt;strong&gt;Auto Backup&lt;/strong&gt;. Save to a local &lt;span class="caps"&gt;NAS&lt;/span&gt; or cloud&amp;nbsp;storage.&lt;/p&gt;
&lt;h3&gt;Tip 4: Use a &lt;span class="caps"&gt;DNS&lt;/span&gt;&amp;nbsp;Sinkhole&lt;/h3&gt;
&lt;p&gt;Point the UniFi &lt;span class="caps"&gt;DHCP&lt;/span&gt; &lt;span class="caps"&gt;DNS&lt;/span&gt; to Pi-hole or AdGuard Home. This provides network-wide ad blocking without per-device&amp;nbsp;configuration.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Troubleshooting Common&amp;nbsp;Issues&lt;/h2&gt;
&lt;h3&gt;Problem 1: &lt;span class="caps"&gt;AP&lt;/span&gt; Adoption&amp;nbsp;Fails&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Ensure the &lt;span class="caps"&gt;AP&lt;/span&gt; and controller are on the same Layer 2&amp;nbsp;network&lt;/li&gt;
&lt;li&gt;Reset the &lt;span class="caps"&gt;AP&lt;/span&gt;: hold the reset button for 5&amp;nbsp;seconds&lt;/li&gt;
&lt;li&gt;&lt;span class="caps"&gt;SSH&lt;/span&gt; to the &lt;span class="caps"&gt;AP&lt;/span&gt; and set the inform &lt;span class="caps"&gt;URL&lt;/span&gt;&amp;nbsp;manually:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ssh&lt;span class="w"&gt; &lt;/span&gt;ubnt@192.168.1.20&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;# default password: ubnt&lt;/span&gt;
set-inform&lt;span class="w"&gt; &lt;/span&gt;http://192.168.1.1:8080/inform
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Problem 2: Slow Wi-Fi&amp;nbsp;Speeds&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Check for channel interference&amp;nbsp;with &lt;code&gt;iwlist&lt;/code&gt; or a Wi-Fi analyzer&amp;nbsp;app&lt;/li&gt;
&lt;li&gt;Ensure 5 GHz is preferred; disable 2.4 GHz for high-bandwidth&amp;nbsp;devices&lt;/li&gt;
&lt;li&gt;Update &lt;span class="caps"&gt;AP&lt;/span&gt; firmware to the latest stable&amp;nbsp;release&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Problem 3: &lt;span class="caps"&gt;VLAN&lt;/span&gt; Traffic Not&amp;nbsp;Routing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Verify the switch port profile is set to &lt;strong&gt;All&lt;/strong&gt; (trunk) or the correct &lt;span class="caps"&gt;VLAN&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Check the firewall rules are not blocking return&amp;nbsp;traffic&lt;/li&gt;
&lt;li&gt;Ensure the device is sending tagged frames if&amp;nbsp;required&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Ubiquiti UniFi is the premier networking platform for homelab operators. It provides enterprise-grade VLANs, firewalling, Wi-Fi, and analytics at a fraction of the cost of Cisco or Aruba. The &lt;span class="caps"&gt;UDM&lt;/span&gt; Pro serves as the heart of a rack-based homelab, while the mobile app and web &lt;span class="caps"&gt;UI&lt;/span&gt; make day-to-day management accessible. With proper &lt;span class="caps"&gt;VLAN&lt;/span&gt; segmentation, a UniFi network becomes a secure foundation for any self-hosted&amp;nbsp;infrastructure.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Migrate IoT devices to the dedicated &lt;span class="caps"&gt;VLAN&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Set up Pi-hole as the network &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Enable &lt;span class="caps"&gt;DPI&lt;/span&gt; and traffic shaping&amp;nbsp;rules&lt;/li&gt;
&lt;li&gt;Add a UniFi Protect camera&amp;nbsp;system&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Affiliate&amp;nbsp;Opportunities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;prerequisites&lt;/strong&gt;: hardware — Ubiquiti &lt;span class="caps"&gt;UDM&lt;/span&gt; Pro, U6 Pro APs, &lt;span class="caps"&gt;USW&lt;/span&gt;&amp;nbsp;switches&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;step-1&lt;/strong&gt;: tool — Wi-Fi analyzer apps, cable&amp;nbsp;testers&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;pro-tips&lt;/strong&gt;: service — structured cabling installation, rack&amp;nbsp;hardware&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Internal Linking&amp;nbsp;Strategy&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;what-is&lt;/code&gt; → related_comparison: &lt;a href="https://steadypub.com/2026/06/tp-link-omada-vs-unifi/"&gt;Ubiquiti vs &lt;span class="caps"&gt;TP&lt;/span&gt;-Link&amp;nbsp;Omada&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prerequisites&lt;/code&gt; → setup_guide: &lt;a href="https://steadypub.com/2026/06/homelab-rack-setup/"&gt;Homelab rack setup&amp;nbsp;guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conclusion&lt;/code&gt; → next_steps: &lt;a href="https://steadypub.com/2026/06/pihole-setup-guide/"&gt;&lt;span class="caps"&gt;DNS&lt;/span&gt; filtering with&amp;nbsp;Pi-hole&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;span class="caps"&gt;CTA&lt;/span&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[comment] What does your UniFi stack look like? Share your gateway and &lt;span class="caps"&gt;AP&lt;/span&gt;&amp;nbsp;combo.&lt;/li&gt;
&lt;li&gt;[newsletter] Get weekly homelab networking and hardware&amp;nbsp;guides.&lt;/li&gt;
&lt;li&gt;[internal_link] Next: compare &lt;a href="https://steadypub.com/2026/06/tp-link-omada-vs-unifi/"&gt;UniFi with &lt;span class="caps"&gt;TP&lt;/span&gt;-Link&amp;nbsp;Omada&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Networking"/><category term="ubiquiti"/><category term="unifi"/><category term="homelab"/><category term="networking"/><category term="wifi"/><category term="router"/></entry></feed>