MAATRIX / Блог / Shlink на Ubuntu 24.04: пошаговая установка

Shlink на Ubuntu 24.04: пошаговая установка

MAATRIX

Публичные сокращатели ссылок вроде bit.ly или clck.ru удобны, пока не встаёт вопрос доверия: они видят весь трафик, могут заблокировать домен без объяснений и не дают доступа к сырым данным о переходах. Shlink закрывает эту проблему — open-source URL-shortener с собственным REST API, детальной аналитикой (гео, устройства, реферер) и поддержкой кастомных доменов. Ниже — рабочая установка на Ubuntu 24.04 через Docker Compose, с MySQL, Nginx и SSL.

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

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

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

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

Shlink — PHP-приложение (ядро на Symfony), которое умеет: создавать короткие ссылки через API или CLI без веб-интерфейса из коробки; собирать статистику переходов (страна, город, браузер, ОС, referrer) без стороннего трекера; работать с несколькими доменами одновременно (multi-domain) — один сервер может обслуживать s.example.com и go.example2.ru; отдавать данные через REST API в JSON, что удобно для интеграции с ботами и CRM; ограничивать срок жизни ссылки, задавать кастомный слаг, добавлять теги.

Веб-интерфейса для конечного пользователя в самом Shlink нет — это осознанное решение проекта. Для UI ставится отдельное приложение Shlink Web Client, тоже open source и тоже в Docker. В этой статье фокус на backend — том, что реально нужно для интеграции по API. И ещё: Shlink не заменяет аналитику вроде Plausible или Matomo — метрики привязаны только к переходам по коротким ссылкам.

Требования к серверу

Shlink лёгкий, но запас под реальную нагрузку закладывать стоит:

РесурсМинимум (тест/личный проект)Рекомендуется (продакшн, десятки тысяч кликов/день)
CPU1 vCPU2 vCPU
RAM1 GB2-4 GB
Диск15 GB SSD25-40 GB SSD (под БД и логи)
ОСUbuntu 24.04 LTSUbuntu 24.04 LTS

Это ориентировочные цифры — реальная нагрузка зависит от числа доменов и частоты запросов к API. Для проекта с активным API-трафиком лучше сразу брать 2 vCPU и 4 GB RAM: миграция на больший тариф без даунтайма не проблема, но комфортнее заложить запас сразу.

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

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

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

Подготовка сервера и DNS

Подключаемся по SSH, обновляем систему и заводим пользователя без root-прав:

apt update && apt upgrade -y
adduser deploy
usermod -aG sudo deploy
su - deploy

Устанавливаем Docker и Docker Compose — Shlink официально распространяется как Docker-образ:

curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
newgrp docker
docker --version
docker compose version

Открываем нужные порты через UFW:

sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable

Подробный разбор правил — в статье про настройку файрвола UFW на Ubuntu 24.04.

Shlink рассчитан на работу через собственный короткий домен. Заведите A-запись, направленную на IP сервера:

Тип: A
Имя: s (или go, l — что удобнее)
Значение: <IP-вашего-сервера>
TTL: 3600

Проверить распространение записи можно так:

dig +short s.example.com

Если результат — IP сервера, DNS настроен верно. Разбор с нуля — в статье настройка домена и DNS на Ubuntu 24.04.

Docker Compose: Shlink + MySQL

Создаём рабочую директорию и файл docker-compose.yml:

mkdir -p ~/shlink && cd ~/shlink
nano docker-compose.yml

Содержимое файла:

services:
  shlink_db:
    image: mysql:8.0
    container_name: shlink_db
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
      MYSQL_DATABASE: shlink
      MYSQL_USER: shlink
      MYSQL_PASSWORD: ${DB_PASSWORD}
    volumes:
      - shlink_db_data:/var/lib/mysql
    networks:
      - shlink_net

  shlink:
    image: shlinkio/shlink:stable
    container_name: shlink
    restart: unless-stopped
    depends_on:
      - shlink_db
    environment:
      DEFAULT_DOMAIN: s.example.com
      IS_HTTPS_ENABLED: "true"
      DB_DRIVER: mysql
      DB_NAME: shlink
      DB_USER: shlink
      DB_PASSWORD: ${DB_PASSWORD}
      DB_HOST: shlink_db
      GEOLITE_LICENSE_KEY: ${GEOLITE_KEY}
    ports:
      - "127.0.0.1:8080:8080"
    volumes:
      - shlink_data:/etc/shlink/data
    networks:
      - shlink_net

volumes:
  shlink_db_data:
  shlink_data:

networks:
  shlink_net:
    driver: bridge

Пояснения: DEFAULT_DOMAIN — короткий домен для ссылок (замените на свой); IS_HTTPS_ENABLED: "true" — Shlink генерирует ссылки с https://, SSL при этом терминирует Nginx; GEOLITE_LICENSE_KEY — ключ базы MaxMind GeoLite2, без него не будет геолокации переходов (регистрация бесплатная); порт наружу не пробрасывается (127.0.0.1:8080) — доступ только через Nginx.

Секреты выносим в отдельный .env рядом с docker-compose.yml:

nano .env
DB_ROOT_PASSWORD=сложный_пароль_root
DB_PASSWORD=сложный_пароль_shlink
GEOLITE_KEY=ваш_ключ_maxmind

Права на файл с секретами:

chmod 600 .env

Запускаем:

docker compose up -d
docker compose logs -f shlink

В логах должно появиться сообщение о готовности и об успешном применении миграций БД. Первый запуск занимает чуть дольше — Shlink создаёт схему.

Nginx как reverse proxy и SSL через Certbot

Ставим Nginx и Certbot:

sudo apt install -y nginx certbot python3-certbot-nginx

Конфиг сайта:

sudo nano /etc/nginx/sites-available/shlink
server {
    listen 80;
    server_name s.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/shlink /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Выпускаем сертификат — Certbot сам допишет блок для 443-го порта и настроит редирект с 80-го:

sudo certbot --nginx -d s.example.com

Если на этом шаге проблемы — разбор частых причин есть в статье Nginx не применяет SSL, а общий принцип reverse proxy для Docker-приложений — в статье про Nginx как reverse proxy на Ubuntu 24.04. Автопродление сертификата Certbot настраивает сам через systemd timer, проверить можно командой sudo systemctl list-timers | grep certbot.

Создание коротких ссылок через API и CLI

У Shlink нет встроенного веб-интерфейса, поэтому базовый способ работы — CLI внутри контейнера или REST API. Сначала генерируем API-ключ (сохраните его сразу — второй раз посмотреть не получится, только выпустить новый):

docker compose exec shlink shlink api-key:generate

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

docker compose exec shlink shlink short-url:create "https://maatrix.io/blog/" --tags=blog,promo

Или через REST API (именно этот способ используют в интеграциях с ботами и скриптами):

curl -X POST "https://s.example.com/rest/v3/short-urls" \
  -H "X-Api-Key: ВАШ_API_КЛЮЧ" \
  -H "Content-Type: application/json" \
  -d '{"longUrl": "https://maatrix.io/blog/", "tags": ["blog"]}'

В ответе — JSON с полями shortUrl и shortCode. Полная спецификация всех методов (статистика, редактирование, срок жизни ссылки) — в OpenAPI-документации прямо в репозитории проекта; через тот же API работает и Shlink Web Client, если решите его поставить.

Резервное копирование

Данные живут в MySQL-контейнере и в docker-volume shlink_data (там же база GeoLite2) — бэкапить нужно оба. Дамп с ротацией по crontab (ежедневно, хранить неделю):

docker compose exec -T shlink_db mysqldump -u root -p"$DB_ROOT_PASSWORD" shlink \
  > ~/backups/shlink_$(date +%F).sql
find ~/backups -name "shlink_*.sql" -mtime +7 -delete

Для более серьёзного подхода — с шифрованием и версионированием — есть отдельная статья про установку BorgBackup на Ubuntu 24.04; её схему легко применить и к volume shlink_data.

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

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

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

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

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

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

Можно ли добавить несколько коротких доменов в один Shlink?

Да, это штатный сценарий (multi-domain) — домены добавляются через API-эндпоинт /rest/v3/domains, каждый новый домен нужно дополнительно прописать в Nginx отдельным server_name со своим SSL-сертификатом.

Нужен ли Shlink Web Client, если мне достаточно API?

Нет, backend самодостаточен: ссылки создаются через CLI или curl. Web Client нужен, только если хочется визуальную панель для нетехнических пользователей.

Контейнер shlink падает сразу после запуска — что делать?

Чаще всего MySQL ещё не успел подняться к моменту первого подключения. Проверьте docker compose logs shlink_db — с restart: unless-stopped контейнер переподключится сам.

Можно ли использовать PostgreSQL вместо MySQL?

Да, поддерживаются PostgreSQL, MariaDB и SQLite — достаточно поменять DB_DRIVER и сервис БД в docker-compose.

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

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

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