MAATRIX / Блог / Homepage в Docker Compose: готовый файл

Homepage в Docker Compose: готовый файл

MAATRIX

Когда на сервере крутится десяток сервисов, каждый на своём порту или поддомене, открывать их через закладки в браузере быстро надоедает — адреса путаются, часть ссылок протухает после переезда контейнера на другой порт. Homepage закрывает эту проблему одним экраном: карточки всех сервисов с живыми виджетами (загрузка CPU, статус в Uptime Kuma, количество задач в *arr-стеке) и поиском по ним же. Ниже — рабочий docker-compose.yml и минимальный набор YAML-конфигов, с которых можно стартовать за 10 минут.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Что такое Homepage и чем он отличается от аналогов

Homepage (проект gethomepage/homepage, ранее известный как homepage от benphelps) — стартовая страница для домашнего или личного сервера, написанная на Next.js. В отличие от простых линкоделок вроде Heimdall или Dashy, у неё есть:

  • виджеты интеграций — больше сотни готовых коннекторов: Docker, Portainer, Uptime Kuma, Pi-hole, Sonarr/Radarr, Proxmox, Grafana, Adguard Home и другие, каждый показывает живые данные прямо на карточке;
  • автообнаружение контейнеров через Docker-лейблы — не нужно вручную вписывать каждый сервис в конфиг, если он уже размечен;
  • конфигурация как код — всё в YAML-файлах, которые удобно хранить в git и переносить между серверами;
  • виджеты информации о системе — загрузка CPU/RAM/диска, погода, календарь, RSS-лента — без сторонних панелей.

Из минусов честно: интерфейс — read-only дашборд, а не панель управления (в отличие от Portainer, где можно рестартовать контейнер). Это осознанный компромисс — Homepage не лезет в зону ответственности Portainer или Traefik, а просто агрегирует то, что они показывают.

Тем, кто уже привык управлять контейнерами через Portainer, Homepage не конкурент, а надстройка сверху — она не трогает жизненный цикл контейнеров, только читает их статус.

Готовый docker-compose.yml

Минимальная и при этом рабочая конфигурация. Каталог homepage-config монтируется внутрь контейнера — все YAML-файлы конфигурации будут лежать на хосте и переживут пересоздание контейнера:

services:
  homepage:
    image: ghcr.io/gethomepage/homepage:v1.4.0
    container_name: homepage
    restart: unless-stopped
    ports:
      - "3000:3000"
    volumes:
      - ./homepage-config:/app/config
      - /var/run/docker.sock:/var/run/docker.sock:ro
    environment:
      - HOMEPAGE_ALLOWED_HOSTS=dashboard.example.com,203.0.113.10:3000
    networks:
      - homepage-net

networks:
  homepage-net:
    driver: bridge

Пара нюансов, на которых легко споткнуться:

  • HOMEPAGE_ALLOWED_HOSTS обязателен начиная с версии 0.8+ — без него дашборд отдаёт 500-ю ошибку при обращении не с localhost. Перечислите через запятую все домены и IP:порт, с которых будете открывать интерфейс.
  • Монтирование docker.sock даёт контейнеру доступ к Docker API хоста — нужно для автообнаружения и виджета статистики контейнеров. Это осознанное снижение изоляции: в теории компрометация Homepage даёт контроль над Docker-демоном. Для личного сервера с доверенным окружением риск обычно приемлем, но держите образ обновлённым и не открывайте порт 3000 в интернет напрямую.
  • Версию образа лучше пинить (v1.4.0), а не брать :latest — мажорные обновления Homepage иногда меняют формат конфигов, и молчаливый апгрейд среди ночи по watchtower может сломать дашборд.

Поднимаем:

mkdir -p homepage-config
docker compose up -d

При первом запуске Homepage сам создаст в homepage-config дефолтные YAML-файлы, если их там нет — их и будем редактировать дальше.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Конфигурация: services.yaml, settings.yaml, bookmarks.yaml

Все настройки живут в отдельных YAML-файлах внутри homepage-config. Разберём три ключевых.

settings.yaml — общий вид дашборда:

title: Домашний сервер
favicon: https://example.com/favicon.ico
theme: dark
color: slate
layout:
  Инфраструктура:
    style: row
    columns: 3
  Медиа:
    style: row
    columns: 4
providers:
  openweathermap: your-api-key-here

services.yaml — карточки сервисов, сгруппированные по секциям (секции должны совпадать с ключами в layout из settings.yaml):

- Инфраструктура:
    - Portainer:
        href: https://portainer.example.com
        description: Управление контейнерами
        icon: portainer.png
        widget:
          type: portainer
          url: http://portainer:9000
          env: 1
          key: ptr_your-api-key

    - Traefik:
        href: https://traefik.example.com
        description: Reverse proxy
        icon: traefik.png
        widget:
          type: traefik
          url: http://traefik:8080

- Медиа:
    - Jellyfin:
        href: https://jellyfin.example.com
        description: Медиасервер
        icon: jellyfin.png

bookmarks.yaml — обычные ссылки без виджетов, для сервисов, которые не нужно мониторить:

- Разработка:
    - GitHub:
        - abbr: GH
          href: https://github.com

    - Документация проекта:
        - abbr: WIKI
          href: https://wiki.example.com

Все три файла Homepage перечитывает на лету при обращении к странице — перезапускать контейнер после правки не нужно, достаточно обновить вкладку в браузере.

Виджеты для мониторинга сервисов

Главная сила Homepage — виджеты, которые тянут живые данные из других сервисов и показывают их прямо на карточке, без перехода на отдельную страницу. Несколько практичных примеров.

Виджет Uptime Kuma показывает статус конкретного монитора:

widget:
  type: uptimekuma
  url: http://uptime-kuma:3001
  slug: my-website-monitor

Виджет Pi-hole выводит число заблокированных запросов за сутки:

widget:
  type: pihole
  url: http://pihole:80
  key: your-pihole-api-token

Встроенный системный виджет resources (без обращения к внешнему сервису) выводит загрузку CPU, память и диски прямо хоста, где крутится сам контейнер Homepage:

- resources:
    cpu: true
    memory: true
    disk: /

Полный список поддерживаемых виджетов (их больше сотни) — в официальной документации проекта; конфигурация каждого сводится к url сервиса и, если нужно, API-ключу или токену. Общий принцип везде один: указать адрес сервиса внутри Docker-сети (по имени контейнера, не через localhost) и учётные данные для API, если сервис их требует.

Автообнаружение контейнеров через Docker-лейблы

Вписывать вручную каждый сервис в services.yaml неудобно, если контейнеров много и они часто меняются. Homepage умеет читать лейблы прямо из Docker и строить карточки сам — для этого достаточно добавить лейблы в docker-compose.yml нужного сервиса:

services:
  jellyfin:
    image: jellyfin/jellyfin
    container_name: jellyfin
    labels:
      homepage.group: Медиа
      homepage.name: Jellyfin
      homepage.icon: jellyfin.png
      homepage.href: https://jellyfin.example.com
      homepage.description: Медиасервер
      homepage.widget.type: jellyfin
      homepage.widget.url: http://jellyfin:8096
      homepage.widget.key: your-api-key

Чтобы Homepage начал читать лейблы, включите провайдер в settings.yaml:

providers:
  docker:
    my-docker:
      socket: /var/run/docker.sock

и сошлитесь на него в services.yaml, если хотите смешивать ручные записи с автообнаружением:

- Медиа:
    - my-docker: null

Подход особенно удобен, когда сервисы разворачиваются через отдельные docker-compose.yml в разных каталогах — карточка в дашборде появляется автоматически, конфигурацию не нужно синхронизировать вручную между двумя местами.

Публикация через reverse proxy и ограничение доступа

Открывать порт 3000 напрямую в интернет — плохая идея: дашборд агрегирует ссылки и статусы всей инфраструктуры, по сути это карта сервера для потенциального атакующего. Правильный путь — спрятать Homepage за reverse proxy с HTTPS и базовой аутентификацией.

Если Traefik уже настроен как reverse proxy для остальных сервисов, добавьте лейблы прямо в сервис Homepage:

services:
  homepage:
    image: ghcr.io/gethomepage/homepage:v1.4.0
    container_name: homepage
    restart: unless-stopped
    volumes:
      - ./homepage-config:/app/config
      - /var/run/docker.sock:/var/run/docker.sock:ro
    environment:
      - HOMEPAGE_ALLOWED_HOSTS=dashboard.example.com
    networks:
      - homepage-net
      - traefik-net
    labels:
      traefik.enable: "true"
      traefik.http.routers.homepage.rule: Host(`dashboard.example.com`)
      traefik.http.routers.homepage.entrypoints: websecure
      traefik.http.routers.homepage.tls.certresolver: letsencrypt
      traefik.http.services.homepage.loadbalancer.server.port: "3000"

networks:
  homepage-net:
  traefik-net:
    external: true

Если Traefik разбирается на своём сервере впервые, до подключения дашборда логично сначала поднять и проверить сам reverse proxy на одном тестовом сервисе, а Homepage добавить последним, когда сертификаты и роутинг уже работают.

Второй слой защиты — Basic Auth или Authelia перед дашбордом, поскольку сам Homepage не имеет встроенной аутентификации. Для Traefik это лейбл вида:

labels:
  traefik.http.routers.homepage.middlewares: homepage-auth
  traefik.http.middlewares.homepage-auth.basicauth.users: "admin:$$apr1$$xyz...hash"

Хеш пароля генерируется через htpasswd -nB admin — команда выведет строку вида admin:$apr1$..., в лейбле Compose доллары нужно удвоить ($$$), иначе Docker Compose попытается интерпретировать их как переменные окружения.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Можно ли редактировать конфиг через веб-интерфейс?

Нет, Homepage — не CMS и не панель управления. Все настройки только через YAML-файлы на диске; интерфейс их лишь отображает и перечитывает при каждом обращении к странице.

Почему виджет показывает ошибку подключения, хотя сервис явно работает?

Чаще всего дело в адресе — внутри Docker-сети нужно обращаться к сервису по имени контейнера (http://portainer:9000), а не по localhost или внешнему домену. Второй частый случай — оба контейнера не в одной Docker-сети.

Нужен ли Homepage доступ к docker.sock, если автообнаружение не используется?

Нет, если вы не подключаете провайдер docker в settings.yaml и не используете виджет docker для статистики контейнеров — можно убрать монтирование сокета вовсе и снизить поверхность атаки.

Как перенести Homepage на другой сервер?

Достаточно скопировать каталог homepage-config целиком — вся конфигурация в текстовых YAML-файлах, база данных не используется.

Чем Homepage отличается от Heimdall и Dashy?

Heimdall — простой каталог ссылок без живых виджетов интеграций. Dashy ближе по функциям, но конфиг у него объёмнее и интерфейс тяжелее; Homepage выигрывает за счёт скорости на Next.js и большого числа готовых коннекторов «из коробки».

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →