VPSРейтинг
Аналитика12 августа 2026 · 17 мин

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. Вместо этого сервер при каждом событии считает короткий хеш:

упрощённо, как это устроено в коде Rybbit
user_id = sha256(IP-адрес + User-Agent) → первые 12 символов

Одинаковый IP и один и тот же браузер дают одинаковый хеш — значит, это один и тот же посетитель. Сам IP-адрес при этом в базу не записывается: он нужен только для определения страны с городом и для расчёта хеша. Сохранение IP включается отдельным переключателем, но по умолчанию он выключен — и включать его без веской причины не надо.

Что из этого следует на практике

  • Cookie-баннер ради счётчика не нужен — в браузере посетителя ничего не сохраняется.
  • Один человек с телефона и с ноутбука — это два разных посетителя. Цифра «пользователи» у любого приватного счётчика всегда завышена относительно живых людей.
  • Смена сети (Wi-Fi → мобильный интернет) как правило создаёт нового посетителя. Обновление браузера — тоже, потому что меняется User-Agent.
  • Сессия закрывается после 30 минут без действий — как и в других системах.

В настройках сайта есть переключатель User ID Salting: он добавляет к хешу секретную «соль», которая меняется каждые сутки. С ним связать посетителя между вчера и сегодня невозможно даже теоретически — приватность выше. Но вместе с этим ломается отчёт о возвращаемости: каждый день все посетители становятся новыми. По умолчанию соль выключена, и для обычного контентного сайта это правильный выбор.

Rybbit, Plausible, Umami, Matomo и Метрика: что выбрать

 RybbitPlausible CEUmamiMatomoМетрика
ЛицензияAGPL-3.0AGPL-3.0MITGPL-3.0закрытая
Что крутится на сервереClickHouse + Postgres + RedisClickHouse + PostgresPostgres или MySQLPHP + 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:

Ubuntu 24.04, всё выполняется от root через sudo
sudo apt update && sudo apt install -y git dnsutils
curl -fsSL https://get.docker.com | sudo sh

Теперь в панели вашего регистратора добавьте A-запись, которая указывает поддомен на IP-адрес сервера:

A-запись у регистратора домена
Тип   Имя     Значение
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 и запускаем установочный скрипт, указав свой поддомен:

подставьте свой домен вместо stats.example.com
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 и поменяйте одну строку:

sudo nano /opt/rybbit/.env
DISABLE_SIGNUP=true

Заодно, раз уж речь о приватности: своя установка по умолчанию отправляет разработчикам обезличенную статистику — версию и число строк в таблицах, без данных о посетителях. Отключается там же, отдельной строкой:

то же самое /opt/rybbit/.env
DISABLE_TELEMETRY=true

Применяем — скрипт перезапускает стек с новыми переменными:

cd /opt/rybbit && sudo ./restart.sh

Коллег после этого можно приглашать изнутри панели: Settings Organization. Ваш собственный вход, разумеется, продолжает работать.

Шаг 4. Ставим счётчик на сайт

В панели нажмите Add Site, укажите домен сайта — и Rybbit покажет готовый тег. Выглядит он так:

вставить в <head> каждой страницы сайта
<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 дочерней темы:

wp-content/themes/ваша-тема-child/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 и приведите две строки к такому виду:

sudo nano /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:

sudo nano /etc/nginx/sites-available/stats.example.com
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:

/etc/nginx/sites-available/example.com
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 и перезапустите:

sudo nano /opt/rybbit/.env
CLUSTER_WORKERS=1
cd /opt/rybbit && sudo ./restart.sh

Диск: главная ловушка

Обычные события занимают мало — ClickHouse сжимает их очень плотно. Всё меняют записи сессий: одна запись весит примерно в тысячу раз больше, чем событие о просмотре страницы, и хранится она в той же базе. Именно поэтому эта функция выключена по умолчанию — включайте её осознанно и следите за местом.

Что сколько занимает по факту (frog — пароль ClickHouse по умолчанию; обе базы слушают только сам сервер, наружу они не торчат):

frog — пароль ClickHouse по умолчанию из docker-compose
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".

Коротко: план с нуля

  1. VPS от 2 ГБ RAM на Ubuntu 24.04, Docker через get.docker.com, на 2 ГБ — файл подкачки
  2. A-запись stats на IP сервера, проверить через dig +short
  3. sudo ./setup.sh stats.example.com — шесть контейнеров и HTTPS автоматом
  4. Создать аккаунт на /signup, затем DISABLE_SIGNUP=true и ./restart.sh
  5. Add Site → скопировать тег → в <head> сайта или в WPCode
  6. Проверить, что визит виден в панели
  7. Проксировать счётчик через свой домен, чтобы не терять визиты
  8. Записи сессий включать осознанно и следить за диском

Под Rybbit нужен VPS от 2 ГБ RAM — подойдёт и тот, на котором уже работает сайт

VPS для сайта и WordPress →