Стандартные сервисы веб-аналитики — Яндекс.Метрика и Google Analytics 4 — стали тяжелым бременем для современных веб-ресурсов. Их клиентские скрипты весят от 50 до 150 КБ, выполняют сложный парсинг DOM-дерева, ухудшают метрики Core Web Vitals (в особенности показатели INP и LCP) и требуют обязательного показа раздражающих cookie-баннеров в соответствии с 152-ФЗ и GDPR.
Но главная беда для владельцев сайтов — катастрофическая потеря данных. По статистике технических проектов, от 30% до 45% посетителей используют расширения-блокировщики (uBlock Origin, AdGuard, Privacy Badger) или встроенную защиту браузеров Brave, Firefox и Safari. В результате в стандартных отчетах отсутствует почти половина реального трафика, а конверсии и пути клиентов фиксируются с огромными погрешностями.
Инженерное решение этой проблемы — развертывание собственной независимой системы аналитики Umami на легковесной VDS в связке с Docker Compose и PostgreSQL. Ниже подробно разбираем развертывание контейнеров, маскировку скрипта от списков EasyPrivacy, настройку обратного прокси Nginx с бесплатным SSL-сертификатом и организацию автоматических бэкапов базы данных в облачное S3-хранилище.
1. Зачем развертывать Umami: потери от AdBlock, замедление DOM и 152-ФЗ / GDPR
Umami — это открытая (Open Source) платформа веб-аналитики, написанная на TypeScript, Node.js (Next.js) и Prisma, использующая в качестве хранилища реляционную СУБД PostgreSQL. В отличие от громоздких систем вроде Matomo (бывший Piwik), Umami сфокусирована на максимальной скорости и лаконичности.
Сравним ключевые эксплуатационные характеристики Umami и коммерческих счетчиков:
| Критерий оценки | Google Analytics 4 | Яндекс.Метрика | Self-hosted Umami |
|---|---|---|---|
| Размер клиентского JS | ~50–90 КБ (gtag.js) |
~60–120 КБ (tag.js + вебвизор) |
~2 КБ (script.js) |
| Использование Cookies | Обязательно (_ga, _gid) | Обязательно (_ym_uid, _ym_d) | Полный отказ от cookies |
| Необходимость Cookie-баннера | Да (строгое требование GDPR) | Да (требование 152-ФЗ) | Не требуется |
| Блокировка AdBlock / uBlock | 30–45% потерь у IT-аудитории | 25–40% потерь | 0% потерь (при маскировке) |
| Владение сырыми данными | На серверах Google (США) | На серверах Яндекса (РФ) | Исключительно на вашем VDS |
| Влияние на PageSpeed (LCP/INP) | Ощутимое замедление TBT | Нагрузка при активном вебвизоре | Абсолютно незаметно (0 ms TBT) |
Umami идентифицирует уникальных пользователей без сохранения персональных данных: платформа генерирует анонимный суточный хэш на основе IP-адреса посетителя, строки User-Agent и секретной соли сервера (APP_SECRET). В полночь соль обновляется, что исключает сквозной межсайтовый трекинг и делает сервис полностью комплаентным с нормами приватности без всплывающих предупреждений.
2. Системные требования к VDS и подготовка чистой Ubuntu 24.04 LTS
Благодаря высокой эффективности связки Node.js и PostgreSQL инстанс Umami способен обслуживать до 1–2 миллионов просмотров страниц в месяц на минимальном тарифе виртуального сервера:
- Процессор: 1–2 виртуальных ядра (vCPU).
- Оперативная память: 1–2 ГБ RAM (под приложение требуется ~150–250 МБ, под PostgreSQL — ~250–500 МБ).
- Диск: от 20 ГБ NVMe SSD. Сжатые таблицы PostgreSQL требуют около 1 ГБ на каждые 10 миллионов собранных событий.
- Сетевой адрес: один выделенный статический IPv4.
- Домен: отдельный поддомен (например,
analytics.yourdomain.ruили нейтральныйmetrics.mycompany.org).
Совет инженера: проверка внешнего IP и делегирования DNS
Перед началом настройки проверьте свой внешний статический адрес VDS с помощью утилиты Определить мой IP-адрес, а после добавления A-записи поддомена убедитесь в ее глобальной доступности через DNS Lookup и Резолвер на платформе SysKit.
Подключитесь к серверу по SSH под пользователем с привилегиями sudo. Обновите пакетную базу и настройте файл подкачки (Swap), чтобы защитить СУБД от аварийного завершения службой Linux OOM-Killer при кратковременных нагрузках:
# Обновление индекса пакетов и системы
sudo apt update && sudo apt upgrade -y
# Создание и активация Swap-файла размером 2 ГБ
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# Автозагрузка Swap при старте ОС
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
# Оптимизация агрессивности сброса страниц памяти
sudo sysctl vm.swappiness=10
echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf
Подробное руководство по тонкой настройке сжатого пространства в оперативной памяти читайте в материале Настройка Swap и ZRAM на Linux VDS: спасение от OOM-Killer.
Установите официальный контейнерный движок Docker Engine и плагин Docker Compose:
# Установка вспомогательных утилит
sudo apt install -y ca-certificates curl gnupg lsb-release
# Добавление официального GPG-ключа репозитория Docker
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
# Подключение APT-репозитория
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Установка Docker и плагина Compose
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# Включение автозапуска службы
sudo systemctl enable --now docker
3. Развертывание связки Umami и PostgreSQL в Docker Compose
Создадим изолированный рабочий каталог /opt/umami и структуру файлов конфигурации:
sudo mkdir -p /opt/umami && cd /opt/umami
sudo mkdir -p sql-data
Сгенерируйте надежные криптографические пароли для базы данных и внутреннюю соль приложения APP_SECRET:
# Генерация надежного пароля для PostgreSQL
openssl rand -hex 24
# Генерация APP_SECRET для шифрования сессий Umami
openssl rand -hex 32
Создайте файл переменных окружения /opt/umami/.env:
cat <<'EOF' | sudo tee /opt/umami/.env
# Настройки базы данных PostgreSQL
POSTGRES_DB=umami
POSTGRES_USER=umami_user
POSTGRES_PASSWORD=ЗАМЕНИТЕ_НА_ВАШ_ПАРОЛЬ_DB
# Строка подключения для Prisma ORM
DATABASE_URL=postgresql://umami_user:ЗАМЕНИТЕ_НА_ВАШ_ПАРОЛЬ_DB@db:5432/umami
# Секретный ключ для хэширования солей посетителей
APP_SECRET=ЗАМЕНИТЕ_НА_ВАШ_APP_SECRET
# Порт локальной привязки сервиса
PORT=3000
EOF
Теперь создайте файл оркестрации /opt/umami/docker-compose.yml. Обратите внимание на директивы ограничения ресурсов и привязку порта только к локальному интерфейсу 127.0.0.1:
services:
umami:
image: ghcr.io/umami-software/umami:postgresql-latest
container_name: umami-app
restart: unless-stopped
ports:
- "127.0.0.1:3000:3000"
environment:
DATABASE_URL: ${DATABASE_URL}
APP_SECRET: ${APP_SECRET}
depends_on:
db:
condition: service_healthy
networks:
- umami-internal
mem_limit: 512m
cpus: 1.0
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
db:
image: postgres:16-alpine
container_name: umami-db
restart: unless-stopped
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- ./sql-data:/var/lib/postgresql/data
networks:
- umami-internal
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 5s
timeout: 5s
retries: 5
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
networks:
umami-internal:
driver: bridge
Важное предупреждение: безопасность портов Docker
Никогда не публикуйте порты баз данных (5432) и приложений (3000) как 0.0.0.0:3000:3000. Docker автоматически модифицирует цепочки iptables, минуя правила фаервола UFW. Привязка к 127.0.0.1:3000:3000 гарантирует, что сервис доступен только локальному веб-серверу Nginx. Детали этой проблемы описаны в исследовании Обход правил UFW в Docker: исправление уязвимости публикации портов.
Запустите контейнеры в фоновом режиме:
sudo docker compose up -d
Проверьте статус запуска и логи инициализации базы данных:
sudo docker compose ps
sudo docker compose logs -f umami
При первом запуске Umami автоматически выполнит миграции Prisma и создаст необходимые таблицы в PostgreSQL. Сервис будет готов к приему запросов через несколько секунд.
4. Рекомендуемые надежные VDS-провайдеры для сервера веб-аналитики
Сервер аналитики обрабатывает регулярный фоновый поток HTTP-запросов и выполняет частые операции записи в базу данных. Для стабильной работы без очередей I/O требуются быстрые NVMe-накопители корпоративного класса и гарантированная пропускная способность сети. Ниже представлены проверенные российские облачные провайдеры для размещения Umami:
Рекомендуемые VDS-провайдеры
Отказоустойчивые сервера с быстрыми NVMe и каналом до 1 Гбит/с
Timeweb Cloud
Идеальная площадка для запуска Umami: готовый шаблон Docker, сверхбыстрые NVMe со скоростью до 3500 МБ/с, бесплатный перенос и почасовая оплата. Сеть до 1 Гбит/с без жестких лимитов трафика.
Selectel
Высоконадежные облачные серверы уровня Enterprise в дата-центрах Москвы и Санкт-Петербурга. Отличный выбор для корпоративных проектов: возможность подключения S3-хранилища для бэкапов базы данных в одной локации.
Beget
Продуманная и удобная панель управления с развертыванием чистого сервера Ubuntu за 60 секунд. Бесплатная базовая защита от сетевых атак, стабильный канал и отзывчивая техническая поддержка 24/7.
5. Настройка Nginx Reverse Proxy и автоматический выпуск SSL Let's Encrypt
Для маршрутизации внешнего трафика, шифрования по протоколу HTTPS и терминирования SSL установим веб-сервер Nginx и утилиту Certbot:
sudo apt install -y nginx certbot python3-certbot-nginx
Создайте файл конфигурации виртуального хоста /etc/nginx/sites-available/analytics.conf, заменив analytics.yourdomain.ru на ваше реальное доменное имя:
server {
listen 80;
listen [::]:80;
server_name analytics.yourdomain.ru;
# Запрет доступа к скрытым файлам
location ~ /\. {
deny all;
}
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
# Оптимизация буферизации для высокой частоты запросов
proxy_buffering on;
proxy_buffers 8 16k;
proxy_buffer_size 16k;
}
}
Активируйте сайт, проверьте синтаксис конфигурации и перезапустите Nginx:
sudo ln -s /etc/nginx/sites-available/analytics.conf /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Выпустите бесплатный криптографический сертификат Let's Encrypt. Утилита Certbot автоматически обновит конфигурацию Nginx и настроит редирект с HTTP на HTTPS:
sudo certbot --nginx -d analytics.yourdomain.ru --agree-tos --no-eff-email -m admin@yourdomain.ru --redirect
Проверить корректность цепочки сертификатов, поддержку протокола TLS 1.3 и статус продления можно в онлайн-сервисе Проверка SSL / TLS сертификата на платформе SysKit.
6. Обход блокировщиков рекламы: маскировка трекера и кастомный эндпоинт
Популярные списки блокировки (в частности, EasyPrivacy и Peter Lowe's List) содержат регулярные выражения, реагирующие на стандартные пути Umami: /script.js и /api/send. Если оставить их по умолчанию, технически подкованные пользователи с uBlock Origin по-прежнему не попадут в статистику.
Для 100% обхода эвристических фильтров используем встроенную функцию маскировки URL в Nginx. Дополним блок server в файле /etc/nginx/sites-available/analytics.conf специальными псевдонимами:
# Маскировка JS-скрипта под нейтральное системное имя
location = /lib/telemetry.js {
proxy_pass http://127.0.0.1:3000/script.js;
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;
# Кэширование скрипта на стороне браузера на 24 часа
expires 24h;
add_header Cache-Control "public, no-transform";
}
# Маскировка API-эндпоинта отправки метрик
location = /api/v1/collect {
proxy_pass http://127.0.0.1:3000/api/send;
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;
}
Примените новые правила:
sudo nginx -t && sudo systemctl reload nginx
Теперь клиентский код будет загружаться по неприметному адресу /lib/telemetry.js, а пакеты данных отправляться на /api/v1/collect. Ни один фильтр блокировки не срежет такой запрос, так как он выглядит как обычный системный запрос первого уровня.
7. Подключение трекера на сайт и отслеживание кастомных событий
Откройте веб-интерфейс Umami в браузере по адресу https://analytics.yourdomain.ru. По умолчанию создана учетная запись администратора:
- Логин:
admin - Пароль по умолчанию:
umami
Важное предупреждение: смените пароль администратора
Сразу после первого входа перейдите в раздел Settings → Profile и установите сложный пароль администратора длиной от 16 символов. Не оставляйте учетные данные по умолчанию в открытом доступе.
Перейдите в раздел Settings → Websites и нажмите кнопку Add website. Укажите название проекта (например, My Awesome Project) и его доменное имя (например, myproject.ru). Umami сгенерирует уникальный идентификатор Website ID (UUID v4).
Вставьте следующий тег в секцию <head> вашего сайта перед закрывающим тегом:
<!-- Подключение трекера Umami с обходом AdBlock -->
<script
defer
src="https://analytics.yourdomain.ru/lib/telemetry.js"
data-website-id="00000000-0000-0000-0000-000000000000"
data-host-url="https://analytics.yourdomain.ru/api/v1/collect">
</script>
Параметр data-host-url указывает скрипту отправлять телеметрию именно на замаскированный эндпоинт, гарантируя обход блокировщиков.
Отслеживание кликов и кастомных конверсий
Для фиксации целевых действий посетителей (клики по кнопкам, скачивание прайс-листов, переходы в Telegram) не нужно писать сложный код. Достаточно добавить HTML-атрибут data-umami-event к любому элементу:
<!-- Отслеживание клика по кнопке заказа -->
<button
data-umami-event="Order Click"
data-umami-event-plan="VDS-Enterprise">
Заказать сервер
</button>
<!-- Отслеживание перехода в Telegram-канал -->
<a
href="https://t.me/syskit_ru"
data-umami-event="Telegram Link Click">
Подписаться на канал
</a>
Для SPA-приложений (React, Vue, Next.js) доступен прямой программный вызов через глобальный объект umami:
// Вызов из JavaScript после успешной отправки формы
if (window.umami) {
umami.track('Lead Form Submitted', {
form: 'callback_modal',
source: 'landing_header'
});
}
8. Автоматическое резервное копирование базы данных PostgreSQL в S3-хранилище
База данных Umami хранит историческую ценность для маркетинга и аналитики. Потеря сервера без бэкапа уничтожит всю динамику трафика. Настроим автоматический ежедневный дамп базы PostgreSQL со сжатием и выгрузкой в S3-хранилище.
Создайте каталог и исполняемый bash-скрипт /opt/umami/backup.sh:
cat <<'EOF' | sudo tee /opt/umami/backup.sh
#!/bin/bash
set -eo pipefail
# Конфигурационные переменные
PROJECT_DIR="/opt/umami"
BACKUP_DIR="/opt/umami/backups"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
BACKUP_FILE="$BACKUP_DIR/umami_db_$TIMESTAMP.sql.gz"
RETENTION_DAYS=14
mkdir -p "$BACKUP_DIR"
# Загрузка переменных окружения
export $(grep -v '^#' "$PROJECT_DIR/.env" | xargs)
# Создание дампа базы данных через docker exec без остановки сервиса
echo "[$(date)] Запуск создания дампа базы PostgreSQL..."
docker exec umami-db pg_dump -U "$POSTGRES_USER" "$POSTGRES_DB" | gzip -9 > "$BACKUP_FILE"
echo "[$(date)] Дамп успешно создан: $BACKUP_FILE (размер: $(du -h "$BACKUP_FILE" | cut -f1))"
# Опциональная отправка в S3 (раскомментируйте при настроенном awscli / s3cmd)
# aws s3 cp "$BACKUP_FILE" "s3://my-cloud-backups/umami/" --endpoint-url https://s3.timeweb.cloud
# Удаление локальных дампов старше 14 дней
find "$BACKUP_DIR" -type f -name "umami_db_*.sql.gz" -mtime +$RETENTION_DAYS -delete
echo "[$(date)] Ротация завершена. Удалены архивы старше $RETENTION_DAYS дней."
EOF
sudo chmod +x /opt/umami/backup.sh
Проверьте ручной запуск скрипта создания бэкапа:
sudo /opt/umami/backup.sh
ls -lh /opt/umami/backups/
Добавьте регулярное задание в системный планировщик crontab для запуска резервного копирования каждую ночь в 03:30:
# Добавление задачи в cron суперпользователя
(sudo crontab -l 2>/dev/null; echo "30 3 * * * /opt/umami/backup.sh >> /var/log/umami_backup.log 2>&1") | sudo crontab -
Подробный разбор интеграции с облачными объектными хранилищами и оповещениями в Telegram читайте в материале Автоматический бэкап баз данных и файлов с VDS в S3-хранилище, а составить корректное расписание cron поможет Генератор расписаний Crontab.
9. Харденинг безопасности и безопасное обновление контейнеров
Чтобы сервер аналитики работал непрерывно и был надежно защищен от несанкционированного доступа, выполните базовый харденинг операционной системы:
- Настройка межсетевого экрана UFW: откройте только порты веб-сервера (
80,443) и SSH (по умолчанию22), заблокировав все остальные входящие подключения.sudo ufw default deny incoming sudo ufw default allow outgoing sudo ufw allow 22/tcp sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw enable - Защита от перебора паролей Fail2ban: установите Fail2ban для защиты SSH-демона и веб-сервера от брутфорс-атак. Подробнее в руководстве Настройка Fail2ban на VDS: защита SSH и Nginx.
Регламент обновления Umami
Команда Umami регулярно выпускает релизы с новыми функциями отчетов и патчами безопасности. Благодаря архитектуре Docker Compose обновление выполняется без риска повреждения данных:
cd /opt/umami
# 1. Загрузка свежего образа приложения
sudo docker compose pull umami
# 2. Перезапуск контейнера в бесшовном режиме
sudo docker compose up -d umami
# 3. Удаление устаревших неиспользуемых слоев Docker
sudo docker image prune -f
База данных PostgreSQL при этом продолжит работать без перерыва, а контейнер Umami автоматически применит новые миграции схемы при старте.
10. Резюме и чек-лист готовности к промышленной эксплуатации
Развертывание собственной аналитики Umami возвращает вам полный контроль над данными о посещаемости, кардинально ускоряет загрузку страниц сайта и исключает потери трафика из-за блокировщиков рекламы. Вы получаете чистый, эстетичный дашборд со всей необходимой статистикой (страницы, рефереры, страны, устройства, браузеры, цели) без юридических рисков и затрат на абонентскую плату.
Перед переводом трекера на боевые сайты сверьтесь с контрольным чек-листом готовности:
- [x] Порт контейнера
3000привязан строго к адресу127.0.0.1и закрыт от внешнего доступа. - [x] Пароль администратора по умолчанию
umamiизменен на надежный в настройках профиля. - [x] Выпущен и автоматически продлевается SSL-сертификат Let's Encrypt для поддомена.
- [x] В конфигурации Nginx настроена маскировка адреса скрипта и API-эндпоинта.
- [x] Настроено ночное резервное копирование базы PostgreSQL через cron с ротацией файлов.
- [x] В
docker-compose.ymlзаданы лимиты памяти (512M) и ротация логов (max-size: 10m).
Готовы запустить собственную независимую аналитику?
Выберите надежный виртуальный сервер с быстрыми NVMe-дисками, выделенным IPv4 и стабильным каналом связи для бесперебойного сбора метрик 24/7.