Umami на сервере: частые ошибки и решения
Umami обещает поднять self-hosted аналитику за пять минут в одном Docker-контейнере — и в целом это правда, стек здесь куда легче, чем у Plausible или Matomo. Но именно эта простота усыпляет бдительность: типовые ошибки прячутся не в архитектуре, а в мелочах — переменных окружения, миграциях базы и связке с реверс-прокси. Разберём их по порядку, с конкретными командами.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Архитектура self-hosted Umami и где чаще всего спотыкаются
В отличие от Plausible с его тройкой контейнеров, Umami — это одно Next.js-приложение плюс одна база данных (PostgreSQL или MySQL на выбор). Официальный образ docker.umami.is/umami-software/umami идёт в двух вариантах тега — postgresql-latest и mysql-latest — под соответствующую СУБД, и это первая точка, где путаются: тег образа должен совпадать с реальной базой, к которой вы подключаетесь, иначе Prisma-клиент внутри контейнера не сможет корректно работать со схемой.
Типовой docker-compose.yml выглядит так:
services:
umami:
image: docker.umami.is/umami-software/umami:postgresql-latest
ports:
- "3000:3000"
environment:
DATABASE_URL: postgresql://umami:umami_pass@db:5432/umami
DATABASE_TYPE: postgresql
APP_SECRET: замените-на-случайную-строку-32-байта
depends_on:
db:
condition: service_healthy
restart: always
db:
image: postgres:15-alpine
environment:
POSTGRES_DB: umami
POSTGRES_USER: umami
POSTGRES_PASSWORD: umami_pass
volumes:
- umami-db-data:/var/lib/postgresql/data
restart: always
healthcheck:
test: ["CMD-SHELL", "pg_isready -U umami -d umami"]
interval: 5s
timeout: 5s
retries: 5
volumes:
umami-db-data:
Три категории проблем закрывают почти все обращения по Umami: (1) контейнер не видит базу, (2) миграции падают при обновлении версии, (3) скрипт трекинга подключён, но данные в дашборде не появляются. Идём по каждой.
Контейнер стартует, но не подключается к базе данных
Симптом: umami в статусе restarting, в логах — что-то вроде Can't reach database server at 'db:5432' или P1001 (это код ошибки Prisma). Причины почти всегда одни и те же.
1. В DATABASE_URL указан localhost вместо имени сервиса. Внутри docker-сети контейнеры видят друг друга по имени сервиса из docker-compose.yml, а не по localhost — это касается и 127.0.0.1. Правильно: postgresql://user:pass@db:5432/umami, где db — имя сервиса базы в том же compose-файле.
docker compose logs umami --tail 50
docker exec -it <postgres_container> psql -U umami -d umami -c '\dt'
2. База ещё не готова принимать соединения, когда стартует Umami. Без depends_on: condition: service_healthy и healthcheck у Postgres контейнер приложения может подняться раньше базы и упасть с первой попытки коннекта. Добавьте healthcheck, как в примере выше, — Docker Compose дождётся готовности базы перед стартом Umami.
3. Пароль или имя базы не совпадают между сервисами. Частая невнимательность — поменяли POSTGRES_PASSWORD в блоке db, но забыли обновить DATABASE_URL в блоке umami. Пересоздавайте оба контейнера после любой правки переменных:
docker compose up -d --force-recreate umami db
Если база отдельно стоит не в Docker, а на выделенном сервере — общая диагностика отказов подключения к PostgreSQL (в том числе pg_hba.conf и listen_addresses) разобрана в статье postgresql-ne-prinimaet-podklyucheniya-prichiny-i-reshenie — логика та же независимо от того, что именно к базе подключается.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверОшибки миграций Prisma при обновлении версии
Umami активно развивается, и между релизами меняется схема базы через Prisma-миграции, которые применяются автоматически при старте контейнера. Обычно это незаметно, но иногда обновление ломается посреди процесса — например, если контейнер перезапустили вручную во время миграции или закончилось место на диске.
Типичная ошибка в логах — код P3009: *"migrate found failed migrations in the target database"*. Она значит, что одна из миграций отметилась как применённая наполовину, и Prisma отказывается продолжать, чтобы не повредить данные ещё сильнее. Порядок действий:
# зайти в контейнер и посмотреть статус миграций
docker exec -it umami sh
npx prisma migrate status
# если конкретная миграция реально накатилась вручную/частично —
# пометить её как применённую и продолжить
npx prisma migrate resolve --applied "20240115000000_migration_name"
Если непонятно, накатилась миграция или нет — не гадайте, а восстанавливайтесь из бэкапа, снятого до обновления. Правило простое: снимайте дамп базы перед каждым docker compose pull, а не только перед мажорными релизами:
docker exec <postgres_container> pg_dump -U umami umami > umami_backup_$(date +%F).sql
Общий подход к автоматизации регулярных бэкапов Docker-томов — в статье bekap-docker-volume-na-servere-chastye-oshibki-i-resheniya, это применимо и к тому с данными Umami.
Скрипт подключён, но события не считаются
Дашборд Umami показывает ноль визитов, хотя <script>-тег вставлен и сетевой запрос к трекеру виден в консоли браузера. Причины по убыванию частоты:
1. Website ID не совпадает. У каждого сайта в Umami свой data-website-id (UUID), выданный при добавлении сайта в интерфейсе. Скопировали код с чужой вкладки или старого сайта — события уходят, но привязываются не туда. Сверьте атрибут в HTML с тем, что показывает UI при клике на сайт → Tracking code.
<script defer src="https://analytics.example.com/script.js" data-website-id="ваш-uuid"></script>
2. Адблокеры режут скрипт по паттерну имени. Списки вроде EasyPrivacy знают про self-hosted Umami не хуже, чем про облачный, и блокируют запросы, похожие на аналитику, даже если скрипт лежит на вашем собственном домене. Официально поддерживаемый обход — переименовать путь к скрипту через реверс-прокси, не трогая логику самого приложения:
location /js/tracker.js {
proxy_pass http://127.0.0.1:3000/script.js;
}
location /api/send {
proxy_pass http://127.0.0.1:3000/api/send;
}
И в HTML используйте новый путь: src="https://example.com/js/tracker.js". Это снижает потери от блокировщиков, но не гарантирует 100% — часть пользователей блокирует JS-трекинг вообще любым способом, и с этим ничего не поделать без ущерба для приватности, ради которой вы вообще выбрали self-hosted аналитику.
3. Включён "Do Not Track" respecting, и браузер шлёт DNT-заголовок. В настройках сайта в Umami есть переключатель уважения заголовка DNT — если он включён, посетители с DNT в браузере не попадут в статистику. Это осознанный компромисс приватности, а не баг; проверьте настройку сайта, если ожидаете иные цифры.
4. Реверс-прокси не пробрасывает нужные заголовки. Если Umami стоит за nginx или Traefik, убедитесь, что заголовки Host, X-Forwarded-For и X-Forwarded-Proto доходят до приложения — без них геолокация и часть логики сбора событий работает некорректно. Базовые ошибки настройки nginx как прокси, включая пропавшие заголовки, разобраны в статье nginx-kak-revers-proksi-na-servere-chastye-oshibki-i-resheniya.
Сколько ресурсов реально нужно и когда подключать Redis
В отличие от Plausible с прожорливым ClickHouse, сам процесс Umami — лёгкий Node.js-сервис, и требования у него скромные. Ориентировочно (это именно ориентир — фактическая нагрузка зависит от числа сайтов и глубины хранимой истории событий):
| Нагрузка | RAM | vCPU | Диск |
|---|---|---|---|
| 1-2 сайта, до 50 000 событий/мес | 1 ГБ | 1 | 10-15 ГБ SSD |
| несколько сайтов, до 500 000 событий/мес | 2 ГБ | 1-2 | 20-30 ГБ SSD |
| много сайтов, миллионы событий/мес | 4 ГБ+ | 2+ | 40 ГБ+ SSD, растёт с историей |
Основной потребитель ресурсов при росте — не сам Umami, а база данных: PostgreSQL под ней хранит каждое событие как строку, и на больших объёмах имеет смысл следить за индексами и регулярным VACUUM. Если сервер общий с другими сервисами — закладывайте память под базу отдельно, не рассчитывая, что она "подожмётся" при пиках. Общие приёмы настройки PostgreSQL под нагрузку разобраны в статье postgresql-na-servere-chastye-oshibki-i-resheniya.
В актуальных версиях Umami есть опциональная поддержка Redis (REDIS_URL) — она снимает часть нагрузки с базы на кэшировании сессий и часто запрашиваемых данных дашборда. Для одного-двух сайтов с умеренным трафиком Redis не нужен вообще; подключать его стоит, когда дашборд начинает заметно тормозить под несколькими одновременными пользователями или при большом числе отслеживаемых сайтов на одном инстансе.
Если разворачиваете весь стек через docker-compose в продакшене, а не для теста — стоит сразу заложить лимиты ресурсов на контейнеры и restart-политику, это разобрано в статье docker-compose-dlya-prodakshena-na-servere-chastye-oshibki-i-resheniya.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Umami или Plausible — что проще в самостоятельной поддержке?
Umami легче по стеку (одна база вместо связки PostgreSQL+ClickHouse), поэтому и падает реже, и требует меньше ресурсов. Если нужны более глубокие отчёты из коробки — присмотритесь к Plausible, но за счёт большей сложности инфраструктуры.
Можно ли перейти с MySQL на PostgreSQL без потери данных?
Штатного инструмента миграции между типами баз в Umami нет — придётся переносить данные вручную через экспорт/импорт таблиц или писать собственный скрипт конвертации. Проще спланировать выбор СУБД заранее, чем переезжать позже.
Почему цифры в Umami отличаются от Google Analytics?
Umami не использует cookies для идентификации посетителей и может уважать заголовок Do Not Track — это меняет методику подсчёта уникальных визитов, а не означает ошибку сбора данных.
Как исключить собственные заходы на сайт из статистики?
Самый простой способ — заблокировать свой IP на уровне реверс-прокси для пути /api/send, либо использовать локальное расширение/фильтр в браузере, который блокирует запросы к вашему домену аналитики.
Нужен ли внешний SMTP для Umami?
Нет, в отличие от Plausible, Umami по умолчанию не отправляет писем для подтверждения регистрации — учётные записи создаются администратором вручную через интерфейс или CLI, почтовый релей не требуется.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →