Rybbit на VPS: приватная аналитика вместо Google Analytics
Счётчик без cookie и без баннера согласия, данные которого лежат на вашем сервере. Разбираемся, как Rybbit считает людей без cookie, ставим его на Ubuntu одной командой с автоматическим HTTPS и подключаем счётчик к сайту так, чтобы его не резали блокировщики.
Почему вебмастера уходят с Google Analytics
Причин обычно четыре, и денег среди них нет — GA4 бесплатный.
1. Простой вопрос требует сложного ответа
В GA4 нет привычных «просмотров страниц» как основы отчёта — всё построено на событиях и параметрах. Чтобы узнать «сколько человек пришло вчера из поиска и что они читали», нужно собрать отчёт в конструкторе. Владелец сайта на пять страниц тратит на это вечер и всё равно не уверен в результате.
2. Блокировщики режут часть аудитории
Домен Google Analytics стоит первым в каждом фильтре — от uBlock Origin до встроенной защиты Brave, Firefox и Safari. Насколько именно занижена статистика, зависит от тематики: на сайтах для разработчиков и на IT-тематике потери самые большие. Проблема не в самой цифре, а в том, что вы не знаете, какая часть аудитории для вас невидима.
3. Данные о ваших посетителях — не ваши
Счётчик собирает поведение ваших читателей и отдаёт его рекламной компании. Для российского сайта к этому добавляется вопрос, где физически лежат данные пользователей, — а вы не можете ни ответить на него, ни повлиять на ответ.
4. Историю могут стереть без вас
Детальные данные в GA4 хранятся ограниченный срок, а история прошлой версии, Universal Analytics, была удалена Google в 2024 году — вместе со всей накопленной статистикой тех, кто не успел её выгрузить. Свой сервер такой сюрприз исключает: данные удаляются только тогда, когда вы сами это настроите.
Отсюда и спрос на приватные счётчики: небольшой скрипт, никаких cookie, простые понятные отчёты и база данных, которая физически стоит у вас.
Что такое Rybbit
Rybbit — открытая веб-аналитика под лицензией AGPL-3.0, самый быстрорастущий проект в своей нише: 12,6 тысячи звёзд на GitHub, актуальная версия v2.8.0 от 27 июля 2026 года. Есть платное облако разработчиков и есть полноценная самостоятельная установка — о ней и речь.
Что вы получаете после установки:
- обычный дашборд: посетители, сессии, страницы, источники, страны, устройства, браузеры — всё на одном экране без конструктора отчётов;
- цели и воронки — «сколько людей дошло от статьи до формы заявки и где отвалилось»;
- записи сессий — видео того, как посетитель двигал мышь и кликал по странице (выключено по умолчанию);
- карта путей по сайту, отчёт по возвращаемости, скорость страниц (Core Web Vitals);
- отслеживание ошибок JavaScript у реальных посетителей;
- публичный дашборд — можно открыть статистику клиенту или читателям по ссылке;
- сколько угодно сайтов и пользователей на одной установке.
Чего в бесплатной версии нет
Два пункта остались только в облаке: отчёты на почту и интеграция с Google Search Console. Всё остальное, включая записи сессий и воронки, в self-hosted работает полностью — этим Rybbit заметно отличается от Plausible, где бесплатная версия урезана специально.
Как Rybbit узнаёт посетителей без cookie
Это главное, что стоит понять до установки: от механики зависит и юридическая сторона, и то, как читать цифры.
Классический счётчик кладёт в браузер cookie с идентификатором и потом узнаёт его. Rybbit не кладёт ничего — ни cookie, ни записи в localStorage. Вместо этого сервер при каждом событии считает короткий хеш:
user_id = sha256(IP-адрес + User-Agent) → первые 12 символовОдинаковый IP и один и тот же браузер дают одинаковый хеш — значит, это один и тот же посетитель. Сам IP-адрес при этом в базу не записывается: он нужен только для определения страны с городом и для расчёта хеша. Сохранение IP включается отдельным переключателем, но по умолчанию он выключен — и включать его без веской причины не надо.
Что из этого следует на практике
- Cookie-баннер ради счётчика не нужен — в браузере посетителя ничего не сохраняется.
- Один человек с телефона и с ноутбука — это два разных посетителя. Цифра «пользователи» у любого приватного счётчика всегда завышена относительно живых людей.
- Смена сети (Wi-Fi → мобильный интернет) как правило создаёт нового посетителя. Обновление браузера — тоже, потому что меняется User-Agent.
- Сессия закрывается после 30 минут без действий — как и в других системах.
В настройках сайта есть переключатель User ID Salting: он добавляет к хешу секретную «соль», которая меняется каждые сутки. С ним связать посетителя между вчера и сегодня невозможно даже теоретически — приватность выше. Но вместе с этим ломается отчёт о возвращаемости: каждый день все посетители становятся новыми. По умолчанию соль выключена, и для обычного контентного сайта это правильный выбор.
Rybbit, Plausible, Umami, Matomo и Метрика: что выбрать
| Rybbit | Plausible CE | Umami | Matomo | Метрика | |
|---|---|---|---|---|---|
| Лицензия | AGPL-3.0 | AGPL-3.0 | MIT | GPL-3.0 | закрытая |
| Что крутится на сервере | ClickHouse + Postgres + Redis | ClickHouse + Postgres | Postgres или MySQL | PHP + MySQL | — |
| RAM от | 2 ГБ | 2 ГБ | 1 ГБ | 2 ГБ | — |
| Без cookie | да | да | да | по умолчанию нет | нет |
| Воронки | да | только в облаке | да | платный плагин | да |
| Записи сессий | да | нет | нет | да | Вебвизор |
| Где лежат данные | у вас | у вас | у вас | у вас | у Яндекса |
Как выбирать. Нужен простой счётчик посещаемости и сервер поменьше — берите Umami: одна база, один контейнер, минимум обслуживания. Нужен полный набор инструментов веб-мастера — цели, воронки, записи сессий — и не жалко 4 ГБ памяти, берите Rybbit. Matomo имеет смысл, когда нужна максимально близкая замена «большой» аналитике с электронной коммерцией и привычным интерфейсом, и вы готовы обслуживать PHP-приложение.
Про Яндекс.Метрику. Она бесплатная, точная и с Вебвизором — если вопросов к передаче данных наружу нет, это рабочий вариант, и статью можно закрывать. Rybbit ставят тогда, когда данные не должны уходить никому вообще, когда аудитория не только российская, или когда счётчик нужен без cookie-баннера. Никто не мешает держать оба.
Что понадобится
- VPS от 2 ГБ RAM, лучше 4 ГБ. Ubuntu 24.04 LTS, диск от 20 ГБ. Архитектура x86-64 — на ARM ClickHouse запускается не везде.
- Поддомен для панели, в примерах —
stats.example.com. Отдельный домен покупать не нужно, хватит поддомена вашего же сайта. - Свободные порты 80 и 443. Если на сервере уже стоит Nginx или Apache — это не помеха, ниже есть отдельный раздел для такого случая.
Отдельная установка обслуживает любое количество сайтов, так что ставить её на каждый проект не нужно — одной хватит на все.
Шаг 1. Готовим сервер: Docker, DNS и память
Ставим Docker официальным скриптом — он же поставит плагин Compose:
sudo apt update && sudo apt install -y git dnsutils
curl -fsSL https://get.docker.com | sudo shТеперь в панели вашего регистратора добавьте A-запись, которая указывает поддомен на IP-адрес сервера:
Тип Имя Значение
A stats 203.0.113.10Подождите, пока запись разойдётся, и проверьте с сервера — должен вернуться его же IP-адрес:
dig +short stats.example.comНе пропускайте эту проверку
Сертификат выпускается автоматически при первом обращении к сайту, и для этого удостоверяющий центр должен достучаться до вашего сервера по домену. Если DNS ещё не обновился, установка пройдёт, а HTTPS не заработает — и вы будете искать причину не там. Обычно записи расходятся за 5–30 минут.
Если включён файрвол, откройте порты для веб-сервера:
sudo ufw allow 80/tcp
sudo ufw allow 443/tcpЕсли у сервера ровно 2 ГБ — сделайте это до установки
Два гигабайта — это работающий минимум, но без запаса: ClickHouse при старте забирает память агрессивно и на голом сервере может уронить сам себя. Файл подкачки снимает вопрос за минуту:
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstabНа сервере с 4 ГБ и больше этот шаг можно пропустить.
Шаг 2. Установка Rybbit
Скачиваем репозиторий в /opt/rybbit и запускаем установочный скрипт, указав свой поддомен:
sudo git clone https://github.com/rybbit-io/rybbit.git /opt/rybbit
cd /opt/rybbit
sudo chmod +x *.sh
sudo ./setup.sh stats.example.comЧто делает скрипт:
- создаёт файл
/opt/rybbit/.envс вашим доменом и случайным секретным ключом; - скачивает готовые образы и поднимает шесть контейнеров: базы ClickHouse, PostgreSQL и Redis, бэкенд, интерфейс и веб-сервер Caddy;
- Caddy сам получает сертификат Let’s Encrypt и дальше сам его продлевает — certbot и конфиги Nginx не нужны.
Скачивание образов занимает 2–5 минут. Проверяем, что все шесть контейнеров живы:
sudo docker psВ колонке STATUS у clickhouse, postgres и redis должно быть healthy. Если какой-то контейнер перезапускается по кругу — смотрите его логи, например:
sudo docker logs --tail 50 clickhouseШаг 3. Первый вход и закрытие регистрации
Откройте в браузере https://stats.example.com/signup и создайте аккаунт администратора. Если страница не открывается по HTTPS, дайте Caddy минуту на выпуск сертификата и посмотрите, что он пишет:
sudo docker logs --tail 30 caddyСразу после регистрации закройте регистрацию
По умолчанию форма создания аккаунта открыта всем, кто знает адрес панели. Пока она открыта, любой желающий может завести себе учётку на вашем сервере.
Откройте /opt/rybbit/.env и поменяйте одну строку:
DISABLE_SIGNUP=trueЗаодно, раз уж речь о приватности: своя установка по умолчанию отправляет разработчикам обезличенную статистику — версию и число строк в таблицах, без данных о посетителях. Отключается там же, отдельной строкой:
DISABLE_TELEMETRY=trueПрименяем — скрипт перезапускает стек с новыми переменными:
cd /opt/rybbit && sudo ./restart.shКоллег после этого можно приглашать изнутри панели: Settings → Organization. Ваш собственный вход, разумеется, продолжает работать.
Шаг 4. Ставим счётчик на сайт
В панели нажмите Add Site, укажите домен сайта — и Rybbit покажет готовый тег. Выглядит он так:
<script
src="https://stats.example.com/api/script.js"
data-site-id="1"
defer
></script>data-site-id у каждого сайта свой — берите его из панели, не из примера. Скрипт весит около 33 КБ, в сжатом виде — примерно 10 КБ, и грузится с атрибутом defer, то есть отрисовку страницы не задерживает.
Если сайт на WordPress
Проще всего плагином WPCode: Плагины → Добавить новый → найти WPCode → установить → в разделе Header вставить тег из панели Rybbit и сохранить. Правки в тему не нужны, и обновление темы ничего не сломает.
Если плагины ставить не хочется, добавьте в functions.php дочерней темы:
function rybbit_analytics_script() {
echo '<script src="https://stats.example.com/api/script.js" data-site-id="1" defer></script>';
}
add_action('wp_head', 'rybbit_analytics_script');В родительскую тему код класть нельзя — первое же обновление его сотрёт. Подробнее про сам сервер под WordPress — в статье WordPress на VPS.
Проверка. Откройте сайт в обычном окне браузера (не в режиме инкогнито с блокировщиком) и загляните в панель Rybbit: в шапке дашборда есть счётчик посетителей онлайн, он оживёт за несколько секунд, а сам визит появится в разделе Sessions. Если тихо, откройте консоль браузера клавишей F12, введите rybbit и нажмите Enter: если в ответ ошибка, скрипт не загрузился.
Если на сервере уже работает Nginx
Встроенному Caddy нужны порты 80 и 443. Если их уже занял ваш веб-сервер, он просто не поднимется. В этом случае Rybbit ставится без Caddy, а наружу его отдаёт существующий Nginx. Отличие ровно в одном флаге:
sudo git clone https://github.com/rybbit-io/rybbit.git /opt/rybbit
cd /opt/rybbit
sudo chmod +x *.sh
sudo ./setup.sh stats.example.com --no-webserverОбязательно закройте порты от интернета
С флагом --no-webserver скрипт публикует порты 3001 и 3002 на всех интерфейсах, то есть панель становится доступна по http://IP-сервера:3002 в обход HTTPS. И UFW тут не спасёт: Docker пробивает правила файрвола напрямую. Исправляется двумя строками в .env.
Откройте /opt/rybbit/.env и приведите две строки к такому виду:
HOST_BACKEND_PORT="127.0.0.1:3001:3001"
HOST_CLIENT_PORT="127.0.0.1:3002:3002"cd /opt/rybbit && sudo ./restart.shТеперь оба порта слушают только сам сервер. Создаём конфиг Nginx:
server {
listen 80;
server_name stats.example.com;
client_max_body_size 10M;
location /api/ {
proxy_pass http://127.0.0.1:3001;
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;
}
location / {
proxy_pass http://127.0.0.1:3002;
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 ln -s /etc/nginx/sites-available/stats.example.com /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d stats.example.comЗаголовок X-Real-IP здесь не украшение: именно из него Rybbit берёт адрес посетителя для определения страны. Забудете строку — вся аудитория окажется из города, где стоит ваш сервер. Строка client_max_body_size 10M нужна для записей сессий: без неё браузер будет получать ошибку 413 при отправке длинных записей.
Проксирование счётчика через свой домен
Своя установка уже теряет меньше визитов, чем облачный счётчик: вашего поддомена нет в готовых списках блокировщиков, в отличие от адресов Google и Яндекса. Но для браузера это всё ещё запрос на посторонний домен, а часть блокировщиков и режимов приватности режут такие запросы по общим правилам.
Лечится тем, что скрипт раздаётся с адреса самого сайта. Rybbit специально сделан под это: он смотрит, откуда его загрузили, отрезает от адреса хвост /script.js и дальше шлёт данные по тому же пути. То есть достаточно пробросить один префикс.
Добавьте в конфиг Nginx того сайта, который считаете (не панели), внутрь блока server:
location /stats/ {
proxy_pass https://stats.example.com/api/;
proxy_set_header Host stats.example.com;
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_ssl_server_name on;
client_max_body_size 10M;
}sudo nginx -t && sudo systemctl reload nginxПосле этого замените в теге адрес скрипта на путь своего сайта:
<script
src="https://example.com/stats/script.js"
data-site-id="1"
defer
></script>Проверить можно прямо с сервера — в ответ должен прийти код 200:
curl -s -o /dev/null -w "%{http_code}\n" https://example.com/stats/script.jsПоследний штрих: в панели откройте настройки сайта и включите First-Party Proxy. Этот переключатель говорит Rybbit, что перед ним стоит ваш собственный прокси и заголовкам с IP-адресом посетителя можно доверять.
Ресурсы: сколько ест и как не забить диск
Основной потребитель памяти — ClickHouse: он рассчитан на аналитику больших объёмов и резервирует память заранее. Отсюда и минимум в 2 ГБ. Посмотреть реальное потребление на своём сервере:
sudo docker stats --no-streamЕсли сервер на 2 ГБ, кроме файла подкачки из первого шага уменьшите число рабочих процессов бэкенда: по умолчанию их четыре, для небольшого сайта хватит одного. Добавьте строку в /opt/rybbit/.env и перезапустите:
CLUSTER_WORKERS=1cd /opt/rybbit && sudo ./restart.shДиск: главная ловушка
Обычные события занимают мало — ClickHouse сжимает их очень плотно. Всё меняют записи сессий: одна запись весит примерно в тысячу раз больше, чем событие о просмотре страницы, и хранится она в той же базе. Именно поэтому эта функция выключена по умолчанию — включайте её осознанно и следите за местом.
Что сколько занимает по факту (frog — пароль ClickHouse по умолчанию; обе базы слушают только сам сервер, наружу они не торчат):
sudo docker exec clickhouse clickhouse-client --password frog \
--query "SELECT table, formatReadableSize(sum(bytes_on_disk)) AS size
FROM system.parts WHERE active AND database = 'analytics'
GROUP BY table ORDER BY sum(bytes_on_disk) DESC"Сроки хранения по умолчанию:
| Данные | Хранятся |
|---|---|
| События: просмотры, цели, клики | вечно |
| Записи сессий | 30 дней |
| Отсеянный трафик ботов | 3 месяца |
Если записи сессий съедают место быстрее, чем хотелось бы, сократите срок хранения до двух недель:
sudo docker exec clickhouse clickhouse-client --password frog --database analytics \
--query "ALTER TABLE session_replay_events
MODIFY TTL toDateTime(timestamp) + INTERVAL 14 DAY"Обновление и резервная копия
Обновление — одна команда, она сама заберёт новый код и образы и пересоздаст контейнеры:
cd /opt/rybbit && sudo ./update.shРезервная копия состоит из трёх частей. Первая и самая важная — /opt/rybbit/.env: там лежит ключ BETTER_AUTH_SECRET, от которого зависят и входы пользователей, и идентификаторы посетителей. Потеряете его — потеряете связь с накопленной статистикой. Вторая — настройки сайтов и пользователи в PostgreSQL:
sudo docker exec postgres pg_dump -U frog -d analytics -Fc \
| sudo tee /root/rybbit-pg-$(date +%F).dump > /dev/nullТретья — сами данные аналитики в ClickHouse. Их проще всего забрать копией каталога, для этого стек нужно ненадолго остановить:
cd /opt/rybbit
sudo docker compose --profile with-webserver stop
sudo tar czf /root/rybbit-ch-$(date +%F).tar.gz \
-C /var/lib/docker/volumes/rybbit_clickhouse-data/_data .
sudo ./restart.shПростой — меньше минуты. Как автоматизировать выгрузку копий на внешнее хранилище, описано в статье Restic + rclone: бэкапы VPS в облако.
Частые проблемы
Сайт не открывается по HTTPS, сертификат не выпускается
Причин ровно три, и все проверяются за минуту. Первая — A-запись ещё не разошлась или указывает не туда: dig +short stats.example.com должен вернуть IP вашего сервера. Вторая — порт 80 закрыт файрволом или занят другим веб-сервером: sudo ss -tlnp | grep :80 покажет, кто на нём сидит; если это Nginx, вам нужен раздел про --no-webserver. Третья — опечатка в домене при запуске setup.sh: проверьте строку DOMAIN_NAME в .env, поправьте и выполните sudo ./restart.sh. Настоящая причина всегда видна в sudo docker logs caddy.
Контейнер clickhouse перезапускается по кругу
Два типичных случая. Не хватило памяти — в логах будет упоминание OOM или процесс просто убивается без объяснений; лечится файлом подкачки из раздела про ресурсы или тарифом побольше. Либо процессор сервера не поддерживает набор инструкций SSE 4.2, который ClickHouse требует обязательно: так бывает на виртуалках, где хостер выдал обобщённый тип процессора вместо настоящего. Проверить: grep -o sse4_2 /proc/cpuinfo | head -1 — если ответ пустой, ClickHouse на этом сервере не запустится, нужен другой тариф или другой провайдер.
Счётчик стоит, а данных нет
Откройте консоль браузера (F12) на своём сайте и введите rybbit. Ошибка в ответ означает, что скрипт не загрузился: проверьте вкладку Network — запрос к script.js должен возвращать код 200. Дальше по частоте: тег вставлен не в <head>; data-site-id не тот, что в панели; конструктор страниц или Google Tag Manager вырезали атрибуты data-* при вставке; работает блокировщик. Отдельный неочевидный случай — проверка через консольные утилиты вроде curl или через headless-браузер: Rybbit по умолчанию отсеивает ботов, и такие визиты в отчёт не попадут, хотя запрос прошёл успешно.
Все посетители из одного города
Верный признак того, что до Rybbit не доходит адрес посетителя и он видит адрес вашего же прокси. Проверьте, что в конфиге Nginx есть строка proxy_set_header X-Real-IP $remote_addr; — именно этот заголовок Rybbit читает в первую очередь. И проверьте, что в настройках сайта включён First-Party Proxy — без него Rybbit может предпочесть адрес того, кто постучался к нему напрямую, а это ваш собственный прокси или Cloudflare.
Кончилось место на диске
В 99% случаев это записи сессий. Посмотрите размеры таблиц командой из раздела про диск: если session_replay_events заметно больше остальных — выключитеSession Replay в настройках сайта и сократите срок хранения. Если место нужно прямо сейчас, записи можно удалить целиком, статистика при этом не пострадает: sudo docker exec clickhouse clickhouse-client --password frog --database analytics --query "TRUNCATE TABLE session_replay_events".
Коротко: план с нуля
- VPS от 2 ГБ RAM на Ubuntu 24.04, Docker через get.docker.com, на 2 ГБ — файл подкачки
- A-запись
statsна IP сервера, проверить черезdig +short sudo ./setup.sh stats.example.com— шесть контейнеров и HTTPS автоматом- Создать аккаунт на
/signup, затемDISABLE_SIGNUP=trueи./restart.sh Add Site→ скопировать тег → в<head>сайта или в WPCode- Проверить, что визит виден в панели
- Проксировать счётчик через свой домен, чтобы не терять визиты
- Записи сессий включать осознанно и следить за диском
Под Rybbit нужен VPS от 2 ГБ RAM — подойдёт и тот, на котором уже работает сайт
VPS для сайта и WordPress →