MAATRIX / Блог / Dashy на сервере: частые ошибки и решения

Dashy на сервере: частые ошибки и решения

MAATRIX

Dashy — один из самых функциональных self-hosted дашбордов: секции с иконками, статус-мониторинг подключённых сервисов, виджеты погоды, курсов и системных метрик, поиск по всем сервисам с клавиатуры. Но именно из-за этой функциональности новички чаще всего спотыкаются на одном из трёх мест: контейнер не стартует, конфиг не читается или статусы сервисов упорно горят красным, даже когда сами сервисы работают. Разберём типичные ошибки по порядку — от установки до бэкапа конфигурации.

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

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

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

Установка Dashy в Docker Compose: типичные ошибки старта

Дашборд официально распространяется как Docker-образ lissy93/dashy, и почти все проблемы начинаются на этом шаге. Рабочий минимальный docker-compose.yml:

version: "3.8"
services:
  dashy:
    image: lissy93/dashy:latest
    container_name: dashy
    restart: unless-stopped
    volumes:
      - ./conf.yml:/app/public/conf.yml
    ports:
      - "4000:8080"
    environment:
      - NODE_ENV=production
    healthcheck:
      test: ["CMD", "node", "/app/services/healthcheck"]
      interval: 1m30s
      timeout: 10s
      retries: 3
      start_period: 40s

Частые ошибки на этом этапе:

  • Контейнер стартует и сразу падает (Restarting). Почти всегда причина — смонтированный conf.yml, который на хосте ещё не существует или является директорией. Docker при отсутствии файла молча создаёт на его месте папку, и контейнер не может открыть конфиг как файл. Создайте пустой conf.yml на хосте до первого docker compose up, даже если это просто заглушка с минимальным содержимым.
  • Порт 8080 занят другим сервисом. Внутри контейнера Dashy слушает 8080 — меняется только внешний порт в ports. Если на сервере уже висит что-то на 4000, смените маппинг, например на 4001:8080, и не трогайте правую часть.
  • unhealthy в docker ps, хотя сайт открывается. Healthcheck использует внутренний скрипт node /app/services/healthcheck, который иногда не успевает пройти за start_period на слабых VPS при первом старте. Увеличьте start_period до 90s — не убирайте healthcheck совсем, он полезен для авторестарта при зависании.
  • Ошибка permission denied при монтировании конфига. На хостах с SELinux или при запуске Docker от непривилегированного пользователя том может монтироваться read-only. Проверьте владельца файла (ls -l conf.yml) и права: chmod 644 conf.yml обычно достаточно, поднимать 777 не нужно.

Если это ваш первый сервис в Docker Compose на сервере вообще, до Dashy стоит один раз наладить сам стек — база для многих подобных проблем разобрана в статье про частые ошибки Docker Compose в проде.

Ошибки в conf.yml: синтаксис, схема, пустой экран

Вся конфигурация Dashy живёт в одном YAML-файле, и это одновременно удобно и опасно: одна лишняя пробельная позиция — и дашборд либо не поднимается, либо открывается пустым белым экраном без единой ошибки на странице.

Типичная структура:

pageInfo:
  title: Мой сервер
  description: Панель управления сервисами

appConfig:
  theme: colorful
  layout: auto
  iconSize: medium
  language: ru

sections:
  - name: Инфраструктура
    icon: fas fa-server
    items:
      - title: Portainer
        description: Управление контейнерами
        icon: hl-portainer
        url: https://portainer.example.com
        statusCheck: true

Куда чаще всего утыкаются:

  • YAML чувствителен к отступам, а не к количеству пробелов само по себе. Смешивание табов и пробелов — гарантированный краш парсера. Проверяйте конфиг перед перезапуском: python3 -c "import yaml; yaml.safe_load(open('conf.yml'))" либо yamllint conf.yml, если он установлен — это быстрее, чем гадать по логам контейнера.
  • Дублирующиеся ключи или отсутствие обязательных полей. У каждого пункта в items обязателен title, у sectionsname. Их отсутствие Dashy иногда проглатывает молча, просто не рисуя блок.
  • Белый экран после правки конфига без ошибок в консоли браузера. Проверьте логи контейнера: docker logs dashy --tail 50. Если там тишина — откройте DevTools → Network и посмотрите, отдаётся ли /conf.yml (код 200) и валиден ли он после конвертации в JSON на лету.
  • Кириллица ломает файл при редактировании в Windows-редакторах. Сохраняйте conf.yml строго в UTF-8 без BOM — некоторые редакторы по умолчанию добавляют BOM-маркер, который YAML-парсер интерпретирует как мусорный символ перед pageInfo:.
  • Правки не применяются после перезапуска. Если конфиг редактируется через встроенный визуальный редактор в интерфейсе Dashy, а не напрямую в файле — изменения могут сохраняться в другую копию внутри контейнера и теряться при пересоздании. Надёжнее редактировать conf.yml на хосте и делать docker compose restart dashy.

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

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

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

Статус-чекер сервисов не работает: красные точки при живых сервисах

Это самая частая жалоба на Dashy — статус-мониторинг (statusCheck: true) показывает офлайн для сервисов, которые прекрасно открываются в браузере. Причина почти всегда одна: по умолчанию проверка статуса выполняется из браузера пользователя, а не с сервера, где крутится сам Dashy.

Из этого вытекают конкретные симптомы и решения:

  • CORS-блокировка. Браузер стучится напрямую на statusCheckUrl целевого сервиса, и если тот не отдаёт заголовок Access-Control-Allow-Origin, запрос падает с ошибкой, а Dashy рисует красный индикатор. Проверяется в DevTools → Console по строке CORS policy. Решение — либо добавить permissive CORS-заголовок на целевом сервисе (не всегда безопасно), либо указать statusCheckUrl на эндпоинт, который CORS не режет, например /health за тем же прокси, что и сам Dashy.
  • Смешанный контент HTTP/HTTPS. Если Dashy открыт по HTTPS, а statusCheckUrl указывает на http://, браузер молча блокирует запрос как небезопасный. Приводите все проверяемые URL к HTTPS.
  • Внутренние адреса недоступны из браузера клиента. Если вы заходите на Dashy из дома, а statusCheckUrl указывает на внутренний IP сервера или имя контейнера в docker-сети (http://portainer:9000) — это резолвится только внутри серверной сети, но не с вашего ноутбука. Указывайте публично резолвящийся адрес.
  • Таймаут на медленных сервисах. Сервисы с долгим холодным стартом не успевают ответить за отведённое время. Увеличьте statusCheckInterval на уровне appConfig и не завязывайтесь на статус-чек как на единственный сигнал доступности.

Если вам нужен именно надёжный внешний мониторинг аптайма, а не декоративные индикаторы в дашборде, разумнее держать Dashy как витрину, а реальный алертинг вынести в отдельный сервис — например, Uptime Kuma с разбором частых ошибок настройки, и уже его публичный статус-виджет встраивать в Dashy как ссылку, а не полагаться на клиентский statusCheck.

Виджеты (погода, курсы, системные метрики) не показывают данные

Отдельный класс проблем — не иконки-ссылки, а активные виджеты (type: weather, type: crypto-price, type: cpu и т.д.), которые в списке widgets внутри секции тянут данные из внешних API или с самого хоста.

  • Виджет висит с крутящимся лоадером бесконечно. В большинстве случаев не указан или неверный API-ключ там, где он обязателен (погода, некоторые крипто-виджеты). Ключ прописывается прямо в conf.yml в параметрах виджета — если тариф API ограничивает частоту запросов, не ставьте интервал обновления слишком коротким, иначе получите блокировку по rate limit (в консоли браузера это видно как HTTP 429).
  • Системные виджеты (CPU, RAM, диск) показывают данные контейнера, а не хоста. Это ожидаемое поведение, если контейнеру не даны нужные mount-точки и права на чтение /proc и /sys с хоста. Если системные метрики сервера критичны — отдельный exporter с прямым доступом к хосту надёжнее, чем виджет внутри дашборда.
  • Иконки сервисов не грузятся (битые картинки вместо логотипов). Dashy поддерживает несколько источников иконок: favicon, встроенный набор hl- (homelab icons), классы Font Awesome (fas fa-...), либо прямой URL на картинку. Если используете favicon, а сервис не отдаёт favicon.ico по стандартному пути — иконка не подтянется. Надёжнее явно указывать icon: https://.../logo.png или брать иконку из встроенного набора, а не полагаться на автодетект.

Dashy за reverse proxy: доступ по домену и HTTPS

Открывать дашборд по IP:порт для постоянного использования неудобно и небезопасно — тем более что сам Dashy видит все ваши внутренние сервисы разом. Стандартная связка — Traefik или Caddy перед контейнером Dashy.

Пример для Traefik (метки в docker-compose):

    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.dashy.rule=Host(`dash.example.com`)"
      - "traefik.http.routers.dashy.entrypoints=websecure"
      - "traefik.http.routers.dashy.tls.certresolver=letsencrypt"
      - "traefik.http.services.dashy.loadbalancer.server.port=8080"

Ключевые грабли:

  • ERR_TOO_MANY_REDIRECTS при открытии домена. Признак того, что и Traefik, и сам Dashy пытаются делать HTTPS-редирект одновременно, либо в переменной окружения BASE_URL контейнера прописан протокол, конфликтующий с тем, что видит прокси. Держите редиректы на стороне прокси, не задваивайте их.
  • Порт в label loadbalancer.server.port указан 4000 вместо 8080. Traefik обращается к контейнеру внутри docker-сети напрямую по внутреннему порту — это всегда 8080, независимо от того, что указано слева в ports для внешнего доступа. Если фронтом стоит Traefik в общей сети, секцию ports из compose-файла вообще можно убрать.
  • Сертификат не выпускается или Traefik ведёт себя странно — эти проблемы не специфичны для Dashy и разобраны отдельно, но применимы один в один: частые ошибки Let's Encrypt SSL и Traefik на сервере — частые ошибки и решения.

Аутентификация, права доступа и бэкап конфигурации

Dashy — это, по сути, карта всей вашей инфраструктуры в одном месте, поэтому оставлять его без защиты снаружи — плохая идея, даже если это "для себя".

  • Встроенная аутентификация через appConfig.auth.users. Пароли задаются как SHA-256 хеш, не в открытом виде:
appConfig:
  auth:
    users:
      - user: admin
        hash: "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d"

Хеш для пароля получить локально: echo -n "ваш_пароль" | sha256sum. Не храните в репозитории conf.yml с реальными хешами, если репозиторий публичный.

  • Встроенной аутентификации мало для боевого использования. Она защищает саму страницу, но не ограничивает частоту попыток входа и не ведёт журнал доступа. Для внешнего периметра разумнее добавить Basic Auth на уровне прокси вторым слоем, либо вообще спрятать дашборд за VPN и не публиковать его в открытый интернет — для внутренней панели это чаще всего правильный выбор.
  • Бэкап conf.yml — обязателен и тривиален. Вся конфигурация — один YAML-файл, поэтому простейший бэкап это версионирование в git (без секретов в открытом виде) или регулярная копия по крону: cp conf.yml conf.yml.bak-$(date +%F). Восстановление после сбоя сервера сводится к docker compose up -d с тем же файлом — никакой базы данных Dashy не хранит.
  • Обновление образа. docker compose pull && docker compose up -d обновляет контейнер до актуального тега. Перед крупным обновлением сверьтесь с changelog проекта — структура conf.yml между версиями менялась, часть старых полей могла быть переименована.

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

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

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

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

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

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

Почему Dashy не открывается после docker compose up, хотя контейнер в статусе Up?

Чаще всего порт проброшен неверно (перепутаны стороны в ports: "4000:8080") или прокси ссылается не на тот внутренний порт. Проверьте напрямую с сервера: curl -I http://localhost:4000.

Можно ли использовать Dashy без Docker?

Технически да, проект поддерживает сборку из исходников через yarn, но для продакшена Docker-образ проще в обслуживании — обновления и бэкап конфигурации через него надёжнее.

Статус-чекер показывает офлайн для сервиса на том же сервере — это нормально?

Нет, если сервис реально работает. В большинстве случаев причина в CORS (см. раздел выше).

Нужен ли Dashy отдельный домен или можно на поддиректории?

Лучше отдельный поддомен (dash.example.com). Поддиректория требует правки BASE_URL и путей к статике и на практике даёт лишние 404 на иконки и скрипты.

Что делать, если после обновления образа конфиг перестал парситься?

Откатите на предыдущий тег (image: lissy93/dashy:X.Y.Z вместо latest) и сравните changelog — обычно проблема в переименованном поле conf.yml. Держать latest в проде вообще рискованно для любого активно развивающегося self-hosted сервиса.

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

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

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