Skip to main content

My Home Lab Setup

·639 words·3 mins
Home-Lab Tech Linux Homelab K8s Docker Debian
Rahul Mysore
Author
Rahul Mysore
Senior Software Engineer | Startups Guy | Go, K8s, LLM | 0 -> 1
Table of Contents

I finally decided to set up a home lab. After some research, I went with an HP EliteDesk 800 G6 with these specs:

  • CPU: Intel Core i5 10th Gen
  • RAM: 16 GB
  • Storage: 256 GB NVMe

I installed Debian 13 (Trixie) without a desktop environment a headless server all the way.


Installing Docker Engine
#

Since we’re running headless (no GUI), we install Docker Engine, not Docker Desktop (which requires a desktop environment).

# Remove old versions if any
sudo apt remove docker docker.io containerd runc

# Install prerequisites
sudo apt update
sudo apt install -y ca-certificates curl gnupg lsb-release

# Add Docker's GPG key
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg \
  -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# Add Docker repository
echo "deb [arch=$(dpkg --print-architecture) \
signed-by=/etc/apt/keyrings/docker.asc] \
https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Install Docker
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io \
  docker-buildx-plugin docker-compose-plugin

# Add your user to docker group (no sudo needed)
sudo usermod -aG docker $USER

# Enable and start Docker
sudo systemctl enable docker
sudo systemctl start docker

# Verify
docker run --rm hello-world

Note: Log out and back in for group changes to take effect, or run newgrp docker.


Server Hardening
#

For basic security, I installed fail2ban to protect against brute force attacks:

sudo apt install fail2ban -y
sudo systemctl enable fail2ban --now

Then I set up UFW (Uncomplicated Firewall):

sudo apt install ufw -y
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw enable

It’ll warn you that enabling UFW may disrupt SSH—type y and hit enter.

Verify both are running:

sudo ufw status
sudo systemctl status fail2ban

UFW should show Status: active with a rule allowing SSH.


Tailscale VPN
#

I installed Tailscale on my laptop, phone, and server for easy remote access.

curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up

Your nodes will show up in the Tailscale admin console. You can then SSH into your server from anywhere using the Tailscale IP or MagicDNS name (e.g., user@your-server.tailnet.ts.net). I used MagicDNS to access Portainer from my laptop and it worked perfectly.


Portainer
#

For a web UI to manage containers, I installed Portainer:

docker volume create portainer_data

docker run -d \
  --name portainer \
  --restart unless-stopped \
  -p 9000:9000 \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v portainer_data:/data \
  portainer/portainer-ce:latest

Access it at http://your-tailscale-server:9000.


Pi-hole DNS Sinkhole
#

Why? Pi-hole blocks ads and trackers at the network level by acting as a DNS sinkhole. Instead of installing ad blockers on every device, you just point your DNS to Pi-hole and it blocks requests to known ad/tracker domains.

Deploy via Portainer
#

Go to Stacks → Add stack, name it pihole, and paste:

services:
  pihole:
    image: pihole/pihole:latest
    container_name: pihole
    ports:
      - "53:53/tcp"
      - "53:53/udp"
      - "80:80"
    environment:
      - WEBPASSWORD=changeme    # change this!
      - TZ=America/New_York
    volumes:
      - ./etc-pihole:/etc/pihole
      - ./etc-dnsmasq.d:/etc/dnsmasq.d
    restart: unless-stopped

Hit Deploy the stack.

Configure Tailscale DNS
#

Why? Instead of configuring DNS on each device or router, Tailscale lets you push DNS settings to all connected devices. All your devices will automatically use Pi-hole for DNS queries.

Go to tailscale.com → Admin Console → DNS:

  1. Scroll to Nameservers → Add nameserver → Custom
  2. Enter your server’s Tailscale IP (100.x.x.x)
  3. Check Override local DNS
  4. Hit Save

All Tailscale devices will now route DNS through Pi-hole.

Fix Password Issue (If Needed)
#

If the WEBPASSWORD env var didn’t set properly (known Pi-hole issue), reset it:

docker exec -it pihole pihole setpassword yourpassword

Access Pi-hole admin at http://your-server/admin. Check the Query Log to see traffic flowing.


What’s Next?
#

This is just the beginning. Future posts will cover:

  • Installing k3s (lightweight k8s for homelabs)
  • Setting up networking and DNS
  • Deploying my first workloads
  • Monitoring and observability

Stay tuned!

Related

Neovim AI Tools
·546 words·3 mins
Setup Tech Linux AI Nvim Vim Neovim Windsurf Opencode
Dank Material Shell, Niri and Custom Plugin
·562 words·3 mins
Side-Project Setup Tech Linux Go Niri Dms Quick-Shell Wm
My Linux Journey: From Ubuntu to Hyprland, Vim to Tiling Window Managers, and Everything In Between
·1213 words·6 mins
Setup Tech Linux Window-Managers I3 Hyprland Vim Neovim
Startup Interview and Defunct Process
·1115 words·6 mins
Interview Tech Linux Go CLI Defunct Concurrency
Building a TUI for Managing Systemd Services: A Fun Side Project
·745 words·4 mins
Side-Project Tech Linux Go Systemd TUI
Midwest Block-a-Thon
·602 words·3 mins
Hackathon Tech Blockchain Next.js Metamask Pinata