Homer Dashboard Installation and Configuration

Homer is a dead-simple static server dashboard that displays all your self-hosted services in a clean, organized homepage configured entirely through a single YAML file. With no database, no backend, and minimal resource usage, Homer is ideal for VPS environments where you want a visual overview of your services without adding operational overhead.

Prerequisites

  • Docker and Docker Compose installed (or any web server for static files)
  • Root or sudo access
  • Basic YAML syntax knowledge
  • Services already running that you want to link

Installing Homer with Docker

# Create Homer directory
sudo mkdir -p /opt/homer/assets/icons

# Create docker-compose.yml
sudo tee /opt/homer/docker-compose.yml <<'EOF'
version: '3.8'

services:
  homer:
    image: b4bz/homer:latest
    restart: unless-stopped
    ports:
      - "8080:8080"
    volumes:
      - /opt/homer/assets:/www/assets
    environment:
      - INIT_ASSETS=1    # Copy example assets on first run
    user: "1000:1000"
EOF

# Start Homer
cd /opt/homer
sudo docker compose up -d

# Monitor startup
sudo docker compose logs homer

Access Homer at http://your-server:8080

On first run with INIT_ASSETS=1, Homer copies example assets including a sample config.yml to the assets directory.

Alternative: run without Docker using Nginx:

# Download Homer
curl -LO https://github.com/bastienwirtz/homer/releases/latest/download/homer.zip
sudo unzip homer.zip -d /var/www/homer/

# Configure Nginx to serve the static files
sudo tee /etc/nginx/sites-available/homer <<'EOF'
server {
    listen 8080;
    root /var/www/homer;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }
}
EOF

sudo ln -s /etc/nginx/sites-available/homer /etc/nginx/sites-enabled/
sudo systemctl reload nginx

YAML Configuration Basics

The entire Homer configuration lives in /opt/homer/assets/config.yml:

# Edit the configuration file
sudo nano /opt/homer/assets/config.yml

Minimal config.yml:

# config.yml
title: "My Server Dashboard"
subtitle: "VPS Services"
logo: "assets/logo.png"

header: true
footer: '<p>My VPS - <a href="https://my-provider.com">Provider</a></p>'

# Optional: theme (default, dark)
theme: default

# Optional: color palette override
colors:
  light:
    highlight-primary: "#3367d6"
    highlight-secondary: "#4285f4"
    highlight-hover: "#5a95f5"
    background: "#f5f5f5"
    card-background: "#ffffff"
    text: "#363636"
    text-header: "#ffffff"
    text-title: "#303030"
    text-subtitle: "#424242"
    card-shadow: rgba(0, 0, 0, 0.1)
    link: "#3273dc"
    link-hover: "#363636"

  dark:
    highlight-primary: "#3367d6"
    highlight-secondary: "#4285f4"
    highlight-hover: "#5a95f5"
    background: "#131313"
    card-background: "#2b2b2b"
    text: "#eaeaea"
    text-header: "#ffffff"
    text-title: "#fafafa"
    text-subtitle: "#f5f5f5"
    card-shadow: rgba(0, 0, 0, 0.4)
    link: "#3273dc"
    link-hover: "#ffdd57"

Service Grouping

Organize services into logical groups:

# config.yml - services section
services:
  - name: "Monitoring"
    icon: "fas fa-heartbeat"
    items:
      - name: "Grafana"
        logo: "assets/icons/grafana.png"
        subtitle: "Metrics and dashboards"
        tag: "monitoring"
        url: "https://grafana.example.com"
        target: "_blank"
      - name: "Prometheus"
        logo: "assets/icons/prometheus.png"
        subtitle: "Metrics collection"
        tag: "monitoring"
        url: "https://prometheus.example.com"

  - name: "Media"
    icon: "fas fa-film"
    items:
      - name: "Jellyfin"
        logo: "assets/icons/jellyfin.png"
        subtitle: "Media streaming"
        tag: "media"
        keywords: "video music"
        url: "https://jellyfin.example.com"
      - name: "Navidrome"
        logo: "assets/icons/navidrome.png"
        subtitle: "Music server"
        tag: "media"
        url: "https://music.example.com"

  - name: "Storage & Files"
    icon: "fas fa-hdd"
    items:
      - name: "Nextcloud"
        logo: "assets/icons/nextcloud.png"
        subtitle: "File sync and share"
        tag: "storage"
        url: "https://cloud.example.com"
      - name: "Seafile"
        logo: "assets/icons/seafile.png"
        subtitle: "Fast file sync"
        tag: "storage"
        url: "https://seafile.example.com"

  - name: "DevOps"
    icon: "fas fa-code"
    items:
      - name: "Gitea"
        logo: "assets/icons/gitea.png"
        subtitle: "Git hosting"
        tag: "dev"
        url: "https://git.example.com"
      - name: "Portainer"
        logo: "assets/icons/portainer.png"
        subtitle: "Docker management"
        tag: "infra"
        url: "https://portainer.example.com"

Custom Icons

Use Font Awesome icons (included):

# Use any Font Awesome 5 Free icon
items:
  - name: "My Service"
    icon: "fas fa-server"      # solid icons
  - name: "Another Service"
    icon: "far fa-file"        # regular icons
  - name: "Github"
    icon: "fab fa-github"      # brand icons

Use custom PNG/SVG icons:

# Place icons in the icons directory
sudo cp myservice.png /opt/homer/assets/icons/

# Reference in config.yml
# logo: "assets/icons/myservice.png"

Download a curated icon pack:

# Download Dashboard Icons (popular icon collection for home labs)
cd /opt/homer/assets/icons

# Download specific icons
curl -LO https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/grafana.png
curl -LO https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/jellyfin.png
curl -LO https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/portainer.png
curl -LO https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/nextcloud.png

Health Checks

Homer supports API-based health checks for services that implement a status endpoint:

# Enable status check for a service
items:
  - name: "Grafana"
    url: "https://grafana.example.com"
    type: "Ping"    # Simple HTTP check

  - name: "Gitea"
    url: "https://git.example.com"
    type: "Gitea"   # Built-in Gitea integration

  - name: "Jellyfin"
    url: "https://jellyfin.example.com"
    type: "Emby"    # Jellyfin uses Emby-compatible API
    apikey: "your-jellyfin-api-key"

  - name: "Sonarr"
    url: "https://sonarr.example.com"
    type: "Sonarr"
    apikey: "your-sonarr-api-key"

Custom status check with Ping type:

# Ping type checks if the URL returns a 2xx status
# The status dot shows green (online) or red (offline)
- name: "My API"
  url: "https://api.example.com/health"
  type: "Ping"

Theme Customization

Apply a dark theme:

# In config.yml
theme: default   # or: default, dark

# Optional: user can toggle in the UI, or force with:
# defaults:
#   colorTheme: dark

Custom CSS in assets:

# Create a custom.css file
sudo tee /opt/homer/assets/custom.css <<'EOF'
/* Change font */
body {
  font-family: "Inter", sans-serif;
}

/* Make cards slightly larger */
.card {
  min-height: 70px;
}

/* Custom card hover effect */
.card:hover {
  transform: translateY(-2px);
  transition: transform 0.2s ease;
}
EOF
# Reference in config.yml
stylesheet:
  - "assets/custom.css"

Reverse Proxy with Nginx

# /etc/nginx/sites-available/homer
server {
    listen 80;
    server_name home.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name home.example.com;

    ssl_certificate /etc/letsencrypt/live/home.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/home.example.com/privkey.pem;

    # Optional: restrict to specific IPs
    # allow 1.2.3.4;
    # deny all;

    # Optional: basic auth
    # auth_basic "Dashboard";
    # auth_basic_user_file /etc/nginx/.htpasswd;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}
sudo ln -s /etc/nginx/sites-available/homer /etc/nginx/sites-enabled/
sudo certbot --nginx -d home.example.com
sudo systemctl reload nginx

Troubleshooting

Dashboard not loading after config change:

# Homer hot-reloads config automatically in the browser
# If the page breaks, check YAML syntax
# YAML linter:
python3 -c "import yaml; yaml.safe_load(open('/opt/homer/assets/config.yml'))"

# View Homer container logs for errors
sudo docker compose logs homer

# Check file permissions
ls -la /opt/homer/assets/config.yml
sudo chown 1000:1000 /opt/homer/assets/config.yml

Icons not showing:

# Verify files exist and are readable
ls -la /opt/homer/assets/icons/

# Check the path in config.yml matches exactly
# logo: "assets/icons/filename.png"  (not absolute path)

# Test direct access to the icon
curl -I http://your-server:8080/assets/icons/grafana.png

Health checks not working:

# Ensure the service URL is accessible from the Homer container
sudo docker compose exec homer wget -q -O - http://grafana:3000/api/health

# For external services, ensure the Homer container has internet access
sudo docker compose exec homer wget -q -O - https://grafana.example.com

Conclusion

Homer provides the simplest possible server dashboard — a single YAML file that renders a fast, searchable service directory without databases, authentication overhead, or complex configuration. By combining Font Awesome icons, custom PNG logos, and API-based health checks, you get an informative at-a-glance view of your entire self-hosted infrastructure that loads instantly and requires virtually no maintenance.