DEV Community

Cover image for One Open Source Project a Day (No. 182): Homepage — A Sleek Unified Dashboard for All Your Self-Hosted Services
WonderLab
WonderLab

Posted on

One Open Source Project a Day (No. 182): Homepage — A Sleek Unified Dashboard for All Your Self-Hosted Services

Introduction

"More and more services, longer and longer bookmarks, and every time you need something you have to think for a moment — it's time for a dashboard."

This is the 182nd article in the "One Open Source Project a Day" series. Today's project is Homepage.

If you run a home server or NAS with Jellyfin, Nextcloud, Sonarr, Portainer, and a dozen other services all humming away — you've definitely felt the pain: every service lives on its own port, you manage them through memory or bookmarks, and the only way to check if something's healthy is to open it and look.

Homepage solves exactly this. It's a unified entry point dashboard for self-hosted services — configure all your services in YAML, auto-discover Docker containers, and get live status plus key metrics on a single page.

32.6k Stars, GPL-3.0, 200+ contributors, and Next.js static generation for blazing-fast loads.

What You Will Learn

  • Homepage's YAML configuration system (services, widgets, bookmarks, settings — four files)
  • How Docker Label auto-discovery works
  • 150+ Service Widget integrations (Sonarr, AdGuard Home, and more as examples)
  • Secure secret injection with environment variables
  • How Homepage stacks up against similar tools (Dashdot, Heimdall, Homarr)

Prerequisites

  • Basic familiarity with Docker and docker-compose
  • Comfortable reading and writing YAML

Project Background

What It Is

Homepage positions itself as a configuration-driven self-hosted service dashboard. It isn't a drag-and-drop visual editor — you describe your service layout and integrations precisely through YAML files. This design decision pays off in two concrete ways: your config can live in version control, and it can be reused across multiple machines without any re-clicking.

All API requests are proxied through the backend. The browser never sees your API keys — which addresses a real security problem common in similar tools.

Author / Team

  • Primary maintainer: @shamoon
  • Contributors: 200+
  • License: GPL-3.0

Project Stats

  • ⭐ GitHub Stars: 32,600+
  • 🍴 Forks: 2,100+
  • 📄 License: GPL-3.0
  • 💻 Stack: Next.js (React) + YAML config
  • 🌐 Website: gethomepage.dev
  • 🐳 Image: ghcr.io/gethomepage/homepage:latest

What It Does

The Problem It Solves

Self-hosting without a dashboard:
  Jellyfin   → http://192.168.1.100:8096
  Nextcloud  → http://192.168.1.100:8080
  Sonarr     → http://192.168.1.100:8989
  Portainer  → http://192.168.1.100:9000
  Grafana    → http://192.168.1.100:3000
  … (and ten more)

Problems:
  - IP + port combos live in your memory or bookmarks
  - A service goes down and you don't notice until you need it
  - How many things are in the media library? What's in the download queue?
    You have to navigate in to find out.

With Homepage:
  One page → entry points to all your services
  Service cards → live status (online / offline / response time)
  Widgets → key metrics right on the card (episode count, currently playing, disk usage…)
Enter fullscreen mode Exit fullscreen mode

Use Cases

  1. Home server / NAS management panel

    • Everything in one place; a single entry point for all devices on your local network
  2. Media center dashboard

    • What's playing in Jellyfin/Plex, Sonarr/Radarr download queue status, disk usage — at a glance
  3. Network and security monitoring

    • AdGuard Home block statistics, Uptime Kuma availability, Traefik routing status — live
  4. Internal team tool navigation

    • A shared entry page for a small team's internal services, replacing hand-maintained bookmarks
  5. VPS multi-service management

    • Manage all services on a VPS from one page, safely accessible externally behind a reverse proxy

Quick Start

The minimal docker-compose deployment:

services:
  homepage:
    image: ghcr.io/gethomepage/homepage:latest
    container_name: homepage
    ports:
      - 3000:3000
    volumes:
      - ./config:/app/config          # YAML config directory
      - /var/run/docker.sock:/var/run/docker.sock:ro  # Docker auto-discovery (optional)
    environment:
      HOMEPAGE_ALLOWED_HOSTS: your-domain.dev  # or LAN IP
    restart: unless-stopped
Enter fullscreen mode Exit fullscreen mode

After launch, visit http://localhost:3000 and edit the YAML files in ./config/ to configure your services.

Core Features

1. Four YAML Configuration Files

File Purpose
services.yaml Define service groups and service cards
widgets.yaml Top-of-page info widgets (clock, weather, search bar, etc.)
bookmarks.yaml Quick-access link groups
settings.yaml Global settings (title, theme, layout, language, etc.)

2. 150+ Service Widget Integrations

Each service card can embed a widget that pulls live data directly from the corresponding service's API:

Category Representative Services
Media management Sonarr, Radarr, Lidarr, Readarr, Bazarr
Media servers Jellyfin, Plex, Emby, Navidrome
Download clients qBittorrent, Transmission, Deluge, SABnzbd, NZBGet
Network tools AdGuard Home, Pi-hole, Traefik, Nginx Proxy Manager
Monitoring Uptime Kuma, Grafana, Prometheus, Netdata, Glances
Storage / cloud TrueNAS, Nextcloud, Portainer
System info CPU, memory, disk, network usage (built-in)

3. Docker Label Auto-Discovery

With the Docker socket mounted, just add homepage.* labels to any container and it appears in the dashboard automatically — no services.yaml edits needed:

# Add these labels to any other container's docker-compose
services:
  sonarr:
    image: linuxserver/sonarr
    labels:
      homepage.group: Media
      homepage.name: Sonarr
      homepage.icon: sonarr.png
      homepage.href: http://sonarr:8989/
      homepage.description: Series management
      homepage.widget.type: sonarr
      homepage.widget.url: http://sonarr:8989
      homepage.widget.key: your-api-key
Enter fullscreen mode Exit fullscreen mode

4. Secure Secret Management

API keys don't live in YAML — they're injected via environment variables:

# services.yaml uses a placeholder
widget:
  type: sonarr
  url: http://sonarr:8989
  key: {{HOMEPAGE_VAR_SONARR_KEY}}   # placeholder

# docker-compose.yml injects the real value
environment:
  HOMEPAGE_VAR_SONARR_KEY: your-actual-api-key
Enter fullscreen mode Exit fullscreen mode

The config files are safe to commit to Git.

5. Multi-Platform and Localization

  • AMD64 and ARM64 support (covers Raspberry Pi and similar ARM devices)
  • 40+ languages
  • Light / dark theme switching

A Deeper Look

The Configuration System in Practice

A typical services.yaml looks like this:

- Media:
    - Jellyfin:
        icon: jellyfin.png
        href: http://jellyfin:8096/
        description: Media server
        siteMonitor: http://jellyfin:8096/
        widget:
          type: jellyfin
          url: http://jellyfin:8096
          key: {{HOMEPAGE_VAR_JELLYFIN_KEY}}
          fields: ["movies", "series", "episodes"]

    - Sonarr:
        icon: sonarr.png
        href: http://sonarr:8989/
        description: Series management
        widget:
          type: sonarr
          url: http://sonarr:8989
          key: {{HOMEPAGE_VAR_SONARR_KEY}}
          fields: ["wanted", "queued", "series"]

- Network:
    - AdGuard Home:
        icon: adguard-home.png
        href: http://adguard:80/
        widget:
          type: adguard
          url: http://adguard:80
          username: admin
          password: {{HOMEPAGE_VAR_ADGUARD_PASS}}
          fields: ["queries", "blocked", "filtered"]
Enter fullscreen mode Exit fullscreen mode

The siteMonitor field sends periodic HTTP HEAD requests and displays online status with response time on the card — no API integration required, so any HTTP service can be monitored.

Why Next.js Static Generation

Homepage uses Next.js with an unusual rendering strategy:

Most dashboard tools:
  Browser requests page → server renders dynamically each time → returns HTML
  ↑ Every load has latency

Homepage:
  Build time: static HTML/CSS/JS generated → served directly as static files
  Widget data: separate API routes fetch in real time
  ↑ Page shell loads instantly; widget data fills in asynchronously
Enter fullscreen mode Exit fullscreen mode

The practical effect: the page is essentially instant. Widgets populate asynchronously afterward, so one slow service doesn't block the whole page from loading.

Docker Socket Security Considerations

Mounting /var/run/docker.sock enables container auto-discovery, but it grants full Docker daemon access — a security surface worth thinking about.

Common mitigations:

# Option 1: Read-only mount (Homepage only needs read access)
volumes:
  - /var/run/docker.sock:/var/run/docker.sock:ro

# Option 2: Docker Socket Proxy (recommended for security-sensitive setups)
# Insert a proxy between Homepage and the socket, exposing only read-only APIs
services:
  socket-proxy:
    image: tecnativa/docker-socket-proxy
    environment:
      CONTAINERS: 1   # allow reading container info only
      POST: 0         # block all write operations
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro

  homepage:
    environment:
      # connect to the proxy instead of the socket directly
      HOMEPAGE_DOCKER_HOST: socket-proxy
      HOMEPAGE_DOCKER_PORT: 2375
Enter fullscreen mode Exit fullscreen mode

Option 2 is the right choice in security-conscious environments.

Comparison with Similar Tools

Dimension Homepage Homarr Heimdall Dashdot
Configuration YAML files GUI drag-and-drop GUI YAML
Docker auto-discovery ✅ Labels
Service widget count 150+ 50+ Few Few
API proxy (key security) ✅ Backend proxy Partial
Static generation
Version-controllable config ✅ Natural ❌ DB-stored ❌ DB-stored
Stars 32.6k 7k+ 6k+ 3k+

Homepage's edge: the most widgets + YAML configs that belong in version control + backend proxy for key protection. The trade-off is a slightly higher floor for getting started compared to drag-and-drop tools.


Project Links and Resources

Official Resources

Related Resources

  • awesome-selfhosted — The definitive self-hosted software list, for finding more services to put in your dashboard
  • Uptime Kuma — A self-hosted monitoring tool that integrates exceptionally well with Homepage
  • tecnativa/docker-socket-proxy — Recommended Docker socket security proxy to pair with Homepage

Summary

Key Takeaways

  1. YAML as the center of gravity: services, widgets, bookmarks, settings — four files, config as documentation, Git version control out of the box
  2. Docker Label auto-discovery: new container + homepage.* labels = it appears in the dashboard, no manual maintenance needed
  3. 150+ Service Widgets: from the *arr stack to AdGuard Home, API data surfaces directly on each card
  4. Backend proxy protects secrets: API keys never reach the browser; environment variable injection lets config be committed safely
  5. Static generation architecture: page shell loads instantly, widget data fills asynchronously — a slow service doesn't drag down the rest

Who This Is For

  • Home server / NAS enthusiasts: running a pile of self-hosted services and wanting one unified front door
  • Config-as-code people: prefer precise YAML control over drag-and-drop, and want configs in version control
  • Security-minded self-hosters: not willing to expose API keys to the browser
  • **arr media stack users*: Sonarr + Radarr + Jellyfin all-in — Homepage has the most comprehensive widget coverage for this setup

One-Line Verdict

Homepage does one small, sharp thing: it takes your services scattered across a dozen ports and unifies them with one YAML file and one elegant page.


Check out PrimeSkills — a curated marketplace of AI agents and skills that have been validated in real-world, enterprise-grade workflows. No fluff, just what actually works.

Find more useful knowledge and interesting products on my Homepage

Top comments (0)