Зачем нужны best practices для туннелирования

Localhost tunnel — один из самых простых инструментов в арсенале разработчика: одна команда — и ваш локальный сервер доступен из интернета. Но простота обманчива. Неаккуратно настроенный туннель может раскрыть конфиденциальные данные, замедлить рабочий процесс или сломаться в разгар демонстрации клиенту. В 2026 году туннели стали стандартной частью разработки: команды используют их для тестирования вебхуков, preview-окружений в CI/CD, тестирования мобильных приложений и доступа к IoT-устройствам. Чем больше вы полагаетесь на туннели, тем важнее использовать их правильно.

Этот гайд содержит 20 best practices, разделённых на четыре категории: безопасность, производительность, командная работа и интеграция с CI/CD. Каждая практика включает конкретное действие, которое можно выполнить прямо сейчас. Примеры кода используют fxTunnel — open-source инструмент для туннелирования с поддержкой HTTP, TCP и UDP — но принципы применимы к любому решению.

Краткая справка: все 20 практик

Вот все практики одним взглядом. Используйте как чек-лист.

#КатегорияПрактикаПриоритет
1БезопасностьВсегда используйте туннели с TLS-шифрованиемКритический
2БезопасностьОстанавливайте туннели, когда они не нужныКритический
3БезопасностьНикогда не пробрасывайте продакшен-данныеКритический
4БезопасностьВалидируйте подписи вебхуковВысокий
5БезопасностьИспользуйте переменные окружения для токеновВысокий
6БезопасностьВыбирайте open-source инструментыСредний
7БезопасностьОбновляйте клиентСредний
8ПроизводительностьВыбирайте правильный протокол туннеляВысокий
9ПроизводительностьИспользуйте health check перед открытием туннеляВысокий
10ПроизводительностьВыбирайте relay-сервер ближе к пользователямСредний
11ПроизводительностьМониторьте задержки и пропускную способностьСредний
12ПроизводительностьИспользуйте инспектор трафика для отладкиВысокий
13КомандаСтандартизируйте запуск туннелей через wrapper-скриптВысокий
14КомандаДокументируйте URL туннелей в общих каналахСредний
15КомандаИспользуйте кастомные домены для стабильных URLСредний
16КомандаОтдельный туннель для каждого микросервисаВысокий
17CI/CDАвтоматизируйте создание туннелей в пайплайнахВысокий
18CI/CDГенерируйте preview URL для каждого PRВысокий
19CI/CDЗапускайте E2E-тесты через URL туннеляСредний
20CI/CDАвтоматически закрывайте туннелиКритический

Безопасность (практики 1-7)

Безопасность – это фундамент. Туннель создаёт точку входа из интернета в вашу локальную машину, и относиться к этому стоит так же серьёзно, как к продакшен-серверу. Тема шифрования подробнее раскрыта в статье TLS 1.3 в туннелировании.

Практика 1: Всегда используйте туннели с TLS-шифрованием

Каждый байт данных между вашей машиной и relay-сервером должен быть зашифрован. Без TLS любой участник сетевого пути — ваш провайдер, оператор Wi-Fi, атакующий — может прочитать ваш трафик. Это касается API-токенов, сессионных cookies и тел запросов.

fxTunnel шифрует все соединения через TLS 1.3 по умолчанию. Настраивать ничего не нужно:

# TLS работает автоматически — каждый туннель зашифрован
fxtunnel http 8080
# -> https://abc123.fxtun.dev (TLS 1.3)

Проверка версии TLS для любого туннеля:

# Проверяем версию TLS
openssl s_client -connect your-tunnel.fxtun.dev:443 2>/dev/null | grep "Protocol"
# -> Protocol  : TLSv1.3

Действие: Если ваш текущий инструмент не шифрует трафик по умолчанию — переходите на тот, который шифрует.

Практика 2: Останавливайте туннели, когда они не нужны

Каждый запущенный туннель — это открытая дверь. Закончили работу — закройте его. Звучит очевидно, но забытые туннели — проблема номер один в командах, которые используют туннелирование ежедневно.

# Запустите туннель, поработайте, затем остановите
fxtunnel http 8080
# Нажмите Ctrl+C по завершении

# Для скриптовых туннелей используйте trap для гарантированной очистки
fxtunnel http 8080 &
TUNNEL_PID=$!
trap "kill $TUNNEL_PID 2>/dev/null" EXIT

Действие: Добавьте trap в каждый скрипт, запускающий туннель. Поставьте напоминание, если склонны забывать.

Практика 3: Никогда не пробрасывайте продакшен-данные

Туннель должен указывать на dev-сервер с тестовыми данными, тестовыми ключами API и тестовыми аккаунтами. Никогда не создавайте туннель к продакшен-базе данных, продакшен-API или сервису, работающему с реальными данными пользователей.

# Правильно: туннель к dev-серверу с тестовыми данными
DATABASE_URL="postgres://dev:dev@localhost:5432/testdb" npm run dev
fxtunnel http 3000

# Неправильно: туннель к продакшен-базе
# fxtunnel tcp 5432  # указывает на продакшен PostgreSQL — НИКОГДА ТАК НЕ ДЕЛАЙТЕ

Действие: Создайте чек-лист для команды, явно запрещающий создание туннелей к продакшен-сервисам.

Практика 4: Валидируйте подписи вебхуков

Даже при наличии TLS всегда проверяйте подписи вебхуков на сервере. Stripe, GitHub, Telegram и другие сервисы подписывают payload вебхуков. Валидация подписи гарантирует, что запрос действительно пришёл от ожидаемого сервиса, а не от атакующего, обнаружившего URL вашего туннеля.

# Запускаем туннель для тестирования вебхуков
fxtunnel http 8080
# -> https://wh-dev.fxtun.dev

# В коде сервера всегда проверяйте подпись:
# Stripe:  stripe.webhooks.constructEvent(body, sig, secret)
# GitHub:  crypto.timingSafeEqual(expectedSig, actualSig)

Гайд по тестированию вебхуков описывает полный процесс.

Действие: Добавьте валидацию подписи к каждому эндпоинту вебхуков до начала тестирования через туннель.

Практика 5: Используйте переменные окружения для токенов

Никогда не хардкодьте токены туннеля, API-ключи или секреты в скриптах и конфигурационных файлах. Используйте переменные окружения.

# Храните токен fxTunnel в переменной окружения
export FXTUNNEL_TOKEN="your-token-here"

# Клиент считывает его автоматически
fxtunnel http 8080

# В CI/CD используйте секреты
# GitHub Actions:
#   env:
#     FXTUNNEL_TOKEN: ${{ secrets.FXTUNNEL_TOKEN }}

Действие: Проверьте скрипты и конфиги на наличие захардкоженных токенов. Перенесите их в переменные окружения или менеджер секретов.

Практика 6: Выбирайте open-source инструменты

Open-source туннель позволяет проверить реализацию TLS, изучить обработку данных и провести аудит кодовой базы. С closed-source инструментом вы доверяете слову вендора. fxTunnel полностью открыт на GitHub — каждая строка кода доступна для аудита.

Статьи ngrok vs Cloudflare vs fxTunnel и обзор инструментов туннелирования сравнивают open-source и закрытые решения бок о бок.

Действие: Проверьте, является ли ваш текущий инструмент для туннелирования open-source. Если нет — оцените альтернативы.

Практика 7: Обновляйте клиент

Каждый релиз fxTunnel включает обновлённый runtime Go с последними патчами безопасности для crypto/tls. Устаревшие клиенты могут содержать известные уязвимости.

# Обновляем fxTunnel до последней версии
curl -fsSL https://fxtun.dev/install.sh | bash

# Или через Go
go install github.com/mephistofox/fxtun.dev/cmd/fxtunnel@latest

# Проверяем текущую версию
fxtunnel --version

Действие: Поставьте ежемесячное напоминание для обновления клиента. В CI/CD всегда устанавливайте последнюю версию.


Производительность (практики 8-12)

Туннель добавляет задержку, потому что трафик проходит через relay-сервер. Эти практики помогут минимизировать накладные расходы и получить максимальную производительность.

Практика 8: Выбирайте правильный протокол туннеля

fxTunnel поддерживает три протокола: HTTP, TCP и UDP. Правильный выбор протокола убирает лишние накладные расходы.

# Веб-приложение — HTTP-туннель (оптимизирован для HTTP-трафика)
fxtunnel http 3000

# Доступ к базе данных — TCP-туннель
fxtunnel tcp 5432

# Игровой сервер или данные IoT-датчиков — UDP-туннель
fxtunnel udp 27015

HTTP-туннели оптимизированы для веб-серверов и API. TCP подходит для баз данных, SSH и других потоковых протоколов. UDP – для real-time нагрузок, чувствительных к задержкам. Различия подробно разобраны в статье «TCP и UDP туннелирование».

Действие: Проверьте свои команды запуска туннелей. Убедитесь, что используете правильный протокол для каждого сервиса.

Практика 9: Используйте health check перед открытием туннеля

Не запускайте туннель, пока приложение не готово принимать запросы. Туннель, указывающий на сервер, который ещё загружается, будет отдавать ошибки всем, кто зайдёт по URL.

#!/bin/bash
# start-with-tunnel.sh — запуск приложения, ожидание health check, затем туннель

# Запускаем приложение
npm run dev &
APP_PID=$!

# Ждём готовности приложения
echo "Ожидание запуска приложения..."
for i in $(seq 1 30); do
  if curl -sf http://localhost:3000/health > /dev/null 2>&1; then
    echo "Приложение готово."
    break
  fi
  if [ "$i" -eq 30 ]; then
    echo "Приложение не запустилось за 60 секунд."
    kill $APP_PID 2>/dev/null
    exit 1
  fi
  sleep 2
done

# Запускаем туннель
fxtunnel http 3000 &
TUNNEL_PID=$!

# Очистка при выходе
trap "kill $APP_PID $TUNNEL_PID 2>/dev/null" EXIT

wait $APP_PID

Действие: Оберните запуск туннеля в скрипт с ожиданием health check.

Практика 10: Выбирайте relay-сервер ближе к пользователям

Если вы показываете демо клиенту в Европе, а relay-сервер находится в Азии — каждый запрос добавляет 200+ мс задержки. В fxTunnel SaaS relay выбирается автоматически. Для self-hosted развёртываний размещайте сервер географически близко к тем, кто будет обращаться к туннелю.

# SaaS — выбор relay автоматический
fxtunnel http 8080

# Self-hosted — разверните сервер рядом с пользователями
fxtunnel server --listen :443 --tls-cert cert.pem --tls-key key.pem

Действие: Для self-hosted конфигураций разверните relay в том же регионе, где находится основная аудитория.

Практика 11: Мониторьте задержки и пропускную способность

Если туннель кажется медленным — измерьте. Простой тест с curl покажет, виноват ли туннель или ваше приложение.

# Измеряем время ответа через туннель
curl -o /dev/null -s -w "DNS: %{time_namelookup}s\nConnect: %{time_connect}s\nTLS: %{time_appconnect}s\nTotal: %{time_total}s\n" https://your-tunnel.fxtun.dev/api/health

# Сравниваем с прямым доступом к localhost
curl -o /dev/null -s -w "Total: %{time_total}s\n" http://localhost:8080/api/health

Разница между двумя измерениями — это накладные расходы туннеля. Обычно это 20-80 мс для правильно настроенного туннеля.

Действие: Добавьте измерение задержек в ваш workflow тестирования через туннель.

Практика 12: Используйте инспектор трафика для отладки

Встроенный инспектор трафика fxTunnel показывает каждый запрос и ответ, проходящие через туннель, в реальном времени. Это быстрее, чем настраивать отдельный прокси вроде mitmproxy или Charles.

# Запускаем туннель с инспектором
fxtunnel http 8080
# Инспектор доступен в дашборде fxTunnel

# Повтор конкретного запроса для отладки
# Используйте кнопку replay в интерфейсе инспектора

Инспектор показывает заголовки, тела, статус-коды и тайминги для каждого запроса. Replay позволяет повторно отправить запрос без повторного срабатывания оригинального события — идеально для отладки обработчиков вебхуков. Возможности инспектора подробно описаны в статье об отладке запросов.

Действие: Используйте инспектор вместо добавления debug-логов в приложение при устранении неполадок с туннелем.


Командная работа (практики 13-16)

Когда несколько разработчиков в команде используют туннели, координация становится важна. Эти практики предотвращают конфликты и путаницу.

Практика 13: Стандартизируйте запуск туннелей через wrapper-скрипт

Вместо того чтобы каждый разработчик запускал fxtunnel с разными флагами, создайте проектный wrapper-скрипт, стандартизирующий конфигурацию.

#!/bin/bash
# scripts/tunnel.sh — проектный запуск туннеля
# Использование: ./scripts/tunnel.sh [service] [port]

SERVICE=${1:-"web"}
PORT=${2:-"3000"}

# Проверяем, запущено ли приложение
if ! curl -sf http://localhost:$PORT/health > /dev/null 2>&1; then
  echo "Ошибка: нет сервиса на порту $PORT"
  echo "Сначала запустите: npm run dev"
  exit 1
fi

echo "Запускаем туннель для $SERVICE на порту $PORT..."
fxtunnel http $PORT --log-file "/tmp/tunnel-${SERVICE}.log" &
TUNNEL_PID=$!

# Ждём URL
for i in $(seq 1 10); do
  TUNNEL_URL=$(grep -oP 'https://[a-z0-9-]+\.fxtun\.dev' "/tmp/tunnel-${SERVICE}.log" 2>/dev/null || true)
  if [ -n "$TUNNEL_URL" ]; then
    echo "Туннель активен: $TUNNEL_URL -> localhost:$PORT"
    break
  fi
  sleep 1
done

trap "kill $TUNNEL_PID 2>/dev/null; echo 'Туннель остановлен.'" EXIT
wait $TUNNEL_PID

Добавьте этот скрипт в репозиторий, чтобы каждый член команды использовал единый workflow.

Действие: Создайте scripts/tunnel.sh в проекте и закоммитьте его в репозиторий.

Практика 14: Документируйте URL туннелей в общих каналах

Когда вы открываете туннель для демо или ревью, отправьте URL в Slack-канал команды (или аналогичный). Укажите, куда ведёт туннель, сколько он будет активен и кто его запустил.

Простой формат:

Туннель активен:
  URL:     https://abc123.fxtun.dev
  Сервис:  frontend (порт 3000)
  Кто:     @alice
  Время:   ~30 минут

Действие: Договоритесь о формате и канале, где публикуются URL туннелей.

Практика 15: Используйте кастомные домены для стабильных URL

Случайные поддомены вроде abc123.fxtun.dev меняются при каждом перезапуске туннеля. Для демо, QA и интеграций, которым нужен стабильный URL, используйте кастомный домен. fxTunnel поддерживает кастомные домены через любого DNS-провайдера на платных тарифах.

# С настроенным кастомным доменом
fxtunnel http 3000
# -> https://dev.yourcompany.com -> localhost:3000

Это особенно важно для OAuth callback URL, которые требуют фиксированного redirect URI. Гайд по OAuth callback описывает настройку пошагово.

Действие: Настройте кастомный домен для наиболее используемого туннеля, если вы на платном тарифе.

Практика 16: Отдельный туннель для каждого микросервиса

Если ваш проект состоит из нескольких сервисов (фронтенд, бэкенд API, воркер), создайте отдельный туннель для каждого вместо маршрутизации всего через один. Это упрощает отладку и делает URL предсказуемыми.

# Терминал 1: Фронтенд
fxtunnel http 3000
# -> https://fe-xyz.fxtun.dev

# Терминал 2: Бэкенд API
fxtunnel http 4000
# -> https://api-xyz.fxtun.dev

# Терминал 3: Админ-панель
fxtunnel http 5000
# -> https://admin-xyz.fxtun.dev

На бесплатном тарифе количество одновременных туннелей не ограничено. Платные тарифы добавляют именованные туннели с кастомными доменами.

Действие: Составьте карту ваших сервисов и назначьте каждому свой туннель.


CI/CD (практики 17-20)

Туннели в CI/CD-пайплайнах открывают preview-окружения, E2E-тестирование через реальные URL и автоматизированные тесты интеграции с вебхуками. Полный процесс описан в гайде по preview-окружениям.

Практика 17: Автоматизируйте создание туннелей в пайплайнах

Установите fxTunnel в CI-раннере и создавайте туннели программно. Это основа для всех CI/CD-workflow с туннелями.

# .github/workflows/tunnel-test.yml
name: Tunnel Integration Test

on: [push]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Start application
        run: |
          docker compose up -d --build
          for i in $(seq 1 30); do
            curl -sf http://localhost:8080/health && break
            sleep 2
          done

      - name: Install fxTunnel
        run: curl -fsSL https://fxtun.dev/install.sh | bash

      - name: Create tunnel
        id: tunnel
        run: |
          fxtunnel http 8080 --log-file /tmp/tunnel.log &
          echo "tunnel_pid=$!" >> "$GITHUB_OUTPUT"
          sleep 5
          TUNNEL_URL=$(grep -oP 'https://[a-z0-9-]+\.fxtun\.dev' /tmp/tunnel.log)
          echo "url=$TUNNEL_URL" >> "$GITHUB_OUTPUT"

      - name: Run tests against tunnel URL
        run: |
          curl -sf ${{ steps.tunnel.outputs.url }}/api/health
          echo "Tunnel is working: ${{ steps.tunnel.outputs.url }}"

      - name: Cleanup
        if: always()
        run: |
          kill ${{ steps.tunnel.outputs.tunnel_pid }} || true
          docker compose down

Действие: Добавьте шаг с туннелем в ваш CI-пайплайн и проверьте работу простым health check.

Практика 18: Генерируйте preview URL для каждого PR

Самый мощный сценарий использования туннелей в CI/CD: автоматические preview-окружения. Каждый pull request получает публичный URL с работающим приложением. Ревьюеры кликают по ссылке вместо того, чтобы локально переключаться на ветку.

# Ключевой шаг: комментарий с preview URL в PR
- name: Comment PR with preview URL
  uses: actions/github-script@v7
  with:
    script: |
      const url = '${{ steps.tunnel.outputs.url }}';
      await github.rest.issues.createComment({
        owner: context.repo.owner,
        repo: context.repo.repo,
        issue_number: context.issue.number,
        body: `## Preview\n\n| | |\n|---|---|\n| **URL** | ${url} |\n| **Commit** | \`${context.sha.substring(0, 7)}\` |`,
      });

Полный workflow с Docker Compose, очисткой и примерами для GitLab CI – в статье о preview-окружениях.

Действие: Настройте preview-окружение для самого активного репозитория.

Практика 19: Запускайте E2E-тесты через URL туннеля

Туннель даёт публичный HTTPS URL, который ведёт себя как реальный деплой. Используйте его для E2E-тестирования с Playwright, Cypress или Selenium.

# Запускаем туннель, затем E2E-тесты
fxtunnel http 3000 --log-file /tmp/tunnel.log &
sleep 5
TUNNEL_URL=$(grep -oP 'https://[a-z0-9-]+\.fxtun\.dev' /tmp/tunnel.log)

# Playwright
npx playwright test --base-url="$TUNNEL_URL"

# Cypress
npx cypress run --config baseUrl="$TUNNEL_URL"

Тестирование через URL туннеля ловит проблемы, которые тестирование на localhost пропускает: проблемы CORS, предупреждения о смешанном контенте, обработка TLS-сертификатов и реальное разрешение DNS.

Действие: Добавьте шаг E2E-тестирования через туннель в ваш CI-пайплайн.

Практика 20: Автоматически закрывайте туннели

Забытый туннель в CI — это и угроза безопасности, и пустая трата ресурсов. Всегда выполняйте очистку.

#!/bin/bash
# ci-tunnel-wrapper.sh — запуск туннеля с автоматической очисткой

cleanup() {
  echo "Закрываем туннель..."
  kill $TUNNEL_PID 2>/dev/null
  docker compose down 2>/dev/null
}
trap cleanup EXIT INT TERM

# Запускаем сервисы и туннель
docker compose up -d --build
fxtunnel http 8080 --log-file /tmp/tunnel.log &
TUNNEL_PID=$!

# Ждём URL туннеля
sleep 5
TUNNEL_URL=$(grep -oP 'https://[a-z0-9-]+\.fxtun\.dev' /tmp/tunnel.log)
echo "Туннель: $TUNNEL_URL"

# Запускаем тесты или ждём ручной проверки
"$@"

# Очистка происходит автоматически через trap

В GitHub Actions используйте concurrency с cancel-in-progress: true и отдельный workflow очистки, срабатывающий при закрытии PR.

Действие: Убедитесь, что каждая CI-джоба, создающая туннель, также его уничтожает — даже при падении джобы.


Паттерны переменных окружения для работы с туннелями

Вот справочник по переменным окружения, упрощающим работу с туннелями в различных контекстах.

# Локальная разработка
export FXTUNNEL_TOKEN="your-token"          # Токен для платных функций
export TUNNEL_PORT="8080"                    # Порт по умолчанию
export TUNNEL_LOG="/tmp/tunnel.log"          # Путь к лог-файлу

# CI/CD (GitHub Actions)
# Сохраните FXTUNNEL_TOKEN как секрет репозитория
# Ссылайтесь в workflow:
#   env:
#     FXTUNNEL_TOKEN: ${{ secrets.FXTUNNEL_TOKEN }}

# Docker Compose
# Передайте URL туннеля как переменную окружения другим сервисам:
#   environment:
#     - API_URL=${TUNNEL_URL}

# .env файл (НЕ коммитьте в git)
FXTUNNEL_TOKEN=your-token
TUNNEL_PORT=8080

Добавьте .env в .gitignore, чтобы предотвратить случайный коммит токенов.

Выбор тарифа под ваш workflow

fxTunnel предлагает три уровня, соответствующих разным потребностям:

ФункцияБесплатноОт $5/месОт $10/мес
HTTP/TCP/UDP туннелиБез ограниченийДо 5 именованных10+ именованных
Трафик и соединенияБез лимитовБез лимитовБез лимитов
Кастомные доменыНетДа (любой DNS)Да (любой DNS)
Инспектор трафикаНетДаДа
ReplayНетДаДа
Подходит дляСоло-разработчик, тестированиеНебольшие команды, демоРастущие команды, CI/CD

Соло-разработчикам и для базового тестирования хватает бесплатного тарифа. Командам, которым нужны стабильные URL и отладка вебхуков, подойдёт тариф $5/мес. Если в CI/CD крутится 10+ туннелей, тариф $10/мес масштабируется под такой workflow.

Типичные анти-паттерны

Вот ошибки, которые мы видим регулярно. Избегайте их.

Анти-паттерн: туннель к продакшену

Никогда не создавайте туннель к продакшен-базе данных, API или сервису. Используйте исключительно тестовые окружения.

Анти-паттерн: токены в коде

Токены в исходном коде оказываются в истории git, логах CI и скриншотах. Всегда используйте переменные окружения или менеджер секретов.

Анти-паттерн: туннель 24/7

Туннель — это временный инструмент. Если нужен постоянный доступ, задеплойте приложение как положено, за обратным прокси с правильным TLS и мониторингом.

Анти-паттерн: один туннель на всё

Маршрутизация нескольких сервисов через один туннель превращает отладку в мучение. Используйте один туннель на сервис.

Анти-паттерн: игнорирование логов

Логи клиента туннеля содержат ошибки соединения, события переподключения и назначение URL. Читайте их, когда что-то идёт не так.

# Всегда используйте лог-файл для фоновых туннелей
fxtunnel http 8080 --log-file /tmp/tunnel.log &

# Проверяйте логи при отладке
tail -f /tmp/tunnel.log

Всё вместе: полная настройка проекта

Вот реальный пример, объединяющий несколько практик в единый workflow разработчика.

#!/bin/bash
# dev-tunnel-setup.sh — полный workflow для мультисервисного проекта
set -euo pipefail

# Конфигурация
FRONTEND_PORT=3000
BACKEND_PORT=4000
LOG_DIR="/tmp/tunnels"
mkdir -p "$LOG_DIR"

# Обработчик очистки
cleanup() {
  echo "Останавливаем все туннели..."
  kill $FE_TUNNEL_PID $BE_TUNNEL_PID 2>/dev/null || true
  echo "Готово."
}
trap cleanup EXIT INT TERM

# Проверяем, запущены ли сервисы
echo "Проверяем сервисы..."
curl -sf http://localhost:$FRONTEND_PORT > /dev/null || { echo "Фронтенд не запущен на порту $FRONTEND_PORT"; exit 1; }
curl -sf http://localhost:$BACKEND_PORT/health > /dev/null || { echo "Бэкенд не запущен на порту $BACKEND_PORT"; exit 1; }

# Запускаем туннели
echo "Запускаем туннели..."
fxtunnel http $FRONTEND_PORT --log-file "$LOG_DIR/frontend.log" &
FE_TUNNEL_PID=$!

fxtunnel http $BACKEND_PORT --log-file "$LOG_DIR/backend.log" &
BE_TUNNEL_PID=$!

# Ждём URL
sleep 5
FE_URL=$(grep -oP 'https://[a-z0-9-]+\.fxtun\.dev' "$LOG_DIR/frontend.log" || echo "pending")
BE_URL=$(grep -oP 'https://[a-z0-9-]+\.fxtun\.dev' "$LOG_DIR/backend.log" || echo "pending")

echo ""
echo "========================================="
echo "  Туннели активны"
echo "========================================="
echo "  Фронтенд: $FE_URL -> localhost:$FRONTEND_PORT"
echo "  Бэкенд:   $BE_URL -> localhost:$BACKEND_PORT"
echo "========================================="
echo ""
echo "Нажмите Ctrl+C для остановки всех туннелей."

# Ждём
wait

Этот скрипт реализует health check (практика 9), использует лог-файлы (предотвращение анти-паттерна), разделяет туннели по сервисам (практика 16) и гарантирует очистку при выходе (практика 20).

FAQ

Сколько туннелей можно запустить одновременно на бесплатном тарифе?

Жёсткого лимита нет – запускайте столько, сколько нужно. Бесплатный тариф не ограничивает ни количество туннелей, ни трафик, ни соединения. Платные тарифы добавляют кастомные домены, инспектор трафика и replay начиная с $5/мес.

Стоит ли использовать туннель в продакшене?

Туннели заточены под разработку и тестирование. Продакшен-нагрузки лучше размещать за полноценным reverse proxy. Но для staging-окружений, внутренних инструментов и длительных демо платные тарифы (от $5/мес) поддерживают кастомные домены и стабильные туннели, которые хорошо справляются с такими задачами.

Как сделать URL туннеля стабильным между перезапусками?

По умолчанию при каждом запуске назначается новый случайный поддомен. Если нужен постоянный адрес – настройте кастомный домен через вашего DNS-провайдера (доступно на платных тарифах от $5/мес). Такой URL переживает перезапуски и переподключения.

Можно ли использовать туннели в CI/CD-пайплайнах?

Да – установите fxTunnel в CI-раннере, поднимите туннель в фоне, вытащите URL из лога и передайте его E2E-тестам или preview-окружению. В разделе CI/CD выше есть готовые скрипты для GitHub Actions.

Какая самая частая ошибка безопасности при работе с туннелями?

Забыть выключить туннель после окончания работы. Каждый активный туннель – открытая точка входа в вашу машину. Возьмите за привычку жать Ctrl+C по завершении сессии и используйте trap в скриптах, чтобы очистка происходила даже при сбое.