When people talk about self-hosting, it's usually around media servers, photo backups, and cloud storage replacements. And I agree, those are important, and that’s why I built my own home server in the first place.
But a home server can run dozens of containers and still feel surprisingly amateur. Not because the applications themselves are bad, but because managing them often requires a lot of guesswork.
Over time, I have experimented with several tiny utility containers that made my server feel more mature, and I eventually settled on four. They’re small, easy to deploy, and arguably some of the most useful services in my stack that actually help me understand and manage everything else.
9 Docker containers that run 24/7 on my $100 mini PC
Maximum value budget homelab.
Vaultwarden
The password manager you keep putting off
I have been using Bitwarden Premium for many years as my default password manager. The world has recently been moving from passwords and 2FAs to a single passwordless login. And frankly, it has been convenient, too. But it also came with a dependency on a particular device. For example, if I created a passkey on my iPhone, I would need my iPhone each time to log in to that account.
That’s when I decided to centralize the process. Bitwarden also supports passkeys, but lately, I have been trying to move my daily-used services to my homelab server. Bitwarden did come with a self-host option, but the server is heavy (needs over 1GB to run comfortably), and that’s not worth it for my old Debian server. Then I came across Vaultwarden, an unofficial Bitwarden-compatible server written in Rust that takes less than 50MB of memory while running. And since it’s Bitwarden-compatible, I could use the same Bitwarden apps and browser extension to use it.
All my credentials now live on my hardware, not someone else's server. Hard to argue with hosting your own passwords and passkeys on your own hardware. I have been using it for several months, and now I think I should have done this earlier.
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
ports:
- "8090:8080"
volumes:
- /opt/vaultwarden/data:/data
environment:
- DOMAIN=https://your-domain.com
- ROCKET_PORT=8080
- ADMIN_TOKEN=your_secure_admin_token
- WEBSOCKET_ENABLED=true
- PASSWORD_MIN_LENGTH=8
restart: unless-stopped
Vaultwarden
- Key highlights
- Self-hosted Bitwarden alternative
Beszel
Lighter than what it replaced
These days, monitoring a server feels like flying an Airbus just to check the weather. It is far more complicated and takes more resources than the actual service it’s monitoring. Why would I want a monitoring tool that either showed me nothing useful or had full-blown enterprise-grade stats that I didn’t need? I have been searching for a monitoring tool that could answer my one question: is my server healthy? Beszel answered that exactly, without overwhelming the whole process.
Beszel depends on two components — a lightweight agent running on the server being monitored and a simple GUI dashboard that displays the metrics. Combined, they don’t take more than 40MB of memory. And the UI is simple enough to glance at the numbers and immediately know what needs my attention. The hub focuses on four core metrics: CPU, RAM, disk, and network usage, which is exactly what I need to know if my server is healthy. I have already used enterprise-level monitoring services like Datadog and Zabbix for large-scale infrastructure, but for a small homelab, they are overkill.
services:
beszel-agent:
image: henrygd/beszel-agent:latest
container_name: beszel-agent
network_mode: host
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- beszel_agent_data:/var/lib/beszel-agent
environment:
- HUB_URL=https://your-beszel-hub-url
- LISTEN=45876
- KEY=your_ssh_ed25519_public_key
- TZ=Asia/Kolkata
restart: unless-stopped
volumes:
beszel_agent_data:
Beszel
Beszel is a lightweight server and container monitoring utility that can be used to track multiple servers via a single dashboard.
Watchtower
Updates itself. Updates everything.
I always say in my articles that deploying a service and making it feel like a cloud service is one thing, and keeping it running is a different story. New homelabbers follow a pattern: deploy and forget. Manually updating containers is something most homelab owners either forget or defer. Even I am one of them. I have more than 15 active services in my stack, but I barely check for any updates. The only time I update something is when a pop-up appears on my screen asking me to.
That’s where Watchtower came in. It monitors Docker images and updates the containers automatically. The first time I ran it, it scanned 21 images and updated 15 of them. So, even I — someone who always talks about security and privacy constantly — am lazy enough not to update the services I use regularly. The interesting fact is that it takes less than 20MB of runtime memory. So, it barely dents your memory; you just need to deploy it once and forget about it. And you don’t need to worry about it forcing updates at inconvenient times, Windows-style. I scheduled it to run at a specific time, and it sticks to that.
services:
watchtower:
image: containrrr/watchtower
container_name: watchtower
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- WATCHTOWER_SCHEDULE=0 30 10 * * *
- WATCHTOWER_CLEANUP=true
- DOCKER_API_VERSION=1.44
restart: unless-stopped
Watchtower
Watchtower automatically updates your Docker containers on a schedule, cleans up old images, and keeps self-hosted stacks current without manual intervention.
Speedtest Tracker
Your ISP doesn't get to lie anymore
Ever encountered inconsistent download or upload issues from your ISP, and when you complain, the ISP asks for a speed test report, declares everything fine, and closes the ticket? Happens to me all the time. And I never have any proof to show them. That’s when I came across Speedtest Tracker.
Save on Storage & Networking deals for your homelab
It’s a simple tracker that runs on a fixed schedule, logs every result, and builds a history. Not just download and upload speeds, but also latency, jitter, and packet loss. And it is accessible through a clean web dashboard. Yes, it is a little heavier than the other three on this list, taking around 120MB of memory, but that's because it's the only one with a database backing the historical logs.
When something feels wrong, I can check historical data before changing settings or restarting containers. It shifts troubleshooting from guesswork to evidence. Speedtest Tracker won't make your internet faster, but it tells you exactly when, where, and how your performance changes over time.
services:
speedtest-tracker:
image: lscr.io/linuxserver/speedtest-tracker:latest
container_name: speedtest-tracker
ports:
- "8765:80"
volumes:
- speedtest-config:/config
environment:
- PUID=1000
- PGID=1000
- APP_KEY=base64:your_generated_app_key
- APP_URL=http://your-server-ip:8765
- DB_CONNECTION=sqlite
- SPEEDTEST_SCHEDULE=0 */6 * * *
restart: unless-stopped
volumes:
speedtest-config:
Speedtest Tracker
Speedtest Tracker is a self-hosted application that monitors the performance and uptime of your internet connection.
The boring containers that keep everything else running
I didn’t add all these services at once. They get added to my stack gradually whenever I feel like I need them. Individually, none of them are particularly exciting. But together, they improve visibility, maintenance, and troubleshooting, with no guesswork required. The interesting part is that none of these Docker containers are resource-intensive. Some of them consume less memory than a browser window, and none of them are why anyone starts self-hosting, but they solve operational problems that appear every day that can pile up over time.
