Публичные сервисы сокращения ссылок вроде Bitly, TinyURL или Clck привычны большинству маркетологов и разработчиков, но несут скрытые системные риски для бизнеса и IT-инфраструктуры. Бесплатные тарифы накладывают жесткие лимиты на количество ссылок, в любой момент могут заблокировать редирект из-за ложных срабатываний антиспам-фильтров или начать показывать пользователям промежуточные страницы с рекламой. Подключение собственного брендированного домена (например, s.company.ru) в коммерческих SaaS-решениях обходится от 35 $ в месяц, а данные об IP-адресах, реферерах и UTM-метках ваших клиентов утекают на зарубежные серверы.
Собственный self-hosted сервис коротких ссылок полностью решает эти проблемы. Развернув Shlink на недорогом VDS, вы получаете неограниченное количество ссылок и кликов, микросекундную скорость отдачи редиректов, удобную панель управления Shlink Web Client, встроенный генератор QR-кодов и детальную аналитику переходов по странам, браузерам и кампаниям на собственном домене.
💡 Почему именно Shlink?
Shlink — это признанный отраслевой стандарт среди open-source сокращателей ссылок (свыше 10 000 звёзд на GitHub). В отличие от устаревших скриптов эпохи PHP 5 (вроде YOURLS), ядро Shlink работает на базе асинхронного рантайма RoadRunner/Swoole. Оно не порождает тяжелые процессы на каждый входящий HTTP-запрос, благодаря чему сервер обрабатывает тысячи перенаправлений в секунду при потреблении всего 40–80 МБ оперативной памяти.
1. Преимущества собственного сервиса коротких ссылок перед публичными SaaS
Для вебмастера, разработчика или владельца интернет-проекта собственный сокращатель ссылок — это не просто эстетика коротких адресов в соцсетях и SMS, а стратегический инструмент контроля трафика:
- Полный контроль над доменом: ваши ссылки никогда не перестанут открываться из-за смены тарифных планов провайдера или блокировки аккаунта.
- Безопасность и конфиденциальность: аналитика переходов, включая IP-клиентов и параметры запросов, хранится строго в вашей базе данных на VDS.
- Мультидоменность: один экземпляр Shlink способен обслуживать десятки разных коротких доменов для разных брендов и проектов.
- Гибкое управление HTTP-статусами: переключение между редиректами 302/307 (для точной аналитики каждого клика) и 301 (для постоянной передачи веса ссылки в поисковиках).
- Экономия бюджета: Shlink вместе с базой данных потребляет минимум ресурсов и комфортно работает на базовом тарифе VDS за 200–400 ₽ в месяц.
| Критерий | Публичные сервисы (Bitly / TinyURL) | Собственный Shlink на VDS |
|---|---|---|
| Кастомный домен | От 35 $/мес за подписку | Бесплатно, без ограничений по числу доменов |
| Лимит переходов | Жесткие квоты (от 500 до 1500 кликов на Free) | Безлимитно (ограничено только каналом VDS) |
| Приватность аналитики | Данные собираются и монетизируются платформой | Изолированная локальная база MariaDB/PostgreSQL |
| API и автоматизация | Rate-limits, платные ключи | Полнофункциональный REST API без ограничений |
2. Архитектура Shlink v4: компоненты и принцип работы
Стек сервиса состоит из трех легковесных компонентов, изолированных в Docker-сети:
- Контейнер Shlink (API & Redirect Engine): основное ядро на образе
shlinkio/shlink:stable. Принимает входящие HTTP-запросы, резолвит короткий slug в базе данных, регистрирует факт визита (User-Agent, реферер, геолокацию по GeoLite2) и моментально возвращает заголовокLocationс целевым URL. Внутри контейнера сервис слушает порт8080. - Контейнер базы данных (MariaDB или PostgreSQL): хранит таблицы ссылок, доменов, тегов, API-ключей и логов посещений. Для защиты от сетевого сканирования порт СУБД изолируется внутри Docker и не выставляется в глобальный интернет.
- Контейнер Shlink Web Client: официальный веб-интерфейс на образе
shlinkio/shlink-web-client:stable. Это Single Page Application (SPA), которое связывается с ядром через REST API по защищенному HTTPS-соединению. Слушает внутренний порт8080.
3. Подготовка домена и настройка DNS-записей
Перед развертыванием контейнеров необходимо делегировать доменные имена на IP-адрес вашего сервера. Для чистоты архитектуры рекомендуется использовать короткий поддомен для редиректов (например, s.mybrand.ru) и отдельный адрес для веб-панели управления (например, links-admin.mybrand.ru).
В панели управления DNS у вашего регистратора или Cloudflare добавьте две ресурсные записи:
s.mybrand.ru. IN A 203.0.113.10
links-admin.mybrand.ru. IN A 203.0.113.10
Замените 203.0.113.10 на реальный публичный IPv4-адрес вашего VDS. После внесения изменений проверьте распространение ресурсных записей по мировым DNS-узлам с помощью бесплатной утилиты DNS Lookup на SysKit, чтобы убедиться в отсутствии кэширования старых IP-адресов. Также рекомендуем проверить доступность стандартных портов через онлайн сканер портов.
4. Готовый production-манифест Docker Compose и файл .env
Для обеспечения production-безопасности категорически не рекомендуется хардкодить пароли базы данных и API-токены прямо в манифесте docker-compose.yml. Все чувствительные переменные выносятся в изолированный файл .env с ограниченными правами доступа.
Создайте рабочую директорию проекта на сервере:
sudo mkdir -p /opt/shlink && cd /opt/shlink
Сгенерируйте криптостойкие пароли с помощью генератора безопасных паролей SysKit либо встроенной утилиты OpenSSL:
openssl rand -hex 16
Создайте файл /opt/shlink/.env со следующим содержимым:
# Домен сервиса коротких ссылок
DEFAULT_DOMAIN=s.mybrand.ru
# Учетные данные MariaDB
DB_NAME=shlink
DB_USER=shlink_user
DB_PASSWORD=generated_super_secret_db_pass_123
DB_ROOT_PASSWORD=generated_root_super_pass_456
# Инициализирующий API-ключ для первого входа
INITIAL_API_KEY=shlink_secret_init_key_789abc
# Бесплатный лицензионный ключ MaxMind для геолокации кликов
GEOLITE_LICENSE_KEY=your_maxmind_license_key_here
Ограничьте права на файл с секретами, чтобы его мог читать только суперпользователь:
sudo chmod 600 /opt/shlink/.env
Теперь создайте файл манифеста docker-compose.yml, использующий эти переменные и обязательную директиву TRUSTED_PROXIES:
services:
shlink_db:
image: mariadb:11
container_name: shlink_db
restart: unless-stopped
mem_limit: 512m
cpus: 0.50
environment:
MARIADB_DATABASE: ${DB_NAME}
MARIADB_USER: ${DB_USER}
MARIADB_PASSWORD: ${DB_PASSWORD}
MARIADB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
volumes:
- shlink_db_data:/var/lib/mysql
networks:
- shlink_net
shlink:
image: shlinkio/shlink:stable
container_name: shlink_app
restart: unless-stopped
mem_limit: 384m
cpus: 0.75
depends_on:
- shlink_db
environment:
DEFAULT_DOMAIN: ${DEFAULT_DOMAIN}
IS_HTTPS_ENABLED: "true"
DB_DRIVER: maria
DB_HOST: shlink_db
DB_NAME: ${DB_NAME}
DB_USER: ${DB_USER}
DB_PASSWORD: ${DB_PASSWORD}
INITIAL_API_KEY: ${INITIAL_API_KEY}
TRUSTED_PROXIES: "1"
REDIRECT_STATUS_CODE: "302"
REDIRECT_CACHE_LIFETIME: "30"
TIMEZONE: "Europe/Moscow"
GEOLITE_LICENSE_KEY: ${GEOLITE_LICENSE_KEY:-}
ports:
- "127.0.0.1:8080:8080"
networks:
- shlink_net
shlink_web:
image: shlinkio/shlink-web-client:stable
container_name: shlink_web
restart: unless-stopped
mem_limit: 128m
cpus: 0.25
ports:
- "127.0.0.1:8081:8080"
networks:
- shlink_net
volumes:
shlink_db_data:
networks:
shlink_net:
driver: bridge
⚠️ Важность директивы TRUSTED_PROXIES и изоляции портов
В Shlink v4 для повышения безопасности отключено автоматическое доверие заголовкам обратного прокси. Параметр TRUSTED_PROXIES: "1" сообщает ядру, что прямо перед ним находится ровно один доверенный Reverse Proxy (Caddy или Nginx). Без этой настройки Shlink проигнорирует заголовок X-Forwarded-For и запишет IP-адрес локального прокси 127.0.0.1 вместо реального IP посетителя, полностью сломав геолокацию кликов.
Кроме того, порты привязаны строго к 127.0.0.1, что защищает от обхода UFW через Docker iptables. Подробнее о сетевой защите читайте в руководстве по защите портов Docker от обхода UFW.
5. Настройка обратного прокси (Caddy 2 и Nginx) с правильными заголовками и SSL
Ядро Shlink и веб-панель не должны обрабатывать TLS напрямую. Терминацию SSL, сжатие трафика и проброс реальных IP-адресов клиентов выполняет внешний веб-сервер. Ниже представлены два проверенных варианта настройки.
Вариант 1. Современный веб-сервер Caddy 2 (Рекомендуется)
Веб-сервер Caddy автоматически получает, верифицирует и продлевает SSL-сертификаты Let's Encrypt без использования Certbot. Для полной совместимости с асинхронным ядром Shlink явно пробросим заголовки X-Real-IP и X-Forwarded-Host. Добавьте в файл /etc/caddy/Caddyfile следующую конфигурацию:
s.mybrand.ru {
encode zstd gzip
reverse_proxy 127.0.0.1:8080 {
header_up X-Real-IP {remote_host}
header_up X-Forwarded-Host {host}
}
}
links-admin.mybrand.ru {
encode zstd gzip
reverse_proxy 127.0.0.1:8081
}
Перечитайте конфигурацию: sudo systemctl reload caddy. Подробнее об особенностях архитектуры Caddy читайте в руководстве по настройке веб-сервера Caddy 2 с авто-SSL для Docker.
Вариант 2. Классический Nginx с Certbot
Если на вашем сервере используется Nginx, создайте виртуальный хост в каталоге /etc/nginx/sites-available/. Для сервиса редиректов s.mybrand.ru обязательно передайте полный комплект прокси-заголовков, включая X-Forwarded-Host для поддержки мультидоменности:
server {
listen 80;
server_name s.mybrand.ru;
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;
proxy_set_header X-Forwarded-Host $host;
proxy_read_timeout 60s;
}
}
Аналогично создается блок для админ-панели links-admin.mybrand.ru с проксированием на http://127.0.0.1:8081. После проверки синтаксиса (sudo nginx -t) и перезапуска службы выпустите бесплатные сертификаты с автоматической настройкой HTTPS-редиректа:
sudo certbot --nginx --redirect -d s.mybrand.ru -d links-admin.mybrand.ru
После активации проверьте корректность цепочки TLS-сертификатов через онлайн SSL-чекер SysKit. Если требуется усилить безопасность заголовков, используйте готовый pSEO-шаблон конфигурации безопасных заголовков Nginx.
6. Запуск сервиса, настройка GeoLite2 и подключение админки
Чтобы Shlink мог строить интерактивную карту кликов с детализацией по странам и городам, требуется бесплатная база данных MaxMind GeoLite2:
- Зарегистрируйтесь на официальном сайте MaxMind GeoLite2.
- В личном кабинете перейдите в раздел Manage License Keys → Generate new license key.
- Скопируйте ключ и вставьте его в значение переменной
GEOLITE_LICENSE_KEYв файле/opt/shlink/.env. При первом запуске Shlink автоматически скачает и развернет актуальную базу городов.
Запустите стек Docker Compose в фоновом режиме:
docker compose up -d
Проверьте статус контейнеров: docker compose ps. Все три службы (shlink_app, shlink_db, shlink_web) должны иметь статус Up. Если вам понадобятся дополнительные API-ключи (например, с ограничением только на определенный домен или автора), их можно выпустить через встроенную CLI-утилиту контейнера:
docker compose exec shlink bin/cli api-key:generate
Консоль вернет сгенерированный токен. Теперь откройте в браузере адрес вашей панели управления https://links-admin.mybrand.ru:
- Нажмите кнопку Add a server.
- В поле Name укажите произвольное имя (например,
Production Shlink). - В поле URL введите полный адрес ядра с HTTPS:
https://s.mybrand.ru. - В поле API Key вставьте значение из переменной
INITIAL_API_KEYили сгенерированный токен. - Нажмите Create server.
Веб-клиент мгновенно подключится к API ядра и откроет дашборд. Вся конфигурация сохраняется в локальном хранилище браузера (LocalStorage), поэтому ваши ключи не передаются третьим лицам.
7. Коды редиректа 301, 302, 307, защита аналитики и нюансы CDN
Один из самых частых вопросов при настройке собственного сокращателя — какой код HTTP-редиректа выбрать. Разница между ними критична для учета статистики:
- 301 (Moved Permanently): постоянный редирект. Браузер пользователя сохраняет соответствие «короткая ссылка → целевая страница» в своем локальном кэше. При повторных переходах браузер даже не делает запрос к серверу Shlink, а сразу открывает конечный адрес. В результате повторные клики одного и того же посетителя не регистрируются в аналитике, а счетчик посещений занижается.
- 302 (Found) / 307 (Temporary Redirect): временное перенаправление. Браузер обязан обращаться к серверу Shlink при каждом клике. Сервер фиксирует дату, User-Agent, страну и UTM-метки, после чего моментально направляет посетителя дальше. Именно код
302задан по умолчанию в директивеREDIRECT_STATUS_CODE.
⚠️ Осторожно с кэшированием 302 на уровне CDN (Cloudflare)
Хотя браузеры не кэшируют редиректы 302/307 на постоянной основе, промежуточные прокси-сети и CDN (например, Cloudflare с активным правилом Cache Everything) могут закэшировать 302-ответ прямо на граничных серверах (Edge Cache). Если перед Shlink настроен Cloudflare, обязательно создайте Page Rule или Cache Rule для поддомена s.mybrand.ru/* с параметром Cache Level: Bypass, чтобы каждый клик доходил до вашего VDS.
В Shlink можно тонко настраивать каждую ссылку прямо в веб-интерфейсе:
- Кастомный slug: создание красивых адресов вида
s.mybrand.ru/autumn-saleвместо случайных символов. - Ограничение по времени и кликам: параметры
validUntilиmaxVisitsпозволяют автоматически отключить редирект после завершения маркетинговой акции. - Парольная защита: ссылка запрашивает пароль у посетителя перед выполнением перенаправления.
- Встроенный QR-код: автоматическая генерация векторных SVG и растровых PNG QR-кодов для полиграфии с возможностью настройки цвета и размера.
8. Миграция существующих ссылок: встроенный импорт из Bitly, YOURLS и CSV
Если вы ранее использовали другие сервисы или вели базу ссылок в таблицах Excel/Google Sheets, переносить их вручную не придется. Shlink содержит встроенный интерактивный мастер импорта short-url:import, который поддерживает автоматическую миграцию ссылок и истории переходов:
- Bitly: подключение через Generic Access Token из личного кабинета Bitly. Shlink выгружает все ссылки, созданные под вашим аккаунтом.
- YOURLS: прямое подключение к базе данных старого сервера YOURLS по реквизитам доступа.
- CSV: универсальный импорт из текстового файла со списком соответствий
longUrl,shortCode,titleиtags. - Kutt: перенос из популярного Node.js-сокращателя Kutt.
Для запуска миграции выполните интерактивную команду в консоли контейнера:
docker compose exec shlink bin/cli short-url:import
CLI-мастер предложит выбрать источник стрелками на клавиатуре, запросит API-токен или путь к файлу CSV, после чего безопасно импортирует ссылки в базу MariaDB. Процедура идемпотентна: повторный запуск импорта не создаст дубликатов уже перенесенных ссылок.
9. Проверка работы редиректов и траблшутинг
После создания первой ссылки обязательно протестируйте корректность отдачи HTTP-заголовков через терминал:
curl -ILs https://s.mybrand.ru/test | grep -E "HTTP|location"
В выводе должен присутствовать корректный статус перенаправления и целевой заголовок location:
HTTP/2 302
location: https://mybrand.ru/landing-page/?utm_source=shortlink
Для комплексного аудита цепочки перенаправлений воспользуйтесь онлайн-инструментом проверки редиректов SysKit. Он визуализирует всю цепочку прыжков, помогает выявить скрытые задержки и предотвратить циклические перенаправления. Подробнее о механике циклов читайте в статье о поиске причин циклических редиректов ERR_TOO_MANY_REDIRECTS.
Рекомендуемые VDS-провайдеры
Отказоустойчивые сервера с быстрыми NVMe и каналом до 1 Гбит/с
Timeweb Cloud — Быстрые NVMe VDS
Идеальная инфраструктура для self-hosted сервисов и Docker Compose: порты 80/443 открыты, мгновенный аптайм и сеть до 1 Гбит/с.
Selectel — Надежные облачные серверы
Дата-центры уровня Tier III в Москве и Санкт-Петербурге с почасовой оплатой, приватными подсетями и защитой от DDoS.
Beget — Простота и стабильность VDS
Удобная панель управления сервером, автоматические бэкапы и предустановленный стек Docker Compose в один клик.
Разверните свой сервис коротких ссылок за 15 минут
Для стабильной работы Shlink, MariaDB и веб-панели с гарантированным каналом связи выберите быстрый облачный сервер на скоростных NVMe-накопителях у надежных провайдеров.