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

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

MAATRIX

Если вам нужна веб-аналитика без баннера про cookies на весь экран, без передачи данных посетителей в Google и без пары гигабайт оперативки под Matomo — Umami закрывает этот вопрос за один docker-compose up. Это минималистичный self-hosted счётчик: один контейнер приложения, одна база PostgreSQL, простой дашборд без десятков вкладок. Ниже — рабочий конфиг, который можно скопировать целиком, и то, что обычно всплывает после первого запуска: инициализация, HTTPS, трекинг-скрипт и бэкап.

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

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

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

Что такое Umami и зачем он вам

Umami — open-source аналитика, написанная на Node.js, которая занимает нишу между «просто counter.js» и полновесным Matomo. Она считает то, что реально нужно в 90% случаев: уникальных посетителей, просмотры страниц, источники трафика, страны, устройства, длительность сессий и кастомные события. Никаких тепловых карт, записей сессий и модулей a/b-тестирования — и это не недостаток, а осознанный выбор минимализма.

Ключевые отличия от альтернатив:

  • От Google Analytics — данные не покидают ваш сервер, не нужен баннер согласия на cookies (Umami не ставит cookies посетителю по умолчанию), GA4 не блокируется адблокерами так агрессивно, как Umami, если он крутится на вашем домене.
  • От Matomo — Umami заметно легче по требованиям к ресурсам и проще в администрировании: там, где у Matomo десятки таблиц конфигурации и php-fpm, у Umami один Node-процесс и один API. Если Matomo — это «аналитика для агентства», то Umami — «аналитика для одного сайта или десятка сайтов у одного владельца». Если вам всё же нужна более развёрнутая функциональность (воронки, heatmaps, A/B), стоит посмотреть в сторону Matomo.
  • От Plausible — концептуально близкие продукты (оба про приватность и простоту), но Umami бесплатен для self-hosting без ограничений по трафику и написан не на Elixir, а на связке Node.js + PostgreSQL/MySQL, что для многих проще в поддержке. Если вы уже сравниваете варианты, у нас есть отдельный разбор установки Plausible.

Umami умеет отслеживать несколько сайтов из одной установки, поддерживает кастомные события через data-umami-event, отдаёт данные по REST API и не требует куки-баннера в большинстве юрисдикций (проверьте это с юристом, если работаете в ЕС — Umami снижает риски, но не отменяет due diligence).

Что понадобится перед стартом

Ресурсы под Umami скромные — ориентировочно хватает 1 vCPU и 1 ГБ RAM для одного-двух сайтов с умеренным трафиком; на большем числе доменов или тысячах визитов в день закладывайте 2 ГБ, чтобы PostgreSQL не упирался в лимиты по кешу. Точные цифры зависят от трафика и объёма истории — держите это как ориентир, а не гарантию.

Понадобится:

  • сервер с установленным Docker и Docker Compose (если ещё не разворачивали — вот пошаговая установка Docker на Ubuntu 24.04);
  • домен или поддомен, например analytics.example.com, с A-записью на IP сервера;
  • открытые порты 80 и 443, если планируете HTTPS через Caddy или Let's Encrypt;
  • 5-10 минут времени.

Создайте рабочую директорию:

mkdir -p ~/umami && cd ~/umami

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

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

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

Готовый docker-compose.yml для Umami

Официальный образ Umami со встроенной поддержкой PostgreSQL называется ghcr.io/umami-software/umami:postgresql-latest. Ниже — конфиг с базой, персистентным томом и healthcheck, который не даст приложению стартовать раньше готовности базы:

services:
  umami:
    image: ghcr.io/umami-software/umami:postgresql-latest
    container_name: umami
    restart: always
    environment:
      DATABASE_URL: postgresql://umami:${DB_PASSWORD}@db:5432/umami
      DATABASE_TYPE: postgresql
      APP_SECRET: ${APP_SECRET}
    ports:
      - "3000:3000"
    depends_on:
      db:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://localhost:3000/api/heartbeat || exit 1"]
      interval: 30s
      timeout: 5s
      retries: 3

  db:
    image: postgres:15-alpine
    container_name: umami-db
    restart: always
    environment:
      POSTGRES_DB: umami
      POSTGRES_USER: umami
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - umami-db-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U umami"]
      interval: 5s
      timeout: 5s
      retries: 5

volumes:
  umami-db-data:

Пароль и секрет вынесены в переменные окружения — создайте рядом файл .env:

cat > .env << 'EOF'
DB_PASSWORD=замените-на-длинный-случайный-пароль
APP_SECRET=замените-на-случайную-строку-минимум-32-символа
EOF

Сгенерировать оба значения удобно одной командой:

openssl rand -hex 32

APP_SECRET используется для подписи сессий и токенов API — если его сменить на проде, все активные сессии администратора слетят, а API-ключи станут невалидными. Храните его так же бережно, как пароль от базы.

Порт 3000 в примере выведен наружу для проверки — как только настроите reverse proxy (раздел ниже), его можно убрать из ports и оставить доступ только внутри Docker-сети.

Запуск:

docker compose up -d
docker compose logs -f umami

При первом старте контейнер сам накатывает миграции базы — в логах это видно по строкам вида Prisma migrate и завершается сообщением о готовности сервера на порту 3000.

Первый запуск и создание администратора

Откройте http://ваш-ip:3000 (или домен, если уже настроили proxy) и войдите с дефолтными учётными данными:

  • логин: admin
  • пароль: umami

Первое, что нужно сделать — зайти в Settings → Profile → Change password и сменить пароль на свой. Дефолтная пара admin/umami — это не секрет, она есть в официальной документации, так что оставлять её на проде даже на пять минут не стоит, особенно если порт 3000 или ваш домен уже смотрят наружу.

Дальше добавьте сайт: Settings → Websites → Add website, укажите название и домен. Umami сгенерирует уникальный website-id и код трекинг-скрипта — он понадобится на следующем шаге.

HTTPS и reverse proxy: Caddy или Nginx

Отдавать аналитику по голому HTTP на порту 3000 не стоит: логин администратора и токены API должны идти по HTTPS. Проще всего поднять front перед Umami через Caddy — он сам получит сертификат Let's Encrypt:

analytics.example.com {
    reverse_proxy localhost:3000
}

Подробный разбор установки и автопродления сертификатов — в статье про Caddy с авто-SSL на Ubuntu 24.04.

Если в инфраструктуре уже используется Nginx, конфиг reverse proxy для Umami не отличается от типового — прокидываете запросы на 127.0.0.1:3000 и добавляете сертификат Let's Encrypt отдельно:

server {
    listen 443 ssl http2;
    server_name analytics.example.com;

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

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Общий разбор настройки Nginx как proxy перед докер-приложениями — в статье Nginx как reverse proxy на VPS. После того как HTTPS заработал, уберите публикацию порта 3000 из docker-compose.yml (строку ports: - "3000:3000") — доступ снаружи должен идти только через 443.

Трекинг-скрипт, кастомные события и бэкап базы

Код для вставки на сайт Umami показывает прямо в интерфейсе после добавления сайта — он выглядит примерно так:

<script
  defer
  src="https://analytics.example.com/script.js"
  data-website-id="ваш-website-id">
</script>

Вставляется перед закрывающим </head>. Никаких дополнительных cookie-баннеров под это не требуется — Umami по умолчанию не использует cookies для идентификации посетителя, а строит анонимный дневной хэш из IP, user-agent и соли.

Кастомные события отслеживаются атрибутом data-umami-event без единой строчки JS:

<button data-umami-event="signup-click">Зарегистрироваться</button>

Или через JS API, если событие нужно триггерить программно:

umami.track('purchase', { plan: 'pro', amount: 990 });

Все данные Umami хранятся в одном PostgreSQL-контейнере, так что бэкап сводится к дампу базы. Простой вариант — cron-задача с pg_dump через docker exec:

docker exec umami-db pg_dump -U umami umami | gzip > umami-backup-$(date +%F).sql.gz

Для регулярных автоматических бэкапов тома целиком, с ротацией и отправкой во внешнее хранилище, удобнее использовать отдельный инструмент — разбор такого подхода есть в статье про бэкап Docker volume на VPS.

Обновление до новой версии — стандартная для Docker Compose процедура:

docker compose pull
docker compose up -d

Перед обновлением на проде стоит снять дамп базы (команда выше) — миграции схемы в Umami идут автоматически при старте контейнера и обычно безопасны, но откатить их проще из бэкапа, чем вручную.

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

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

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

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

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

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

Можно ли использовать MySQL вместо PostgreSQL?

Да, у Umami есть отдельный образ ghcr.io/umami-software/umami:mysql-latest с аналогичной схемой docker-compose.yml, разница только в сервисе базы и DATABASE_TYPE. PostgreSQL — более распространённый выбор в примерах из официальной документации.

Сколько сайтов можно подключить к одной установке?

Ограничений в самом Umami нет — один инстанс спокойно обслуживает десятки доменов, каждый со своим website-id и отдельной статистикой в общем дашборде.

Нужен ли баннер cookies для GDPR?

В большинстве трактовок — нет, поскольку Umami по умолчанию не ставит идентифицирующие cookies и хранит анонимизированные данные. Но это не юридическая консультация — если у вас аудитория в ЕС и высокие риски, стоит свериться с юристом.

Что делать, если после docker compose up контейнер umami постоянно перезапускается?

Чаще всего причина — контейнер стартовал раньше, чем PostgreSQL успел поднять слушающий сокет, либо неверный DATABASE_URL в .env. Проверьте docker compose logs umami и убедитесь, что depends_on с condition: service_healthy действительно прописан, как в конфиге выше.

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

Достаточно перенести том umami-db-data (или дамп из pg_dump) и файл .env с тем же APP_SECRET — иначе все выданные ранее сессии и API-токены станут недействительными. Общий алгоритм переноса докер-проектов описан в статье как перенести Docker-проект на другой сервер.

Отличается ли что-то в конфиге для ARM-серверов?

Официальные образы Umami мультиархитектурные и собираются под arm64, так что конфиг выше без изменений работает и на ARM-инстансах — тонкости Docker на ARM разобраны отдельно, если сомневаетесь в совместимости других сервисов.

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

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

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