Установка xTunnel через Docker
Запустите туннель как контейнер — без установки бинарника в систему
Эта инструкция подойдёт, если вы хотите поднять туннель к сервису, который работает в контейнере или на сервере, — без установки бинарника в систему.
Для корректной работы достаточно выполнить первые 4 шага.
Остальные шаги — опциональные.

Образ: ghcr.io/xtnnl/xtunnel-agent (публичный, linux/amd64 и linux/arm64).
Проверьте, что Docker установлен
Выполните команду:
docker --version

Если команда не найдена — установите Docker Desktop (Windows / macOS) или Docker Engine (Linux).
Запустите туннель
Нужны две вещи: ключ лицензии из личного кабинета и адрес вашего сервиса.

docker run -d --name xtunnel \
  --restart=unless-stopped \
  -e XTUNNEL_LICENSE=ВАШ_КЛЮЧ \
  -e XTUNNEL_TARGET=http://host.docker.internal:8080 \
  ghcr.io/xtnnl/xtunnel-agent:v4.0.0

XTUNNEL_TARGET — куда агент будет отправлять пришедшие запросы:
  • сервис на той же машине, что и Docker → http://host.docker.internal:8080 (на Linux добавьте --add-host=host.docker.internal:host-gateway)
  • сервис в соседнем контейнере → http://имя-сервиса:8080 (см. шаг 5)
  • можно без схемы: host:8080

💡 Указывайте конкретную версию (:v4.0.0), а не :latest — так вы точно знаете, что у вас запущено, и обновляетесь осознанно.
Узнайте публичный адрес
Агент пишет логи в формате JSON (по строке на событие). Публичный адрес проще всего вытащить так:

docker logs xtunnel 2>&1 | grep -o "\"PublicUrl\":\"[^"]*""

Откройте этот адрес в браузере — запросы должны дойти до вашего сервиса.

Весь лог целиком: docker logs -f xtunnel.
Проверьте состояние
docker ps

В колонке STATUS должно быть healthy (появляется через ~10–30 секунд после старта).

Подробнее:
docker exec xtunnel /app/xtunnel-agent healthcheck && echo OK
Запуск рядом с вашим приложением (docker compose)
Самый частый сценарий: приложение и туннель в одном docker-compose.yml.

services:
  app:
    image: ваш-образ
  xtunnel:
    image: ghcr.io/xtnnl/xtunnel-agent:v4.0.0
    restart: unless-stopped
    environment:
      XTUNNEL_LICENSE: ВАШ_КЛЮЧ
      XTUNNEL_TARGET: http://app:8080
    depends_on:
      - app

Запуск: docker compose up -d, логи: docker compose logs xtunnel.
Параметры
Задаются переменными окружения (-e ПЕРЕМЕННАЯ=значение или блок environment:).

XTUNNEL_LICENSE (обязательна) — ключ лицензии из личного кабинета
XTUNNEL_TARGET (обязательна) — адрес вашего сервиса: http://host:port или host:port
XTUNNEL_PROTOCOLhttp (по умолчанию) или tcp
XTUNNEL_TCP_PORT — порт сервиса, если в XTUNNEL_TARGET указан только хост
XTUNNEL_DOMAIN — какой из ваших адресов опубликовать, если их несколько
XTUNNEL_ALLOW — пускать только с этих IP: 10.0.0.0/8,203.0.113.7/32
XTUNNEL_LOG_LEVELInformation (по умолчанию) или Debug
XTUNNEL_NODE_ID — постоянное имя узла (см. шаг 7)
XTUNNEL_BACKEND_TIMEOUT_SECONDS — сколько ждать ответ от сервиса (по умолчанию 60)
XTUNNEL_FORCE_REPLACE — забирать адрес, если на лицензии уже есть подключение (по умолчанию true)

⚠️ XTUNNEL_FORCE_REPLACE оставьте true, если лицензия используется только этим контейнером. Если ту же лицензию одновременно использует кто-то ещё, поставьте false — иначе клиенты будут по очереди отбирать адрес друг у друга.
Постоянное имя узла (рекомендуется)
Подключите том — тогда при пересоздании контейнера агент останется тем же узлом:

-v xtunnel-data:/var/lib/xtunnel

Без тома агент при каждом пересоздании выглядит как новый узел (в логах будет предупреждение). Альтернатива тому — задать XTUNNEL_NODE_ID явно.
Обновление
docker pull ghcr.io/xtnnl/xtunnel-agent:v4.0.0
docker rm -f xtunnel
Повторите команду запуска из шага 2 с новым тегом.

В compose: поменяйте тег в image: и выполните docker compose up -d.

Какая версия работает сейчас:
docker inspect --format '{{index .Config.Labels "org.opencontainers.image.version"}}' xtunnel
Готово ✅
Контейнер запущен и подключён
Публичный адрес получен и отвечает
Состояние — healthy
Настроено постоянное имя узла (при необходимости)