FAZLEY RABBI

Note · 2026-07-21

Running a Production-Grade Homelab on Bare Metal

"How I run multiple production apps, manage infrastructure remotely, and deploy AI agents all on a single Ubuntu server with zero monthly cost for AI models."

  • homelab
  • docker
  • cloudflare
  • tailscale
  • devops
  • self-hosting

The Vision: One Server, Many Projects

A single Ubuntu server. Multiple Laravel applications running in production a daily journal, an ERP system, a point-of-sale system, and more. And orchestrating it all? An AI agent named Hermes that I control from my phone via Telegram.

This isn’t a rented cloud VM or a VPS. It’s a repurposed ThinkPad T480 (bought used for under 25,000 BDT) running 24/7 as a dedicated bare metal server full OS, direct hardware access, no hypervisor overhead.

Hermes Agent Telegram Bot Interface


The Hardware

SpecDetails
ModelThinkPad T480 (20L6S29E00)
CPUIntel Core i5-8350U (8 cores) @ 1.70GHz
RAM8GB DDR4 (2× 4GB SODIMM @ 2133 MHz)
Storage238.5GB SK hynix SC401 SATA SSD
OSUbuntu 24.04.4 LTS
NetworkTailscale mesh VPN, Cloudflare Tunnel

Running on bare metal means no noisy neighbors, no hypervisor overhead, and full control over kernel parameters, networking, and storage.

Neofetch Server Hardware Details


The Software Stack: Docker Everything

Every project runs in its own Docker environment. Each one gets:

  • A FrankenPHP container for the web server (PHP 8.3, Caddy, worker mode)
  • A Redis container for caching and sessions
  • A MySQL container for the database
  • A Cloudflare Tunnel container for secure public access

The magic is Docker Compose. Each project lives in its own directory with its own docker-compose.prod.yml:

services:
  app:
    build: .
    container_name: erp_app
    restart: unless-stopped
    ports:
      - "8082:80"
    depends_on:
      - redis
      - mysql

  redis:
    image: redis:7-alpine
    container_name: erp_redis
    restart: unless-stopped

  cloudflared:
    image: cloudflare/cloudflared:latest
    container_name: erp_tunnel
    restart: unless-stopped
    command: tunnel run --token $TUNNEL_TOKEN

Docker Containers Status


Network Architecture: How Traffic Actually Flows

Here’s the path a request takes when you visit one of my apps:

User → Cloudflare Edge → Tunnel → Docker Container → FrankenPHP → Laravel
┌─────────────┐     ┌──────────────┐     ┌──────────────┐
│  Browser     │────▶│  Cloudflare  │────▶│  Server      │
│  (Anywhere)  │     │  Edge (CDN)  │     │  Tunnel      │
└─────────────┘     └──────────────┘     │  Container   │
                                          └──────┬───────┘
                                                 │
                                                 ▼
                                        ┌──────────────┐
                                        │  App Server   │
                                        │  (FrankenPHP) │
                                        └──────────────┘

Each project gets its own tunnel. No reverse proxy, no nginx config, no port forwarding the tunnel handles everything. Zero open ports on the server.

Cloudflare Tunnels List


The Remote Access Layer: Tailscale Mesh VPN

I manage everything from a MacBook, my phone, or via this very AI assistant but none of my devices share a local network. That’s where Tailscale comes in.

DeviceTailscale IPRole
Server100.x.x.85Main server
MacBook Pro100.x.x.10Development
Phone100.x.x.83On-the-go access

Tailscale creates a WireGuard-based mesh network. Every device gets a unique IP, and they can reach each other even through NAT, firewalls, or CGNAT. No port forwarding needed.

Tailscale Mesh Status


The AI Layer: Hermes Agent + Free AI Models

This is the part that surprises everyone. I run an AI agent with full shell access that I control through Telegram and it costs me zero dollars per month for AI inference.

The Providers

ProviderModelCost / Deployment
OpenCode ZenDeepSeek V4 Flash Free / MiMo V2.5 FreeFree API
OpenRouterGemma 4 31B / Nemotron Super / GPT-OSSFree API
GroqLlama 3.3 70BFree API
Local ContainerOllama / Llama (SignalStack Llama)Self-Hosted Docker

Hermes Agent

Hermes Agent is an open-source AI agent system. It can:

  • Run shell commands on the server
  • Read and edit files
  • Scan networks
  • Manage Docker containers
  • Debug production issues
  • Schedule cron jobs for maintenance
  • Use skills (reusable workflows)

And I control it entirely through Telegram no SSH client needed.

Hermes Agent Tunnel Inspection

# Hermes config  providers section
providers:
  openrouter:
    models:
      - deepseek/deepseek-chat:free
  opencode-zen:
    api_base: https://opencode-zen.ai/v1
    models:
      - deepseek-v4-flash-free

Real-World Debugging: The Cloudflare Tunnel Nightmare

Let me share a real debugging session that shows what this homelab can handle.

The Problem: One of my sites (dailylog.fazleyrabbi.xyz) started returning Error 502 bad gateway.

The Diagnosis:

  1. Checked Docker containers were healthy
  2. Checked the app internal curl localhost:80 returned 200 OK
  3. Checked the tunnel a rogue cloudflared process was running with a stale token

The Fix:

  1. Killed the stale PID
  2. Recreated the tunnel with cloudflared tunnel create
  3. Updated the DNS CNAME to point to the new tunnel ID
  4. Switched from --config to --token mode after Cloudflare’s dashboard migration

The Twist: After the migration, the old token was invalidated and the server rejected new connections with Error 1033. The fix required understanding how Cloudflare’s tunnel lifecycle works locally-defined tunnels vs dashboard-managed tunnels.

Error 1033 → "Migrate dailylog" → Dashboard migration → Token invalidated
          → New tunnel created → DNS CNAME updated → Site back online

Docker Logs Health Check Passing


Lessons Learned

What I’d Do Differently

  1. Use environment variables from day one embedding tokens in compose files is a maintenance trap
  2. Monitor tunnel health proactively a cron job checking tunnel status would have caught the stale process earlier
  3. Document DNS architecture the CNAME/tunnel relationship is easy to forget when troubleshooting at 2 AM

What Worked Well

  1. Docker isolation each project is truly independent. Breaking one doesn’t affect others
  2. Cloudflare Tunnel no open ports, no nginx config, automatic TLS. Worth every minute of learning curve
  3. Tailscale the mesh VPN pattern is superior to traditional VPNs for a multi-device homelab
  4. Hermes Agent having an AI assistant with shell access on Telegram is like having a sysadmin in your pocket

Project Directory

ProjectDomain / AccessTech Stack
DailyLogdailylog.fazleyrabbi.xyzLaravel + FrankenPHP + Redis
ERPerp.fazleyrabbi.xyzLaravel + FrankenPHP + MySQL
SignalStacksignalstack.fazleyrabbi.xyzLaravel + React + Redis + Local Llama
LitePOSLocal Port 8081Laravel POS + FrankenPHP + Redis
EduBaseLocal Port 8083Laravel + FrankenPHP + MySQL
MealHQLocal Port 8084Laravel + FrankenPHP + MySQL
OpenEnvMapLocal Port 3006React + Node API + PostgreSQL
Hujjah WebLocal Port 3002Next.js / Node
HomelabUbuntu + Docker + Tailscale
AgentTelegramHermes Agent + OpenRouter/Groq

Running Project Preview 1

Running Project Preview 2

Running Project Preview 3

Running Project Preview 4


The Cost Breakdown

ServiceMonthly Cost / Investment
Server Hardware$0 ongoing (used ThinkPad T480 bought <25k BDT)
AI Inference$0 (free tier models)
Cloudflare$0 (free tier)
Tailscale$0 (personal tier)
Domain~$15/year
Total~$1.25/month

Have a homelab setup? Questions about this architecture? Reach out I’m always happy to talk infrastructure.