{"slug": "homelab-for-the-beginner-you-can-self-host-your-own-server-on-50-hardware", "title": "Homelab For the Beginner: You Can Self-host Your Own Server on $50 Hardware", "summary": "A developer shares a guide on building a homelab for self-hosting services like Nextcloud, Vaultwarden, and FreshRSS using inexpensive hardware, emphasizing digital autonomy and reducing reliance on corporate platforms.", "body_md": "# Homelab For the Beginner: You Can Self-host Your Own Server on $50 Hardware\n\nBuilding on my last post about the [Gemini and Gopher protocols](https://brennan.day/gemini-gophers-and-fingers-oh-my-alternative-internets-beyond-https/), I realized I wanted to take a step further in helping others reclaim web autonomy and sovereignty. So I'm writing this guide.\n\nA few months ago, I wrote about [permacomputing and computing for the apocalypse](https://brennan.day/computing-for-the-apocalypse/) where I briefly spoke about self-hosting and creating your own homelab. But I did not get into the \"how-to\" at all.\n\nI want to do that today, because I took another swing at creating a homelab, and though there was a lot of trial and error, I was overall really impressed by how much capability and functionality you can get out of old, inexpensive hardware.\n\nI originally shelved the project in January and put it on the backburner, because I'm the stereotypical dev that enjoys hopping from one new shiny idea to another. But more than that, [I am not a full-stack web developer](https://brennan.day/why-i-m-not-a-full-stack-dev/). I stick to the front-end and [JAMstack](https://jamstack.org/), avoiding databases, backend, and DevOps altogether.\n\nBut the Internet doesn't actually work that way. Sure, you can use [Netlify](https://www.netlify.com/) or [Vercel](https://vercel.com/) to host and deploy your front-end static sites or [Astro.js](https://astro.build/) solution or whatever else you might be building, typically for no cost. But this means you're relying on a company that could suddenly begin charging you money or change their licensing. Regardless, it's a fragile solution, albeit a really convenient one I'm still using.\n\nI want to [build for the long web](https://brennan.day/how-are-we-preparing-for-the-long-web/), and really, homelabbing can be a fun, useful hobby.\n\n## What Can Be Self-hosted, and Why?\n\nBefore we get into hardware, I want to make the case for *why this is worth doing at all*. It's easy to look at a list of Docker containers and wonder why the hassle is worth it.\n\nEvery service you use daily that you don't control is a liability. Companies shut down, or change their pricing, or get acquired, or start monetizing your data, or make unethical decisions that don't align with your values. I'm sure you've been there.\n\nSelf-hosting is the practice of running your own software on your own hardware. Taking back ownership of the tools you rely on. Here's a taste of what's possible:\n\n**Instead of Google Drive/Dropbox**→[Nextcloud](https://nextcloud.com/)or[Seafile](https://www.seafile.com/). Your files synced to all your devices.** Instead of 1Password/LastPass**→[Vaultwarden](https://github.com/dani-garcia/vaultwarden), a lightweight Bitwarden-compatible password manager you host yourself.**Instead of Feedly/Feedbin**→[FreshRSS](https://freshrss.org/)or[Miniflux](https://miniflux.app/). Read the web on your own terms.** Instead of GitHub**→[Forgejo](https://forgejo.org/)or[Gitea](https://gitea.com/). Your repositories, with no Microsoft or genAI training on your code.**Instead of Discord/Slack**→[Matrix/Synapse](https://matrix.org/)or[Mattermost](https://mattermost.com/). Private and federated.** Instead of Google Photos**→[Immich](https://immich.app/). A beautiful, fast, self-hosted photo library with mobile backup.** Instead of Notion**→[AppFlowy](https://appflowy.io/)or a simple[DokuWiki](https://www.dokuwiki.org/). Flat-file format with no lock-in.** Instead of Twitter/Mastodon (someone else's instance)**→[GoToSocial](https://gotosocial.org/)or[Mastodon](https://joinmastodon.org/). Your own Fediverse node, so your posts live on your server.**Instead of Substack**→[Ghost](https://ghost.org/)or a static site generator like[Hugo](https://gohugo.io/).** Instead of Google Analytics**→[Umami](https://umami.is/)or[Plausible](https://plausible.io/). Privacy-respecting analytics that don't treat website visitors as products.\n\n## The Spectrum of Homelab\n\nIt's important to be mindful that homelabbing is a very wide spectrum: You can have 48U 4-post cabinets in a dedicated, soundproofed, climate-controlled server room with redundant 30 kVA online double-conversion UPS systems backed by a natural-gas automatic standby generator.\n\nOr, you can have [an old Android phone](https://www.instructables.com/Old-Android-Phone-to-WebServer/) or a $15 [Raspberry Pi Zero](https://www.raspberrypi.com/products/raspberry-pi-zero/) with a 2GB microSD serving index.html with the command `darkhttpd /home/pi/site --port 8080`\n\n.\n\nThe overwhelming majority of home servers are far closer to the Pi Zero: A decommissioned work laptop, or a tower pulled from someone's curb, a SFF (small form factor) desktop bought at a garage sale. A machine considered e-waste can actually run web services, drawing only ~40–60 watts from the wall.\n\n## My Philosophy\n\nA popular reason people get into homelabbing and self-hosting is for private streaming of your personal media library, which is usually pirated. That's fine with me, all the power to the pirates! But that's not what this guide is going to be about.\n\nPrimarily, this is because software media systems like [Jellyfin](https://jellyfin.org/) are resource-intensive compared to the services I'm going to be going over. Hardware transcoding, large media libraries, and multiple simultaneous streams ask too much of modest old hardware.\n\nMy homelab, running at `brennan.cafe`\n\n, is a privacy-focused and self-hosted personal infrastructure built on sustainable principles. It represents a journey away from corporate cloud services toward digital sovereignty and ethical computing.\n\n### Why?\n\n**Privacy:** Take back control of personal data**Learning:** Understand the technology you use on a daily basis**Sustainability:** Make use of existing hardware rather than consuming new resources**Freedom:** Break free from vendor lock-in and surveillance capitalism\n\n### Principles\n\nOwn your content, interact with others on your terms[IndieWeb](https://indieweb.org/):Sustainable, mindful computing practices[Permacomputing](https://permacomputing.net/):**FOSS:** Free and Open Source Software exclusively**Privacy:** Zero tracking, no surveillance, respect for users\n\n## Step Zero: Finding Your Hardware\n\nWhere do you get hardware for a homelab, self-hosting server? Anywhere, if you know how to look. With both RAM and storage options [becoming increasingly, absurdly expensive](https://www.pcgamer.com/hardware/memory/team-group-ceo-warns-that-dram-and-ssd-prices-will-still-rise-if-you-need-memory-we-recommend-purchasing-it-as-soon-as-possible/), I can only recommend buying used from the following places:\n\n**Thrift stores and Goodwill**: In many cities, you can walk into a Value Village or local Goodwill and find towers and desktops from 2010–2016 selling for $20–$40. They're usually wiped, sometimes missing a hard drive, occasionally missing RAM. That's fine. Bring a USB stick with a Linux live image. Boot it up in the aisle (yes, you can ask staff). Check that the machine POSTs, that the CPU fans spin, that USB works.**Facebook Marketplace and Kijiji**: Search \"computer\" filtered under $60 and sort by distance. You will find a graveyard of machines people are desperate to get out of their spare rooms. HP EliteDesks, Dell OptiPlexes, Lenovo ThinkCentres. All workhorses built for enterprise, which means they're far more reliable and better-cooled than consumer hardware of the same era. Look for machines with an**Intel Core i3/i5/i7 from the 3rd–7th generation**, or an** AMD FX series**, ideally with at least 4 cores and 8 GB of RAM.\n\n| Spec | Minimum | Sweet Spot |\n|---|---|---|\n| CPU | 4 cores, 2.4 GHz | 4–8 cores, 3.0+ GHz |\n| RAM | 4 GB | 8–16 GB |\n| Storage | 120 GB SSD | 250 GB+ SSD |\n| Network | 100 Mb/s | 1 Gb/s Ethernet |\n| Power | Anything with a standard ATX PSU | — |\n\nHaving a solid state drive will be far faster than a mechanical hard drive (the shiny metal ones that are much heavier), though they do have a shorter lifespan. If the machine you're buying has an HDD, budget $20–$40 for a used SATA SSD (Samsung 860 Evo, Crucial MX500), but keep the HDD for backup.\n\n### What To Avoid\n\n- Small form factor HP/Dell machines with\n*proprietary*power supplies (they fail, and replacements cost more than the machine itself, I learned this the hard way) - Anything with a Core 2 Duo or older unless you're\n*only*serving the most basic webpages. - Machines that have been stored in damp conditions (smell the vents)\n\n## My Homelab: The Tower in A Basement\n\n| Component | Specification |\n|---|---|\n| CPU | AMD FX-4130, 4 cores @ 3.8–3.9 GHz |\n| RAM | 7.24 GiB DDR3-1333 |\n| Storage | 228 GiB SSD (Samsung Evo 820) |\n| Motherboard | Gigabyte GA-78LMT-USB3 (AM3+ socket) |\n| Network | 1 Gb/s onboard Ethernet + USB Wi-Fi adapter |\n| OS |\n|\n\nMy own humble homelab server is a custom Acer Gigabyte full-tower I originally bought off Kijiji at the start of the pandemic six years ago for my little brother. It was advertised as a \"gaming PC\" and was really cheap. Unsurprisingly, it couldn't handle gaming whatsoever. The seller ghosted me when I tried to return it.\n\nAnd thank goodness he did, because now it's the perfect machine for this! 😄\n\nIt lives in the basement, next to a spare bookshelf and synth organ. The tower sits on the carpet floor. A squat black rectangle, sticker residue on the side where a label was once peeled off. With the side panel removed, the fans pleasantly move the air around me while I'm tinkering and troubleshooting. A white $15 USB Wi-Fi adapter with a stubby antenna blinks green constantly.\n\nThis computer is terrible at being a desktop. If you try to even just move a window around, it stutters and lags. (I still have a ThinkPad X200T I bought for $40 that boots into Openbox and BunsenLabs and functions better as a desktop than this tower does) I'm pretty sure there's something wrong with the integrated graphics. But using it as a server you never look at? It works great! It's perfect. The limitation became the feature.\n\nIt did have a dedicated graphics card when I got it—a GT 700-something, one of those cards that's designed to look like a gaming GPU but is actually a low-end office card. I pulled it out and the connector pins looked possibly corroded, and I didn't investigate further.\n\nThe Gigabyte GA-78LMT-USB3 markets itself as being durable, shock-resistant and humidity-resistant. That's pretty funny—who is explicitly in the market for a *durable* motherboard? The answer is doomsday preppers and... homelabbers. The thing has survived being a failed gaming PC, six years of neglected basement storage, and a full server rebuild.\n\nBefore I set this up, I went salvaging for parts in one of the HP Elite Compaq 8200s my mom previously used for her remote job, and I was happily surprised to find a **Samsung Evo 820 250GB SSD** just sitting in it. Those little HPs are nifty machines, but they have a weird proprietary power supply that costs as much as the machine itself to replace.\n\n## What's Running\n\nHere's everything currently live on `brennan.cafe`\n\n:\n\n📁 **Files** — [FileBrowser](https://filebrowser.org/)\nA clean, web-based file manager for browsing and managing everything on the server. Think of it as a lightweight personal Google Drive UI. `files.brennan.cafe`\n\n📦 **Archive** — [ArchiveBox](https://archivebox.io/)\nSelf-hosted internet archiving. Save web pages, bookmarks, videos, and full media captures before they disappear. The web is more ephemeral than anyone admits. `archive.brennan.cafe`\n\n📊 **Monitor** — [Beszel](https://beszel.dev/)\nLightweight system monitoring — CPU, RAM, disk, network, all in a simple dashboard. Useful for actually knowing what your machine is doing. `monitor.brennan.cafe`\n\n📈 **Status** — [Uptime Kuma](https://uptime.kuma.pet/)\nTracks uptime and response time for all my services. Sends me a notification if something goes down. Looks like a Better Uptime clone, except it's yours. `status.brennan.cafe`\n\n📋 **Logs** — [Dozzle](https://dozzle.dev/)\nReal-time Docker log viewer. When something breaks at 2am, this is how you find out why. `logs.brennan.cafe`\n\n(password protected)\n\n💾 **Backup** — [Duplicati](https://www.duplicati.com/)\nEncrypted, scheduled backups to multiple cloud destinations (Backblaze B2, S3, SFTP, whatever you want). A backup solution you actually control. `backup.brennan.cafe`\n\n(password protected)\n\n📖 **Wiki** — [DokuWiki](https://www.dokuwiki.org/)\nFlat-file wiki — no database, just Markdown files on disk. I use it to document my own server: commands I keep forgetting, troubleshooting notes, configs. Write it down the first time. `wiki.brennan.cafe`\n\n🚀 **Deploy** — [Coolify](https://coolify.io/)\nA self-hosted Heroku/Vercel alternative. Point it at a git repo, it handles deployment. More on this below. `deploy.brennan.cafe`\n\n🦥 **Social** — [GoToSocial](https://gotosocial.org/)\nA lightweight ActivityPub server for the Fediverse. My own personal Mastodon instance, running on my own hardware. `@brennan@brennan.cafe`\n\n— `social.brennan.cafe`\n\n📰 **RSS** — [FreshRSS](https://freshrss.org/)\nSelf-hosted RSS/Atom reader with a solid web interface and mobile app support. I read the web through FreshRSS instead of through algorithmic feeds. It uses SQLite by default, so no Postgres required. `rss.brennan.cafe`\n\n✍️ **Blog** — [Grav CMS](https://getgrav.org/)\nA modern flat-file CMS built on PHP. No database. Markdown content. A good middle ground between a static site generator and a full CMS if you want a GUI for writing. `blog.brennan.cafe`\n\n### And the Resource Usage?\n\nThis machine is currently running **eleven web services**, using:\n\n**2 GB out of 8 GB RAM**(25%)** 30 GB storage****~20% CPU**\n\nThat's a quad-core CPU from 2012, 8 gigabytes of DDR3 RAM, and a fast SSD. That's all my server requires, and you could run a homelab on even less.\n\n## Service Recommendations\n\nBefore you start deploying services, it's helpful to know what's realistic for your hardware. Here are the resource requirements for common self-hosted services:\n\n| Service | RAM (Idle) | Storage | Priority | Notes |\n|---|---|---|---|---|\nVaultwarden |\n10–30 MB | ~100 MB | 🔴 High | Password manager, Bitwarden-compatible |\nBeszel + Agent |\n~35 MB | ~100 MB | 🔴 High | Server monitoring hub |\nUptime Kuma |\n~150 MB | ~200 MB | 🔴 High | Uptime/status monitoring |\nDozzle |\n~20 MB | ~0 MB | 🔴 High | Real-time Docker log viewer |\nDuplicati |\n~50 MB idle | ~200 MB | 🔴 High | Encrypted backup solution |\nFreshRSS |\n~50 MB | ~500 MB | 🟡 Medium | RSS/Atom feed reader |\nMiniflux |\n~30–50 MB | ~500 MB | 🟡 Medium | Minimalist RSS reader (requires PostgreSQL) |\nLinkding |\n~70 MB | ~200 MB | 🟡 Medium | Self-hosted bookmark manager |\nShlink |\n~120 MB | ~200 MB | 🟢 Low | URL shortener with analytics |\nPi-hole |\n~130 MB | ~500 MB | 🟢 Low | Network-wide ad blocker |\n\nNote:These are idle/typical usage. RAM and storage will increase with actual usage (more feeds, more bookmarks, larger vaults, etc.).\n\nOn an 8 GB machine with the services listed above, you'd use roughly 655 MB of RAM and 2 GB of storage — leaving plenty of headroom for additional services.\n\n### Services to Avoid\n\nNot every self-hosted service is suitable for older, modest hardware. Here are services that will overwhelm a machine like the one described in this guide:\n\n| Service | Why |\n|---|---|\nJellyfin / Plex |\nRequires hardware video transcoding for smooth playback. Software transcoding on a 4-core CPU will peg the processor and affect all other services. |\nElasticsearch |\nRequires 2+ GB RAM minimum. Designed for enterprise-scale search workloads. |\nClickHouse |\nColumn-store OLAP database designed for high RAM environments. |\nNextcloud |\nTechnically possible, but heavy on CPU for file processing, thumbnail generation, and previews. Can slow down the entire server. |\nGitLab |\nRequires 4+ GB RAM recommended. The self-hosted version is resource-intensive. |\nMatrix Synapse |\nThe original Matrix server is very RAM-heavy. Consider a lighter alternative like Conduit if you need Matrix. |\n\nBuild up to these! Start with lightweight services and understand your machine's limits. Only tackle heavier workloads when you're ready to upgrade hardware or dedicate more resources.\n\n## THE GUIDE\n\nNow, finally, we get into the actual how-to. This is not a single-sitting setup. Depending on how much of this you tackle, you're looking at a weekend project, maybe two. But each piece builds on the last, and once you have the foundation of OS, SSH, tunnel, and Docker, then everything else is running commands.\n\n## Step 1: Choosing Your OS\n\nThere are many different options for what operating system your server runs. Most guides will point you toward [Ubuntu Server](https://ubuntu.com/download/server), and that's reasonable. It's lean, stable, well-documented, and has a massive community.\n\nBut Ubuntu Server is *headless*, which means there's no graphical interface at all. You get a black screen, a blinking cursor, and a login prompt. Everything is done through the terminal. That's fine if you're technical, and it *does* free up RAM and CPU that would otherwise go to running a desktop environment.\n\nMy personal recommendation for beginners, though, is [Lubuntu](https://lubuntu.me/). Here's why:\n\n**It has a GUI when you need it.** Sometimes you just want to drag a file somewhere, or open a browser to check something, or use a GUI text editor. Lubuntu's LXQt desktop is lightweight enough that it costs you almost nothing in resources while giving you this escape hatch.**It behaves like Ubuntu** underneath. Same package manager, same community documentation, same`apt install`\n\neverything.**It's forgiving.** If you mess up your SSH config and lock yourself out, you can still physically sit down at the machine and fix it without needing a rescue USB.\n\nUbuntu Server uses around 200–300 MB less RAM, so keep that in mind. If you want to start with Ubuntu Server anyway, go for it. The rest of this guide works the same way.\n\n## Step 2: Using Micro\n\nIf you're not used to working in the terminal, I recommend you install [Micro](https://micro-editor.github.io/) to start. This is the text editor you'll use for everything configuration-related on the server.\n\n```\nsudo apt install micro\n```\n\nMost Linux guides assume you use `nano`\n\nor `vim`\n\n. Nano is fine and Vim is powerful, but has a learning curve that is famously steep, the mere act of exiting is a meme. (The answer, by the way, is to press `Esc`\n\n, then type `:q!`\n\nand press Enter. `:wq`\n\nif you want to save first.)\n\nMicro, on the other hand, has cursor support and uses familiar shortcuts. `Ctrl+S`\n\nto save, `Ctrl+Q`\n\nto quit, `Ctrl+Z`\n\nto undo. It feels like a GUI text editor.\n\n## Step 3: SSH Keys\n\nNext, you'll need to get the local IP address of your server, run `ip addr`\n\non the server itself for that. When you set up Ubuntu/Lubuntu, you'll provide a username. You put these together:\n\n`your-username@your-server-local-ip`\n\nFor example, mine is `brennan@192.168.1.66`\n\nSSH (Secure Shell) is then the backbone of everything that follows. It lets you connect to your server from any other machine, like your laptop in the living room, or in a coffee shop, anywhere really—and run commands as if you were sitting in front of the server.\n\nInstead of logging in with a password (which is less secure and more annoying), we use a key pair: a private key that lives on your computer, and a public key that goes on the server. The server will only let in machines that have the matching private key.\n\nThere are [detailed guides for this on ssh.com](https://www.ssh.com/academy/ssh/keygen), but the short version:\n\n```\n# On your local machine (not the server)\nssh-keygen -t ed25519 -C \"your-email@example.com\"\n```\n\nThis generates two files: `~/.ssh/id_ed25519`\n\n(your private key, **NEVER** share this) and `~/.ssh/id_ed25519.pub`\n\n(your public key, this goes on the server and can be shared).\n\nI also made [a handy script for generating keys at once](https://source.tube/brennan/omg.lol/src/branch/main/scripts/key-generator.sh) that I originally made for omg.lol. You can see all my public keys on my [/keys](https://brennan.day/keys) page!\n\nNext, copy your SSH key to your server:\n\n```\nssh-copy-id -i ~/.ssh/id_ed25519.pub your-username@your-server-local-ip\n```\n\nOnce your key is copied over, harden the SSH config:\n\n```\nsudo micro /etc/ssh/sshd_config\n```\n\nSet these values:\n\n```\nPasswordAuthentication no\nPubkeyAuthentication yes\nPermitRootLogin no\n```\n\nSave, then restart SSH:\n\n```\nsudo systemctl restart sshd\n```\n\nFrom this point forward, you can connect from your desktop computer to the server with the command:\n\n```\nssh your-username@your-server-local-ip\n```\n\n## Step 4: Keep the Server Running Indefinitely\n\nBy default, a desktop like Lubuntu will put itself to sleep after a period of inactivity. Great for a desktop, bad for a server. Here's how to disable that:\n\n```\n# Disable systemd sleep targets\nsudo systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target\n\n# Disable screen blanking (add to ~/.bash_profile or run at login)\nxset s off\nxset -dpms\nxset s noblank\n```\n\nIf you're using a laptop as your server, also disable lid-close sleep:\n\n```\nsudo micro /etc/systemd/logind.conf\n```\n\nSet:\n\n```\nHandleLidSwitch=ignore\nHandleLidSwitchExternalPower=ignore\n```\n\nThen:\n\n```\nsudo systemctl restart systemd-logind\n```\n\nTo prevent the display from turning off (optional, but nice if the machine has a monitor you occasionally glance at):\n\n```\nsudo micro /etc/X11/xorg.conf.d/10-noblank.conf\nSection \"ServerFlags\"\n  Option \"BlankTime\" \"0\"\n  Option \"StandbyTime\" \"0\"\n  Option \"SuspendTime\" \"0\"\n  Option \"OffTime\" \"0\"\nEndSection\n```\n\nIf you're using WiFi for server connectivity (instead of Ethernet), the WiFi adapter may enter power-save mode and stop responding to connections. For me, this caused a confusing situation where your site is online but you can't SSH in.\n\n**Symptoms:**\n\n- Local SSH unreachable but Cloudflare Tunnel works\n- ARP table shows \"incomplete\" for server IP\n`ip link`\n\nshows WiFi interface in DORMANT state\n\n**Disable WiFi Power Save:**\n\n```\n# Find your WiFi interface name\nip link show\n# Look for something like wlxbc071d481e84 or wlan0\n\n# Disable power save immediately (replace with your interface name)\nsudo iw dev YOUR_INTERFACE set power_save off\n\n# Verify it's disabled\nsudo iw YOUR_INTERFACE get power_save\n# Should show: Power save: off\n```\n\n**Make it persistent across reboots:**\n\n```\n# Create a systemd service\nsudo tee /etc/systemd/system/wifi-powersave-off.service > /dev/null << 'EOF'\n[Unit]\nDescription=Disable WiFi power save\nAfter=network.target\n\n[Service]\nType=oneshot\nExecStart=/usr/sbin/iw dev YOUR_INTERFACE set power_save off\n\n[Install]\nWantedBy=multi-user.target\nEOF\n\n# Enable and start the service\nsudo systemctl enable wifi-powersave-off.service\nsudo systemctl start wifi-powersave-off.service\n```\n\nReplace `YOUR_INTERFACE`\n\nwith your actual WiFi interface name from `ip link show`\n\n.\n\n**Alternative: NetworkManager configuration**\n\n```\nsudo tee /etc/NetworkManager/conf.d/wifi-powersave.conf > /dev/null << 'EOF'\n[connection]\nwifi.powersave = 2\nEOF\n\nsudo systemctl restart NetworkManager\n```\n\n**Note:** If possible, use Ethernet instead of WiFi for your server. Ethernet is more reliable, has lower latency, and doesn't have power management issues.\n\n## Step 5: Port Forwarding vs. Cloudflare Tunnel\n\nThis is the moment where most beginner guides gloss over an important decision: You have a server running on your home network, but how does the outside world reach it? There are two main approaches:\n\n### Option A: Port Forwarding\n\nYour home router sits between the internet and your devices. By default, it blocks all incoming connections from the outside. Port forwarding punches a specific hole in that wall: \"if someone requests port 80 (HTTP) or 443 (HTTPS), send them to this machine.\"\n\nYou configure this in your router's admin interface (usually at `192.168.1.1`\n\nor `192.168.0.1`\n\n). The process varies by router, but you're looking for \"Port Forwarding\" or \"Virtual Servers\" in the settings.\n\n**Pros:**\n\n- No third party involved\n- Fully direct connection, lowest latency\n- No dependency on Cloudflare's uptime\n\n**Cons:**\n\n- Your home IP address is publicly visible\n- If your ISP gives you a dynamic IP (which most residential ISPs do), your address changes periodically — you need a Dynamic DNS (DDNS) service like\n[DuckDNS](https://www.duckdns.org/)to keep a stable domain pointing at it - Some ISPs block incoming connections on port 80/443 on residential plans\n- You are directly exposing your home network to the internet — if your server has a vulnerability, it's reachable\n\n### Option B: Cloudflare Tunnel\n\nNow, [I've criticised Cloudflare in the past](https://brennan.day/the-internets-landlord-problem/), and the problems with their leadership is something to keep in mind.\n\nWith that said, [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/) (formerly Argo Tunnel) works differently from port forwarding. Instead of opening your router, a small daemon called `cloudflared`\n\nruns on your server and *reaches out* to Cloudflare's network, establishing a persistent encrypted connection. Cloudflare then proxies requests through that tunnel to your server.\n\nYour home IP is never exposed. You don't touch your router. It works even if your ISP blocks port 80/443. It works behind CGNAT (the thing some ISPs do where multiple households share a single IP address, making traditional port forwarding impossible).\n\n**Pros:**\n\n- No router configuration\n- Home IP stays private\n- Works with CGNAT and restrictive ISPs\n- Free tier is generous for personal use\n- SSL certificates are handled automatically\n\n**Cons:**\n\n- Cloudflare sits between you and your visitors (they see your traffic)\n- Dependency on Cloudflare's infrastructure\n- Against Cloudflare's ToS to serve large media files through a tunnel\n\n**My recommendation for beginners: start with Cloudflare Tunnel.** It's more forgiving, requires less networking knowledge, and you can always switch to port forwarding later. The privacy tradeoff is there, but for a personal homelab, I think it's reasonable.\n\nHere's how you set up Cloudflare tunnel:\n\n- Create a free account at\n[cloudflare.com](https://www.cloudflare.com/)and add your domain - Install\n`cloudflared`\n\n:\n\n```\n# Add Cloudflare's apt repo\ncurl -L --output cloudflared.deb https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb\nsudo dpkg -i cloudflared.deb\n```\n\n- Authenticate and create a tunnel:\n\n```\ncloudflared tunnel login\ncloudflared tunnel create my-homelab\n```\n\n- Configure your tunnel in\n`~/.cloudflared/config.yml`\n\n:\n\n```\ntunnel: YOUR-TUNNEL-ID\ncredentials-file: /home/youruser/.cloudflared/YOUR-TUNNEL-ID.json\n\ningress:\n  - hostname: files.yourdomain.com\n    service: http://localhost:8080\n  - hostname: blog.yourdomain.com\n    service: http://localhost:2368\n  - service: http_status:404\n```\n\n- Route DNS and start the tunnel:\n\n```\ncloudflared tunnel route dns my-homelab files.yourdomain.com\nsudo cloudflared service install\nsudo systemctl start cloudflared\n```\n\n## Step 6: Docker and Caddy\n\n[Docker](https://www.docker.com/) is what makes running a dozen services on one machine practical. Instead of installing each piece of software directly on your OS (where they'd fight over dependencies and configurations), Docker packages each service in its own isolated container. Each container has everything it needs. They run side by side without interfering with each other. When you want to remove a service, you remove the container. The host machine stays clean.\n\nInstall Docker:\n\n```\ncurl -fsSL https://get.docker.com -o get-docker.sh\nsudo sh get-docker.sh\nsudo usermod -aG docker $USER\n```\n\nLog out and back in. Now you can run Docker commands without `sudo`\n\n.\n\n[Caddy](https://caddyserver.com/) is a web server and reverse proxy. A reverse proxy sits in front of all your services and routes incoming requests to the right container. When someone visits `files.brennan.cafe`\n\n, Caddy looks at the domain name and forwards the request to whatever container is serving FileBrowser on port 8080.\n\nCaddy's killer feature is automatic HTTPS: it provisions and renews SSL certificates from Let's Encrypt automatically, with zero configuration. You don't think about it. It just works.\n\nA `Caddyfile`\n\nlooks like this:\n\n```\nfiles.yourdomain.com {\n    reverse_proxy localhost:8080\n}\n\nwiki.yourdomain.com {\n    reverse_proxy localhost:8090\n}\n```\n\nInstall Caddy:\n\n```\nsudo apt install -y debian-keyring debian-archive-keyring apt-transport-https\ncurl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg\ncurl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list\nsudo apt update\nsudo apt install caddy\n```\n\nEdit `/etc/caddy/Caddyfile`\n\nwith your subdomains and service ports, then:\n\n```\nsudo systemctl reload caddy\n```\n\n## Step 7: Setting Up Monitoring\n\nBefore you deploy a bunch of services, set up monitoring so you can actually see what's happening on your server. You can't manage what you can't measure. This is also a great way to understand how Docker works.\n\n**Beszel**: Internal server monitoring (CPU, RAM, disk, network, per-container stats)\n\nInstall Beszel with Docker:\n\n```\ndocker run -d \\\n  --name beszel \\\n  --restart unless-stopped \\\n  -p 3000:3000 \\\n  -v /beszel_data:/beszel_data \\\n  henrygd/beszel:latest # This is the entire service!\n```\n\nAccess the dashboard at `http://your-server-ip:3000`\n\nand follow the setup wizard to add your server as an agent.\n\n**Uptime Kuma**: External uptime monitoring (checks if services are up from the outside)\n\nInstall Uptime Kuma with Docker:\n\n```\ndocker run -d \\\n  --name uptime-kuma \\\n  --restart unless-stopped \\\n  -p 3001:3001 \\\n  -v uptime-kuma:/app/data \\\n  louislam/uptime-kuma:1\n```\n\nAccess at `http://your-server-ip:3001`\n\nand add monitors for your services.\n\n**Dozzle**: Real-time Docker log viewer\n\nInstall Dozzle with Docker:\n\n```\ndocker run -d \\\n  --name dozzle \\\n  --restart unless-stopped \\\n  -p 8080:8080 \\\n  -v /var/run/docker.sock:/var/run/docker.sock \\\n  amir20/dozzle:latest\n```\n\nAccess at `http://your-server-ip:8080`\n\nto view logs from all your containers in real-time.\n\n## Step 8: Setting Up Backups\n\nBefore you add more services, set up a backup strategy. Duplicati is a solid choice, as it supports multiple destinations (Backblaze B2, S3, SFTP, Google Drive, OneDrive) and handles encryption, scheduling, and deduplication automatically.\n\nInstall Duplicati with Docker:\n\n```\ndocker run -d \\\n  --name duplicati \\\n  --restart unless-stopped \\\n  -p 8200:8200 \\\n  -v duplicati_config:/data \\\n  -v /home/brennan:/source \\\n  duplicati/duplicati:latest\n```\n\nAccess at `http://your-server-ip:8200`\n\nand configure:\n\n- Add a backup destination (Backblaze B2 is affordable and reliable)\n- Select the directories to back up (\n`/home/brennan/cafe`\n\n,`/data/coolify`\n\n, Docker volumes) - Set a schedule (daily at 3 AM is reasonable)\n- Enable encryption with a strong passphrase\n\nImportant:Test your backup by performing a restore. A backup you can't restore is not a backup.\n\n## Step 9: Deploying Services with Coolify\n\n[Coolify](https://coolify.io/) is, as the name implies, really cool. It's a self-hosted alternative to Heroku, Netlify, or Vercel. A web dashboard where you connect a git repository, configure environment variables, and click Deploy. It handles the Docker build, the container orchestration, the reverse proxy config, and the SSL certificate.\n\nFor beginners who don't yet want to write `docker-compose.yml`\n\nfiles by hand, Coolify is a great on-ramp. It comes with one-click installers for Nextcloud, Ghost, WordPress, n8n, Gitea, Plausible Analytics, and dozens of other services.\n\nInstall Coolify with one command:\n\n```\ncurl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash\n```\n\nThen access the dashboard at `http://your-server-ip:8000`\n\nand follow the setup wizard. You'll configure your domain, set up SSH key access to the server (Coolify uses this to manage containers), and you're off.\n\n**A note on resource use:** Coolify itself is more resource-intensive than running containers manually, I've found it uses 300–500 MB of RAM at rest. On an 8 GB machine, that's fine. On a 4 GB machine, you might prefer managing Docker Compose files directly.\n\n### Deployment Order\n\nIf you're following this guide from start to finish, here's a recommended order for deploying services. This builds incrementally and gives you useful tools early:\n\n**Dozzle**: Fastest to deploy, immediately useful for debugging** Beszel + Agent**: Get visibility into your server ASAP** Uptime Kuma**: Monitor all your existing services** Duplicati**: Set up backups before you add more services** Vaultwarden**: Move passwords off commercial providers** Coolify**: Set up your deployment platform** FreshRSS or Miniflux**: Needs PostgreSQL if using Miniflux** Linkding**: Quick single-container deploy** Shlink**: Quick single-container deploy** Pi-hole**: Requires network-level DNS config change on your router\n\n## Step 10: Good Ol' Fashion Blogging\n\n[Hugo](https://gohugo.io/) is a fantastic option for a homelab blog. Generates a static site from plain Markdown files. There's no database, no PHP, no runtime. Just a folder of `.md`\n\nfiles turned into folder of `.html`\n\nfiles.\n\nI specifically created the bash tool [ writer-cli](https://writer.brennan.day) for this use-case! I also created the Hugo blog theme\n\n[IndiePaper](https://github.com/brennanbrown/indiepaper)for people that want a template that has full IndieWeb functionality built-in. The workflow is:\n\n- Write a post in Markdown with my\n`writer-cli`\n\nscript - Hugo rebuilds the site (takes about 200ms for a large site)\n- Caddy serves the static output\n\nTo run Hugo in Docker:\n\n```\nFROM klakegg/hugo:ext-alpine AS builder\nCOPY . /src\nWORKDIR /src\nRUN hugo --minify\n\nFROM caddy:alpine\nCOPY --from=builder /src/public /usr/share/caddy\n```\n\nOr just install Hugo directly:\n\n```\n# Download the latest release\nwget https://github.com/gohugoio/hugo/releases/download/v0.128.0/hugo_extended_0.128.0_linux-amd64.deb\nsudo dpkg -i hugo_extended_0.128.0_linux-amd64.deb\n```\n\nAnd serve the site:\n\n```\nhugo server --bind 0.0.0.0 --baseURL https://blog.yourdomain.com\n```\n\n## Step 11: The Wiki (Document As You Go)\n\nA great project to have on your homelab is a wiki for the homelab itself. The more you work on it, the more you'll learn. It's a virtuous cycle! Document everything and keep notes as you go.\n\n[DokuWiki](https://www.dokuwiki.org/) is my choice because it's flat-file (no database), and the search works great. But [Wiki.js](https://js.wiki/), or even a plain [Obsidian](https://obsidian.md/) vault synced to your server would work fine.\n\nWhat goes in the wiki:\n\n- Every command you run that you had to look up\n- Every config file you edited and what you changed\n- Every error you encountered and how you fixed it\n- Port assignments for all your services (so you don't accidentally give two things the same port)\n- Your Docker Compose files, in full\n- Notes on what broke and why\n\nSix months from now, when something stops working and you can't remember how you set it up, you'll thank yourself.\n\n## Step 12: Security Beyond SSH\n\nSSH hardening is a good start, but there are a few more security basics worth implementing.\n\n**UFW (Uncomplicated Firewall)**: A simple firewall management tool\n\n```\nsudo apt install ufw\nsudo ufw default deny incoming\nsudo ufw default allow outgoing\nsudo ufw allow ssh\nsudo ufw allow 80/tcp\nsudo ufw allow 443/tcp\nsudo ufw enable\n```\n\nThis blocks all incoming traffic except SSH, HTTP, and HTTPS — which is all you need for a web server.\n\n**Fail2ban**: Ban brute-force attackers\n\n```\nsudo apt install fail2ban\nsudo systemctl enable fail2ban\nsudo systemctl start fail2ban\n```\n\nFail2ban monitors log files and bans IPs that show malicious signs (too many failed SSH login attempts, etc.).\n\n**Automatic Security Updates**\n\n```\nsudo apt install unattended-upgrades\nsudo dpkg-reconfigure -plow unattended-upgrades\n```\n\nThis will automatically install security updates on your system, reducing the window of vulnerability.\n\n## Appendix: Power Consumption and Cost\n\nRunning a server 24/7 has an ongoing cost in electricity. The AMD FX-4130 in my own tower has a 125W TDP (Thermal Design Power). In practice, at idle with light services running, it draws about 40–60 watts from the wall. Under load, it might spike to 80–100 watts.\n\n**Monthly cost calculation:**\n\n- Average draw: 50 watts\n- Hours per day: 24\n- Days per month: 30\n- Total kWh: 50W × 24h × 30d ÷ 1000 = 36 kWh\n- Cost at $0.12/kWh: 36 × $0.12 = $4.32/month\n\nSo you're looking at roughly $4–$6 per month in electricity costs for a machine like this. That's not nothing, but it's significantly less than the monthly cost of cloud services.\n\nIf you're concerned about power use, consider:\n\n- Using a more efficient CPU (Intel NUC, Raspberry Pi, or modern low-power desktop)\n- Aggressively power-managing the machine (CPU frequency scaling, aggressive sleep settings on unused services)\n- Running the server on a schedule (only on when you need it)\n\n## A Final Note\n\nWow, that was a lot of steps! Let me tell you, like anything related to programming, you will have bugs. You will have errors. You will be searching and trying to find solutions, and sometimes things will stay broken for a long time.\n\nBecause I've primarily been a front-end webdev for over a decade, I've always run into trouble with devOps. But I just kept returning, I kept figuring out better practices. Better fundamentals. And now my homelab has [better uptimes than GitHub](https://mrshu.github.io/github-statuses/):\n\nThis isn't about the easiest, fastest solution. This isn't about splurging on powerful hardware to replace your entire digital life. Start where you are. Use what you have. Do what you can.\n\nThis is about envisioning a web that's affordable, accessible, and focused on *learning*. My God, how are we supposed to learn anything if everything works the first time or we offload troubleshooting to someone else? (or worse, an error-prone genAI bot?)\n\nHomelabbing is a reclamation project. To reclaim the *understanding* of what the Internet is, and how we can create and build it ourselves.", "url": "https://wpnews.pro/news/homelab-for-the-beginner-you-can-self-host-your-own-server-on-50-hardware", "canonical_source": "https://brennan.day/homelab-for-the-beginner-you-can-self-host-your-own-server-on-50-hardware/", "published_at": "2026-05-28 20:00:00+00:00", "updated_at": "2026-06-13 06:56:26.498517+00:00", "lang": "en", "topics": ["developer-tools"], "entities": ["Nextcloud", "Vaultwarden", "FreshRSS", "Forgejo", "Matrix", "Immich", "Ghost", "Umami"], "alternates": {"html": "https://wpnews.pro/news/homelab-for-the-beginner-you-can-self-host-your-own-server-on-50-hardware", "markdown": "https://wpnews.pro/news/homelab-for-the-beginner-you-can-self-host-your-own-server-on-50-hardware.md", "text": "https://wpnews.pro/news/homelab-for-the-beginner-you-can-self-host-your-own-server-on-50-hardware.txt", "jsonld": "https://wpnews.pro/news/homelab-for-the-beginner-you-can-self-host-your-own-server-on-50-hardware.jsonld"}}