При аренде виртуального сервера (VDS) хостинг-провайдеры указывают предельную пропускную способность сетевого интерфейса: обычно «до 100 Мбит/с» или «порт 1 Гбит/с». Однако физический сетевой адаптер гипервизора разделяется между десятками изолированных виртуальных машин. В часы пиковых нагрузок из-за эффекта «шумных соседей» (noisy neighbors) и перегрузки межоператорских стыков реальная скорость передачи данных может существенно снижаться, а задержка (RTT) и джиттер — возрастать, что напрямую отражается на времени отклика сайтов и скорости синхронизации бэкапов.
Разовый ручной запуск консольных тестов фиксирует лишь состояние канала в конкретную секунду. Для систематического контроля качества сетевого подключения необходим автономный инструмент мониторинга. Оптимальным выбором является Speedtest Tracker (разработчик Alex Justesen) — открытое self-hosted веб-приложение, использующее официальный бинарный движок Ookla Speedtest CLI, формирующее графики сетевых параметров и отправляющее алерты в Telegram при отклонении метрик от установленного соглашения об уровне обслуживания (SLA). Документация проекта доступна на docs.speedtest-tracker.dev.
1. Зачем VDS регулярный замер скорости и как провайдеры лукавят с SLA
В регламентах обслуживания большинства провайдеров пропускная способность заявляется по модели Best Effort («наилучшая возможная попытка»). На фактические показатели канала влияют объективные факторы:
- Вечерняя деградация пиринга: в периоды пикового потребления трафика (19:00–23:00) магистральные каналы дата-центров испытывают повышенную нагрузку, из-за чего пропускная способность до удаленных автономных систем (AS) временно снижается.
- Политики управления полосой (Traffic Shaping): на ряде тарифов при превышении установленных объемов суммарного трафика в месяц ширина канала программно ограничивается до базовых значений.
- Асимметрия каналов: входящая скорость скачивания (Download) и исходящая скорость отдачи (Upload), критически важная для серверов веб-приложений и баз данных, могут заметно отличаться из-за конфигурации сетевых маршрутов провайдера.
- Сетевой джиттер и потеря пакетов (Packet Loss): даже на широком канале потеря доли процента пакетов приводит к деградации алгоритмов контроля перегрузок TCP (BBR, Cubic), увеличивая время установления соединений.
Перед запуском тестов рекомендуется определить вышестоящую автономную систему (AS) и сетевой шлюз сервера с помощью инструментов Узнать мой IP-адрес онлайн и Проверка хостинга и дата-центра сайта.
💡 Совет инженера по объему тестового трафика
При замере скорости на порту 1 Гбит/с многопоточный синтетический тест Ookla за 15–20 секунд прокачивает в обе стороны порядка 1–2 ГБ сетевых данных. Запуск тестов каждые 10–15 минут создаст существенную фоновую нагрузку и израсходует до 3–5 ТБ трафика за месяц. Оптимальная периодичность замеров для VDS — каждые 4–6 часов (или контрольные замеры в ключевые периоды суток).
2. Архитектура Speedtest Tracker: движок на Laravel, связка с Ookla CLI и хранилище SQLite
Архитектура Speedtest Tracker (актуальная стабильная ветка v1.15.x) построена на модульном стеке компонентов:
- Официальный бинарный клиент Ookla Speedtest CLI: в отличие от сторонних библиотек на Python (таких как
speedtest-cli), выполняющих замеры через HTTP-запросы в один поток и упирающихся в мощность одного ядра CPU уже на скоростях 200–300 Мбит/с, нативный бинарник Ookla поддерживает многопоточный сокетный обмен данными и вычисляет задержку под нагрузкой (Loaded Ping / Bufferbloat). - Бэкенд на Laravel и Filament: интерфейс панели построен на базе Laravel и реактивного компонента Livewire, обновляющего метрики на дашборде через периодические асинхронные HTTP-запросы.
- Хранилище SQLite по умолчанию: метрики, журнал инцидентов и системные настройки сохраняются в локальном файле
/config/database.sqlite. Для мониторинга отдельного сервера этого полностью достаточно: база не требует выделенного процесса СУБД и потребляет минимум оперативной памяти. - Контейнеризация от LinuxServer.io: официальный образ linuxserver/speedtest-tracker поддерживает платформы x86-64 (amd64) и ARM64, управляется супервизором s6-overlay и поддерживает сопоставление прав пользователей через переменные
PUIDиPGID.
| Инструмент тестирования | Точность замера канала | История и графики | Потребление RAM | Автоматизация и алерты |
|---|---|---|---|---|
| Speedtest Tracker (Ookla CLI) | Высокая (официальный многопоточный сокетный алгоритм Ookla) | Да (интерактивный веб-дашборд) | ~100–180 МБ |
Telegram, Discord, Webhook, расписание cron |
| Python speedtest-cli | Низкая (упирается в 1 поток CPU на 250+ Мбит/с, возможны искажения) | Нет (только вывод в stdout) | ~30 МБ (в момент теста) |
Требует самописных скриптов в bash/cron |
| iPerf3 | Синтетическая (прямой TCP/UDP тест между узлами с iPerf3-сервером) | Нет (консольные утилиты) | ~15 МБ |
Требует наличия второго выделенного сервера iPerf |
3. Развертывание Speedtest Tracker в Docker Compose на VDS
Для развертывания сервиса создадим выделенный каталог в файловой системе сервера (например, /opt/speedtest-tracker). Каталог для хранения конфигурации и базы данных SQLite должен принадлежать пользователю, под UID которого будет работать процесс внутри контейнера (обычно UID 1000).
# Создаем рабочую директорию проекта и каталог для данных
sudo mkdir -p /opt/speedtest-tracker/data
cd /opt/speedtest-tracker
# Назначаем права пользователя UID 1000 на каталог данных
sudo chown -R 1000:1000 /opt/speedtest-tracker/data
Перед составлением манифеста обязательно сгенерируем ключ шифрования приложения APP_KEY. Начиная с версии v0.20 и во всех последующих релизах v1.x проект отказался от неявной автоматической генерации ключа при старте: документация разработчика требует явно передавать сгенерированный 32-байтный base64-ключ в переменных окружения.
# Генерируем обязательный 32-байтный ключ шифрования в формате Laravel
echo "base64:$(openssl rand -base64 32)"
Скопируйте вывод команды (строку вида base64:AbCdEf12345...=) для подстановки в переменную APP_KEY.
Создадим конфигурационный манифест docker-compose.yml. Обратите особое внимание на директиву публикации портов: мы привязываем контейнер строго к локальному адресу 127.0.0.1:8080:80.
⚠️ Важное предупреждение по безопасности сетевых портов
Никогда не указывайте в ports строку "8080:80" или "80:80" без явного указания IP-адреса хоста! Из-за архитектурных особенностей подсистемы iptables Docker публикует порты напрямую через цепочку PREROUTING в обход стандартного фаервола UFW. Подробнее о механизме этой уязвимости и способах ее устранения читайте в нашем разборе Docker обходит UFW на Linux: закрытие внутренних портов контейнеров. Привязка к 127.0.0.1 гарантирует, что веб-панель будет доступна только через локальный обратный прокси.
Создадим файл docker-compose.yml со следующим содержимым:
services:
speedtest-tracker:
image: lscr.io/linuxserver/speedtest-tracker:latest
container_name: speedtest-tracker
restart: unless-stopped
ports:
# Привязываем порт строго к локальной петле loopback хоста
- "127.0.0.1:8080:80"
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/Moscow
# Обязательный ключ шифрования (сгенерирован через openssl)
- APP_KEY=base64:ВАШ_СГЕНЕРИРОВАННЫЙ_КЛЮЧ=
- APP_URL=https://speedtest.example.com
- DB_CONNECTION=sqlite
# Рекомендуемое расписание (каждые 4 часа), по умолчанию переменная пустая
- SPEEDTEST_SCHEDULE=0 */4 * * *
# Автоматическое удаление замеров старше 90 дней для экономии места
- PRUNE_RESULTS_OLDER_THAN=90
- DISPLAY_TIMEZONE=Europe/Moscow
volumes:
- ./data:/config
# Лимиты ресурсов: deploy.resources — спецификация Compose v2, mem_limit — fallback для Compose v1
deploy:
resources:
limits:
cpus: "1.50"
memory: 512M
reservations:
memory: 128M
mem_limit: 512m
Запускаем сервис в фоновом режиме и контролируем журнал первого старта:
# Запуск контейнера в фоне
docker compose up -d
# Просмотр логов инициализации и применения миграций SQLite
docker compose logs -f speedtest-tracker
При первом запуске скрипт инициализации применит структуру таблиц в SQLite и создаст стандартную учетную запись администратора согласно документации образа:
- Логин (Email):
admin@example.com - Пароль по умолчанию:
password
💡 Совет инженера
Сразу после первого входа в веб-панель перейдите в профиль администратора (Settings → Profile) и немедленно смените стандартный пароль и адрес электронной почты на надежные. Для создания стойких паролей используйте инструмент Генератор сложных паролей онлайн.
4. Настройка расписания cron, выбор эталонных серверов и запуск первого теста
По умолчанию официальный клиент Ookla выбирает сервер тестирования динамически на основе наименьшей задержки (RTT). Однако в режиме долговременного мониторинга автоматический выбор узла снижает сопоставимость данных: в один запуск тест пойдет через сервер одного провайдера, в следующий — через другой узел с иной топологией каналов. На графиках появятся скачки, обусловленные не качеством вашего VDS, а спецификой конкретного удаленного хоста.
Для получения воспроизводимой исторической картины рекомендуется зафиксировать идентификаторы проверенных целевых серверов. Получить список доступных узлов можно официальной консольной командой приложения:
# Официальная artisan-команда Speedtest Tracker для вывода списка ближайших серверов
docker exec -it speedtest-tracker php artisan app:ookla-list-servers
Команда выведет список доступных серверов с их уникальными номерами (ID), наименованиями операторов связи и географическими локациями. Также прямой опрос узлов можно выполнить через низкоуровневый бинарник: docker exec -it speedtest-tracker speedtest --servers.
Выберите 2–3 стабильных узла ключевых магистральных операторов региона. В панели управления перейдите в подраздел Settings → Speedtest:
- Speedtest Schedule: в официальном образе переменная
SPEEDTEST_SCHEDULEизначально не заполнена (автоматические тесты отключены). Рекомендуется задать расписание в cron-формате, например0 */4 * * *(запуск каждые 4 часа) или0 3,9,15,21 * * *. - Speedtest Servers: укажите числовые идентификаторы выбранных узлов через запятую (например,
2113,3682). Сервис будет поочередно использовать именно эти фиксированные точки. - Thresholds (Пороговые значения SLA): настройте минимальные ожидаемые параметры пропускной способности. Например, для тарифа со скоростью 300–500 Мбит/с можно задать предупреждение при падении Download ниже 200 Мбит/с или росте пинга выше 40 мс.
Для проверки конфигурации нажмите кнопку «Queue Speedtest» в правом верхнем углу дашборда. Фоновый воркер запустит процесс замера, и в течение минуты в интерфейсе появятся графики скорости, джиттера и пинга под нагрузкой.
5. Требования к VDS для сетевого мониторинга и выбор надежного провайдера
Контейнер Speedtest Tracker в режиме ожидания потребляет всего 100–180 МБ оперативной памяти. Однако синтетический сетевой бенчмарк предъявляет специфические требования к аппаратным ресурсам ноды:
- Производительность CPU на ядро: обработка многопоточного трафика на скорости около 1 Гбит/с создает кратковременную пиковую нагрузку на процессор. На старых процессорах с низкой базовой частотой узким местом может стать производительность виртуального ядра (CPU throttle), а не сам сетевой интерфейс. Для точных замеров предпочтительны современные процессоры с частотой от 3.0 ГГц.
- Прозрачные условия тарификации трафика: важно заранее изучить условия договора хостинга — предоставляет ли провайдер честный нелимитированный канал или применяет ограничения после определенного порога переданных терабайт.
- Дисковая подсистема NVMe: журналирование SQLite требует минимального времени отклика I/O, чтобы исключить задержки при параллельной записи результатов.
Для развертывания сетевых сервисов и стабильного мониторинга подходят проверенные облачные провайдеры с прозрачной сетевой инфраструктурой:
Рекомендуемые VDS-провайдеры
Отказоустойчивые сервера с быстрыми NVMe и каналом до 1 Гбит/с
Timeweb Cloud — Быстрые NVMe VDS
Высокочастотные процессоры 3.3+ ГГц для быстрой отдачи веб-страниц, NVMe-диски и надежный сетевой канал 1 Гбит/с.
Selectel — Надежные облачные серверы
Отказоустойчивая инфраструктура в сертифицированных дата-центрах Tier III, гарантированные ресурсы vCPU и удобное управление сетью.
Beget — Простота для веб-разработчиков
Мгновенное развертывание Nginx и сайтов в 1 клик, интуитивная панель управления сервером, бесплатные автоматические бэкапы и отзывчивая поддержка 24/7.
6. Настройка Telegram-бота для мгновенных алертов о деградации канала
Автоматический сбор метрик эффективен тогда, когда администратор получает мгновенное уведомление об инциденте без необходимости вручную проверять графики в браузере. Speedtest Tracker поддерживает отправку оповещений через почту, Discord, Webhook и мессенджер Telegram согласно официальному руководству по настройке уведомлений.
Для интеграции Telegram-оповещений выполните следующие шаги:
- Откройте бота
@BotFatherв Telegram и выполните команду/newbot. Задайте имя и юзернейм нового бота, после чего сохраните полученный токен доступа (HTTP API Token). - Узнайте свой персональный ID пользователя или ID рабочей группы с помощью сервисного бота
@userinfobot. - В панели управления Speedtest Tracker откройте раздел Settings → Notifications.
- В блоке Telegram активируйте переключатель и укажите:
- Bot Token: токен созданного бота;
- Chat ID: ваш числовой идентификатор чата.
- В секции Notification Events выберите необходимые события:
- Speedtest Completed — отправка отчета после каждого замера (лучше оставить отключенным при регулярном тестировании, чтобы избежать избыточных сообщений);
- Speedtest Threshold Breached — рекомендуется включить (уведомление отправляется при падении скорости или скачке пинга ниже заданного порога SLA);
- Speedtest Failed — рекомендуется включить (оповещение о сетевой аварии, когда тест не удалось выполнить из-за сбоя DNS или недоступности серверов).
- Нажмите кнопку «Test Notification» для отправки контрольного сообщения и проверки доставки.
7. Безопасная публикация через Nginx Reverse Proxy с авто-SSL и HTTP Basic Auth
Поскольку порт контейнера изолирован на локальном интерфейсе 127.0.0.1:8080, настроим обратный прокси Nginx на хосте с TLS-шифрованием Let's Encrypt и дополнительной базовой аутентификацией (HTTP Basic Auth).
Дашборд Speedtest Tracker построен на базе Laravel Filament и библиотеки Livewire, которая периодически опрашивает бэкенд через асинхронные HTTP-запросы. Чтобы веб-сервер стабильно поддерживал постоянные HTTP/1.1 соединения без разрывов при длительном выполнении теста, настроим стандартные прокси-заголовки.
Шаг 1: Создаем первичную HTTP-конфигурацию /etc/nginx/sites-available/speedtest.conf для валидации доменного имени:
server {
listen 80;
server_name speedtest.example.com;
location / {
proxy_pass http://127.0.0.1:8080;
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/speedtest.conf /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
Шаг 2: Выпускаем бесплатный TLS-сертификат Let's Encrypt с автоматическим перенаправлением на защищенный протокол HTTPS:
# Запуск certbot с плагином nginx и флагом принудительного редиректа
sudo certbot --nginx -d speedtest.example.com --redirect
Шаг 3: Создаем файл паролей для директивы auth_basic, чтобы полностью закрыть панель от автоматизированных сканеров и ботов:
# Устанавливаем apache2-utils при необходимости
sudo apt update && sudo apt install -y apache2-utils
# Создаем файл учетных записей для доступа к панели
sudo htpasswd -c /etc/nginx/.speedtest_htpasswd sysadmin
Итоговая боевая конфигурация виртуального хоста в /etc/nginx/sites-available/speedtest.conf с современным синтаксисом Nginx (директива http2 on;):
server {
listen 80;
server_name speedtest.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
http2 on;
server_name speedtest.example.com;
ssl_certificate /etc/letsencrypt/live/speedtest.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/speedtest.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
# Базовая HTTP-авторизация на уровне веб-сервера
auth_basic "Speedtest Tracker Protected Area";
auth_basic_user_file /etc/nginx/.speedtest_htpasswd;
location / {
proxy_pass http://127.0.0.1:8080;
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;
# Поддержка постоянных соединений HTTP/1.1 для Livewire
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_connect_timeout 60s;
proxy_read_timeout 120s;
proxy_send_timeout 120s;
}
}
Применяем обновленные настройки:
sudo nginx -t && sudo systemctl reload nginx
Проверить корректность цепочки сертификатов и протоколов безопасности TLS можно с помощью инструмента Проверка SSL-сертификата онлайн. Для генерации других конфигураций Nginx с защитными заголовками воспользуйтесь нашим генератором Конфигуратор Nginx Reverse Proxy.
Также обязательно проверьте открытые порты сервера через Онлайн сканер портов, чтобы убедиться, что внутренний порт 8080 закрыт от внешнего мира, а доступны только стандартные порты 80 и 443.
8. Диагностика, ротация истории тестов и защита диска от переполнения
При регулярном мониторинге на протяжении нескольких месяцев база данных накапливает тысячи записей. Чтобы файл SQLite не разрастался неограниченно, в приложении предусмотрен механизм ротации.
💡 Автоматическая очистка устаревших замеров через Laravel Prunable
Модель результатов Result реализует стандартный трейт Illuminate\Database\Eloquent\Prunable. Встроенный планировщик задач Laravel автоматически выполняет команду model:prune раз в сутки, если переменная PRUNE_RESULTS_OLDER_THAN больше нуля (значение 0 отключает ротацию).
Для принудительного запуска очистки устаревших записей по настроенному порогу и создания резервной копии базы выполните:
# Ручной запуск штатной команды ротации Prunable-моделей в контейнере
docker exec -it speedtest-tracker php artisan model:prune
# Создание консистентного снапшота базы данных SQLite через встроенную утилиту
sqlite3 /opt/speedtest-tracker/data/database.sqlite ".backup '/opt/speedtest-tracker/data/backup_$(date +%F).sqlite'"
9. Чек-лист проверки и ввода в эксплуатацию
📋 Чек-лист готовности сетевого мониторинга
- Сгенерирован и прописан обязательный ключ шифрования
APP_KEY. - Порт контейнера привязан строго к петле
127.0.0.1:8080, прямой доступ из интернета заблокирован. - Стандартный пароль учетной записи
admin@example.comзаменен на надежный в профиле пользователя. - Серверы Ookla определены через
php artisan app:ookla-list-serversи зафиксированы в конфигурации. - Настроены пороговые значения скорости и пинга (SLA Thresholds).
- Telegram-бот проверен тестовым оповещением (Test Notification).
- Настроен Nginx reverse proxy с HTTPS (
http2 on;) и базовой аутентификациейauth_basic.
Готовы развернуть независимый сетевой мониторинг на своем VDS?
Выберите надежный облачный сервер с проверенным гигабитным портом, NVMe-накопителями и стабильным пирингом у ведущих провайдеров, чтобы контролировать качество связи круглосуточно.