MAATRIX / Блог / Как установить и настроить Shlink на VPS

Как установить и настроить Shlink на VPS

MAATRIX

Если вы устали от того, что бесплатные сокращатели ссылок режут статистику, показывают чужую рекламу на редиректе или могут в любой момент заблокировать домен, решение простое — поднять свой. Shlink делает то же самое, что bit.ly или clck.ru, но данные, домен и API-ключи остаются полностью у вас. Ниже — рабочая установка на VPS через Docker Compose, с базой, кешем, доменом и SSL.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Что такое Shlink и зачем он нужен

Shlink — открытый URL-сокращатель на PHP, который можно развернуть на своём сервере и использовать как полноценный сервис: с REST API, CLI-утилитой и отдельным веб-клиентом для управления ссылками и просмотра статистики. В отличие от облачных сокращателей у него нет ограничений по количеству ссылок, нет чужой рекламы на промежуточной странице редиректа и нет риска, что сервис однажды остановит работу вместе с вашей историей переходов.

Из практически полезного:

  • собственный короткий домен (например go.вашдомен.ru) вместо bit.ly/xxxxx;
  • кастомные слаги (go.site.ru/promo2026 вместо случайного набора символов);
  • REST API для автоматической генерации ссылок из ваших скриптов, CRM или рассылок;
  • аналитика переходов: страна, устройство, браузер, referrer — без передачи данных третьим лицам;
  • поддержка нескольких доменов на одной инсталляции.

Из ограничений — это не готовый SaaS: обновления, бэкапы и мониторинг лежат на вас. Дальше разберём весь путь от чистого VPS до рабочего сокращателя.

Требования к серверу и подготовка

Shlink — компактное PHP-приложение, поэтому ресурсов ему нужно немного. Для проекта с умеренной нагрузкой (десятки-сотни редиректов в минуту) достаточно небольшого VPS:

ПараметрМинимумКомфортно
CPU1 vCPU2 vCPU
RAM1 GB (со swap)2 GB
Диск15 GB SSD20-30 GB SSD
ОСUbuntu 24.04 LTSUbuntu 24.04 LTS

Понадобится:

  1. VPS с публичным IP и Ubuntu 24.04.
  2. Домен или поддомен, A-запись которого указывает на IP сервера (короткие ссылки будут выглядеть как go.вашдомен.ru/slug).
  3. Установленный Docker и Docker Compose plugin — если их ещё нет, разверните с нуля по инструкции Ubuntu 24.04: установка Docker с нуля.

Проверьте, что Docker установлен и запущен:

docker --version
docker compose version

Если оба вывели версии — можно переходить к установке.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Установка Shlink через Docker Compose

Создаём рабочую директорию и структуру для данных БД:

mkdir -p ~/shlink/data/mysql ~/shlink/data/shlink
cd ~/shlink

Файл .env с секретами (сгенерируйте свои пароли, не используйте примеры ниже):

cat > .env <<'EOF'
DB_ROOT_PASSWORD=замените_на_свой_пароль
DB_PASSWORD=замените_на_свой_пароль
INITIAL_API_KEY=замените_на_свой_ключ
GEOLITE_LICENSE_KEY=
EOF

GEOLITE_LICENSE_KEY можно оставить пустым — без него Shlink просто не будет определять страну посетителя в статистике. Бесплатный ключ MaxMind GeoLite2 получают на сайте maxmind.com после регистрации, это отдельный шаг, не обязательный для запуска.

Теперь docker-compose.yml:

services:
  shlink_db:
    image: mariadb:11
    container_name: shlink_db
    restart: unless-stopped
    environment:
      MARIADB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
      MARIADB_DATABASE: shlink
      MARIADB_USER: shlink
      MARIADB_PASSWORD: ${DB_PASSWORD}
    volumes:
      - ./data/mysql:/var/lib/mysql
    networks:
      - shlink_net

  shlink_redis:
    image: redis:7-alpine
    container_name: shlink_redis
    restart: unless-stopped
    networks:
      - shlink_net

  shlink:
    image: shlinkio/shlink:stable
    container_name: shlink
    restart: unless-stopped
    depends_on:
      - shlink_db
      - shlink_redis
    environment:
      DEFAULT_DOMAIN: go.вашдомен.ru
      IS_HTTPS_ENABLED: "true"
      DB_DRIVER: maria
      DB_NAME: shlink
      DB_USER: shlink
      DB_PASSWORD: ${DB_PASSWORD}
      DB_HOST: shlink_db
      REDIS_SERVERS: redis://shlink_redis:6379
      GEOLITE_LICENSE_KEY: ${GEOLITE_LICENSE_KEY}
      INITIAL_API_KEY: ${INITIAL_API_KEY}
    ports:
      - "127.0.0.1:8080:8080"
    volumes:
      - ./data/shlink:/etc/shlink/data
    networks:
      - shlink_net

  shlink_web_client:
    image: shlinkio/shlink-web-client:stable
    container_name: shlink_web_client
    restart: unless-stopped
    ports:
      - "127.0.0.1:8081:80"
    networks:
      - shlink_net

networks:
  shlink_net:
    driver: bridge

Замените go.вашдомен.ru на реальный поддомен. Оба сервиса — сам Shlink (порт 8080) и веб-клиент для управления (порт 8081) — слушают только 127.0.0.1, наружу их откроет nginx. Запускаем:

docker compose up -d
docker compose logs -f shlink

При первом старте контейнер сам накатит миграции базы данных — в логах должно появиться сообщение о готовности приложения. Если контейнер shlink перезапускается в цикле, почти всегда причина в неверном пароле к БД или в том, что shlink_db ещё не успел подняться — подождите 15-20 секунд и проверьте docker compose ps.

Домен, reverse proxy и SSL

Короткие ссылки и админку удобно развести по разным поддоменам: go.вашдомен.ru — публичный домен для редиректов и API, links.вашдомен.ru — панель управления, закрытая от посторонних. Оба должны указывать A-записью на IP вашего VPS.

Конфиг nginx (/etc/nginx/sites-available/shlink):

server {
    listen 80;
    server_name go.вашдомен.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;
    }
}

server {
    listen 80;
    server_name links.вашдомен.ru;

    # доступ только для доверенных IP, остальным — 403
    allow 203.0.113.10;
    deny all;

    location / {
        proxy_pass http://127.0.0.1:8081;
        proxy_set_header Host $host;
    }
}

Подробный разбор, как правильно поднять nginx именно как reverse proxy перед Docker-контейнерами, — в статье nginx как reverse proxy на VPS. Активируем конфиг и выпускаем сертификаты через certbot:

ln -s /etc/nginx/sites-available/shlink /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx

certbot --nginx -d go.вашдомен.ru -d links.вашдомен.ru

Полный процесс выпуска и автопродления Let's Encrypt сертификатов описан отдельно — см. установку Let's Encrypt SSL на VPS. Альтернатива nginx + certbot — Caddy, который получает сертификат автоматически при первом запуске, без ручных команд; если это ближе вашему стеку, посмотрите Caddy с авто-SSL на VPS.

Ограничение доступа к links.вашдомен.ru по IP или через Basic Auth — не опция, а необходимость: у shlink-web-client нет собственной системы логина, доступ к нему определяется только тем, кто знает API-ключ, введённый в браузере (ключ хранится в localStorage). Если панель открыта всему интернету, найти способ подобрать или перехватить ключ — вопрос времени.

Создание ссылок: API, CLI и веб-интерфейс

API-ключ уже задан переменной INITIAL_API_KEY в .env — при первом старте Shlink создаст его автоматически. Дополнительные ключи (например, отдельный для каждого сотрудника или интеграции) генерируются через CLI:

docker exec -it shlink shlink api-key:generate --name "маркетинг"

Создать короткую ссылку можно прямо из консоли:

docker exec -it shlink shlink short-url:create \
  --long-url="https://вашсайт.ru/landing/promo" \
  --custom-slug="promo2026"

Или через REST API — это удобно, если ссылки генерируются автоматически из вашего кода, CRM или почтовой рассылки:

curl -X POST https://go.вашдомен.ru/rest/v3/short-urls \
  -H "X-Api-Key: ваш_api_key" \
  -H "Content-Type: application/json" \
  -d '{
        "longUrl": "https://вашсайт.ru/landing/promo",
        "customSlug": "promo2026",
        "tags": ["email", "sept2026"]
      }'

В ответе API вернёт готовый короткий URL и метаданные ссылки. Для тех, кто не хочет работать с консолью, есть веб-клиент на links.вашдомен.ru: при первом входе он спросит адрес API-сервера (https://go.вашдомен.ru) и API-ключ, после чего покажет привычный интерфейс — список ссылок, создание новых, теги, QR-коды.

Аналитика, бэкапы и обновление

Каждый переход по короткой ссылке Shlink пишет в базу: время, IP (без хранения в открытом виде, только для геолокации), User-Agent, referrer. В веб-клиенте это превращается в графики по дням, топ стран (если подключен GeoLite2), устройствам и источникам трафика — без передачи данных в Google Analytics или другие внешние системы.

Резервное копирование — это, по сути, дамп базы данных и каталог data/shlink с локальными файлами приложения:

docker compose exec shlink_db mariadb-dump -u root -p shlink > shlink_backup_$(date +%F).sql
tar -czf shlink_data_$(date +%F).tar.gz ./data/shlink

Для регулярных автоматических бэкапов MySQL/MariaDB с ротацией и проверкой целостности имеет смысл сразу настроить cron-задачу по образцу из статьи бэкап MySQL на VPS — там же разобраны типичные ошибки вроде бэкапа «на живую» без --single-transaction.

Обновление до новой версии — обычный pull + пересоздание контейнеров, миграции БД Shlink накатывает сам при старте:

docker compose pull
docker compose up -d
docker compose logs -f shlink

Перед обновлением на мажорную версию (например, со 3.x на 4.x) стоит один раз прочитать changelog проекта на GitHub — там иногда встречаются breaking changes в переменных окружения или структуре API.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Обязательно ли использовать MySQL/MariaDB, или можно проще?

Нет, для небольшого личного проекта Shlink поддерживает SQLite — тогда не нужен отдельный контейнер с базой. Но при росте нагрузки или если вы захотите несколько инстансов Shlink за балансировщиком, MySQL/MariaDB или PostgreSQL надёжнее.

Нужен ли Redis обязательно?

Нет, это опциональный слой кеширования, который снижает нагрузку на базу при большом количестве переходов. Для старта можно запустить и без него, убрав переменную REDIS_SERVERS и сервис shlink_redis из compose-файла.

Как защитить админ-панель, если нет времени настраивать IP-ограничения?

Временный вариант — Basic Auth на уровне nginx (auth_basic + htpasswd) поверх location для links.вашдомен.ru. Это не заменяет полноценную защиту, но закрывает панель от случайных сканеров и ботов.

Можно ли перенести ссылки с bit.ly или другого сервиса?

Да, через API short-url:create с указанием customSlug, совпадающего со старым — если формат позволяет. Массовый перенос удобнее сделать скриптом, который читает экспорт старого сервиса и последовательно вызывает API.

Сколько ссылок и переходов выдержит такая установка?

Точных цифр не дам — многое зависит от того, включён ли Redis, ресурсов VPS и того, как настроена база. Для проекта с несколькими тысячами ссылок и умеренным трафиком описанной конфигурации (1-2 vCPU, 2 GB RAM) обычно хватает с запасом.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →