Blog freshness: Research notes liveLatest update: May 2026Telemetry mode: Public-safe live stripAI tools: Self-hosted demos live
Skip to main content
General
June 20, 2025
5 min read

🧱 Home Server Chronicles: My Docker-Powered Ecosystem β€” Part 1

An in-depth look at the journey of building a modular, containerized home server using Docker Compose on a Beelink SER8 mini PC.

Words

934

Read Time

5 min read

Category

General

Read aloud
Browser TTS unavailable
Ready for a more natural read-aloud pass.
Reading list
Reading History

Recent articles you open here will appear in this quick history.

#Docker#Self-Hosting#Home Lab#Linux#DevOps#Beelink+1

🏑 Welcome to My Home Lab

This is Part 1 of an ongoing series where I document my self-hosted infrastructure journeyβ€”setting up, securing, and scaling an efficient and modular Docker ecosystem on my home server. I’ll take you through the choices I made, services I run, and challenges I solved.

For context: I'm running this system on a πŸ–₯️ Beelink SER8 mini PC, equipped with:

  • AMD Ryzen 7 8745HS
  • 12GB DDR5 RAM
  • 1TB NVMe SSD (boot + Docker)
  • 3.6TB NVMe SSD (media & Immich storage)
  • 932GB External SSD (backups & overflow)
  • Ubuntu 24.04 LTS

This machine replaced my Mac mini for Docker workloads and now acts as the heart of my home cloud, developer platform, and AI lab.

Additionally, I maintain a backup VPS on Oracle Cloud Infrastructure (OCI) that serves as an off-site backup location and disaster recovery solution. I migrated from Digital Ocean to OCI for better performance and cost efficiency β€” see my migration post for details.


πŸ“¦ Why Docker?

I chose Docker for the following reasons:

  • 🧱 Isolation: Each service runs in its own container
  • πŸ” Reproducibility: No more β€œit works on my machine” issues
  • πŸš€ Portability: Move the stack between devices
  • πŸ“„ Declarative Configuration: All setup lives in docker-compose files

🧠 Design Principles

My goal was to keep things modular, composable, and resilient. Here’s what that looked like:

  • πŸ”Ή Split Compose files into roles: core.yml, media.yml, infra.yml, extras.yml, immich.yml
  • πŸ”Ή Avoid monolithic configurations
  • πŸ”Ή Use external networks defined in a central networks.yml
  • πŸ”Ή Enable restart policies and volume mapping for persistence
  • πŸ”Ή Log and monitor every service via Netdata

Each service is deployed headlessly, accessed either via browser, REST APIs, or reverse proxy.


πŸ—‚οΈ Overview of the Series

| Part | Title | |------|-------| | 1️⃣ | Intro & Architecture (you are here) | | 2️⃣ | Core Services: Nginx Proxy Manager, Authentik, Tailscale | | 3️⃣ | Infra Layer: Portainer, Netdata, Watchtower, Backups | | 4️⃣ | Media Stack: Jellyfin, Sonarr, Radarr, Lidarr, Navidrome | | 5️⃣ | Productivity & Photos: Nextcloud, Immich, Paperless-NGX, Vaultwarden |

Let’s begin with the big pictureβ€”how it’s all wired together.


🧱 Architecture

Here's a bird’s eye view of my setup:

                                      +-----------------------+
                                      |  Beelink SER8 (Host)  |
                                      +-----------------------+
                                                |
                       +------------------------+-------------------------+
                       |                        |                         |
                 Docker Compose          External Access             VPN Tunnel
              (core.yml + others)        (NPM, Authentik)             (Tailscale)
                       |
        +--------------+---------------------+------------------+
        |              |                     |                  |
    Core Stack      Media Stack        Productivity        AI & Tools
  (NPM, Auth,    (Jellyfin, Sonarr,  (Nextcloud, Immich,  (Open WebUI,
   MariaDB)       Radarr, Lidarr)     Paperless-NGX)       PodcastAI)

Every service belongs to a category and communicates through pre-defined Docker networks, with networks.yml acting as the shared config.

πŸ”„ Backup & Disaster Recovery: My setup includes an Oracle Cloud (OCI) VPS that serves as an off-site backup location, running the portfolio and critical services with data redundancy and quick recovery in case of hardware failure.


πŸ”„ Modularity with Compose

βž• File Structure

docker_services/
β”œβ”€β”€ core.yml
β”œβ”€β”€ infra.yml
β”œβ”€β”€ media.yml
β”œβ”€β”€ extras.yml
β”œβ”€β”€ immich.yml
β”œβ”€β”€ networks.yml
└── .env

🧩 Why Split Files?

This modular split helps in:

  • βœ… Running specific layers independently
  • βœ… Upgrading only what you need
  • βœ… Easier debugging and configuration
  • βœ… Clear separation of concern

I also prefix volumes and container names per file to avoid naming conflicts.


🌐 Networks & Naming

Defined in networks.yml:

networks:
  proxy_net:
    name: proxy_net
    driver: bridge
    attachable: true
    ipam:
      config:
        - subnet: 172.28.0.0/24
          gateway: 172.28.0.1
  core_net:
    name: core_net
    driver: bridge
    internal: true    # Isolates DBs from direct internet access
  media_net:
    name: media_net
    driver: bridge
  infra_net:
    name: infra_net
    driver: bridge
  extras_net:
    name: extras_net
    driver: bridge

Services declare these external networks in their own files. This ensures containers are interoperable across layers without duplicating definitions.


πŸ” Secrets and Security

Security is critical. Even a home server should have strong hygiene:

  • πŸ”‘ .env files store secrets (never committed)
  • πŸ”’ Authentik SSO + Nginx Proxy Manager enable 2FA and domain routing
  • 🌍 Tailscale manages zero-config VPN with ACLs

All admin UIs are hidden behind TOTP authentication or VPN entry.


🧭 Reverse Proxy Flow

The reverse proxy stack routes requests like this:

User β†’ https://service.jay739.dev
       ↳ Nginx Proxy Manager
           ↳ Authentik (SSO/2FA if protected)
               ↳ Internal Docker container

Each app is accessible via a subdomain thanks to NPM + wildcard DNS setup via Porkbun DDNS, with local DNS resolution handled by dnsmasq pointing to the LAN IP (10.0.0.101).


πŸ“ˆ Monitoring & Maintenance

Every container’s health is tracked using Netdata, running on a dedicated infra container and exposed via:

πŸ”— https://metrics.jay739.dev

I also have a custom Telegram bot for real-time alerting on service health β€” covered in a separate post.


🧰 Core Tools Installed on Host

Even though most things run in Docker, I have some native tools:

  • πŸ›œ tailscale β€” for remote access
  • 🐳 docker, docker-compose β€” core engine
  • πŸ“¦ fail2ban β€” SSH brute force protection
  • πŸ“ƒ rsync, cron β€” automated local backups
  • πŸ“Š htop, btop β€” system resource monitoring

πŸš€ What’s Next?

In the next part of this series, I’ll walk you through the Core Services stack in detail: reverse proxy, domain mapping, VPN access, and 2FA gateways.

Stay tuned, and feel free to reach out if you want to replicate this setup or have questions on customizing your own server stack! πŸ’¬


πŸ‘‰ Part 2 β†’ Core Services (Nginx Proxy Manager, Authentik, Tailscale)

β€” Jayakrishna

Continue Reading

These are close to this article’s reading time, so they make a good next step without a big context switch.