# Trigger туннель

## Обзор

Триггеры - команды, выполняемые по определенному событию, tuna поддерживает два типа событий:

* HTTP запрос (Webhook)
* Письмо (SMTP)

Начиная с версии **0.36.0** команда получает данные события: тело запроса или письмо приходит на stdin, метод, путь, заголовки и адреса — в переменных окружения.

> **К сведению.** Создание Trigger туннеля доступно только по [подписке](https://tuna.am/#pricing).

### Пример

> **Примечание.** Все актуальные флаги, подсказки и примеры можно посмотреть вызвав справку:
>
> ```shell
> tuna trigger --help
> tuna trigger webhook --help
> tuna trigger smtp --help
>
> ```
>
> Почти для всех флагов есть аналогичные [переменные окружения](https://tuna.am/docs/guides/environment-variables.md).

### Скрипт для запуска

Например создайте скрипт `/tmp/trigger.sh` который будет создавать файл и записывать в него фразу `Hello tuna`:

/tmp/trigger.sh

```shell
#!/bin/sh
set -xe
touch /tmp/test_file.txt
echo "Hello tuna" > /tmp/test_file.txt

```

Затем сделайте его исполняемым с помощью команды `chmod +x /tmp/trigger.sh`.

Команда запускается в фоне на каждое событие. Её stdout попадает в лог tuna на уровне `debug` (`--log-level=debug`), stderr — на уровне `error`.

## HTTP запрос (Webhook)

```shell
tuna trigger webhook /tmp/trigger.sh

```

tuna сгенерирует ссылку:

```log
INFO[13:00:00] Welcome to Tuna
INFO[13:00:00] Forwarding tcp://ru.tuna.am:16502 -> 127.0.0.1:35839
INFO[13:00:00] Send an HTTP request to http://ru.tuna.am:16502 to execute the command "/tmp/trigger.sh"

```

Теперь вы можете отправить запрос по указанному адресу, а tuna выполнит указанный скрипт, например:

```shell
curl -sSLf http://ru.tuna.am:16502

```

tuna отвечает на запрос сразу, не дожидаясь завершения команды.

### Данные запроса

Тело запроса передаётся команде на stdin как есть, в том числе бинарное. Остальное — в переменных окружения:

| Переменная                   | Значение                                                        |
| ---------------------------- | --------------------------------------------------------------- |
| `TUNA_REQUEST_METHOD`        | Метод запроса, например `POST`                                  |
| `TUNA_REQUEST_PATH`          | Путь в URL-кодировке, например `/hooks/a%20b`                   |
| `TUNA_REQUEST_QUERY`         | Строка запроса без `?`, например `id=1&debug=true`              |
| `TUNA_REQUEST_HEADER_<NAME>` | Значение заголовка, например `TUNA_REQUEST_HEADER_CONTENT_TYPE` |

Имя заголовка переводится в верхний регистр, все символы кроме `A-Z` и `0-9` заменяются на `_`: `Content-Type` → `TUNA_REQUEST_HEADER_CONTENT_TYPE`, `X-GitLab-Event` → `TUNA_REQUEST_HEADER_X_GITLAB_EVENT`. Значения повторяющихся заголовков склеиваются через `, `. `Host` тоже передаётся: `TUNA_REQUEST_HEADER_HOST`.

Скрипт, который выводит всё, что получил:

/tmp/trigger.sh

```shell
#!/bin/sh
echo "Method: $TUNA_REQUEST_METHOD"
echo "Path:   $TUNA_REQUEST_PATH"
echo "Query:  $TUNA_REQUEST_QUERY"
echo "Headers:"
env | grep '^TUNA_REQUEST_HEADER_' | sed 's/^TUNA_REQUEST_HEADER_/  /' | sort
echo "Body:"
cat

```

```shell
tuna trigger webhook --log-level=debug /tmp/trigger.sh
curl -sSf "http://ru.tuna.am:16502/deploy?env=prod" -H "Content-Type: application/json" -d '{"ref":"main"}'

```

Пример реакции только на нужное событие — запуск деплоя по push в `main` из GitLab:

/tmp/deploy.sh

```shell
#!/bin/sh
set -e
[ "$TUNA_REQUEST_HEADER_X_GITLAB_EVENT" = "Push Hook" ] || exit 0
jq -e '.ref == "refs/heads/main"' > /dev/null || exit 0
/opt/app/deploy.sh

```

### Проверка секрета

С флагом `--secret` tuna принимает только запросы с тем же значением в заголовке `X-Webhook-Secret`, остальным отвечает `400` и команду не запускает. Сам заголовок в переменные окружения не передаётся.

```shell
tuna trigger webhook --secret=s3cr3t /tmp/trigger.sh
curl -sSf http://ru.tuna.am:16502 -H "X-Webhook-Secret: s3cr3t"

```

### Ограничения

Тело запроса — не больше 10 МБ. На запрос побольше tuna ответит `413`, команда не запустится.

## Письмо (SMTP)

```shell
tuna trigger smtp /tmp/trigger.sh

```

tuna сгенерирует ссылку:

```log
INFO[13:00:00] Welcome to Tuna
INFO[13:00:00] Forwarding tcp://ru.tuna.am:19284 -> 127.0.0.1:1025
INFO[13:00:00] Send a message to SMTP server ru.tuna.am:19284 to execute the command "/tmp/trigger.sh"

```

Теперь вы можете отправить письмо по указанному адресу, а tuna выполнит указанный скрипт, например:

```shell
curl -s \
  --url "smtp://ru.tuna.am:19284" \
  --mail-from "tuna@example.com" \
  --mail-rcpt "tuna@example.com" \
  --upload-file /tmp/trigger.sh

```

Команда запускается на каждое принятое письмо. Подключение без письма или без авторизации команду не запускает.

Чтобы принимать письма только с логином и паролем, задайте флаги `--username` и `--password`:

```shell
tuna trigger smtp --username=tuna --password=s3cr3t /tmp/trigger.sh
curl -s --url "smtp://ru.tuna.am:19284" --user "tuna:s3cr3t" \
  --mail-from "tuna@example.com" --mail-rcpt "tuna@example.com" --upload-file mail.eml

```

### Данные письма

Письмо целиком (заголовки и тело в формате RFC 5322) передаётся команде на stdin. Адреса и заголовки — в переменных окружения:

| Переменная                | Значение                                                       |
| ------------------------- | -------------------------------------------------------------- |
| `TUNA_MAIL_FROM`          | Отправитель из конверта (`MAIL FROM`)                          |
| `TUNA_MAIL_TO`            | Получатели из конверта (`RCPT TO`) через `,`                   |
| `TUNA_MAIL_HEADER_<NAME>` | Значение заголовка письма, например `TUNA_MAIL_HEADER_SUBJECT` |

Имена заголовков строятся так же, как [у webhook](#webhook-payload). Закодированные значения вида `=?utf-8?b?...?=` раскодируются, если кодировка — `utf-8`, `us-ascii` или `iso-8859-1`. Остальные приходят как есть.

/tmp/trigger.sh

```shell
#!/bin/sh
echo "From:    $TUNA_MAIL_FROM"
echo "To:      $TUNA_MAIL_TO"
echo "Subject: $TUNA_MAIL_HEADER_SUBJECT"
echo "Message:"
cat

```

### Локальный адрес SMTP-сервера

SMTP-сервер триггера слушает `127.0.0.1:1025`. Если порт занят другим приложением, например Proton Mail Bridge, укажите другой адрес флагом `--listen-address` или переменной `TUNA_TRIGGER_SMTP_LISTEN_ADDRESS`:

```shell
tuna trigger smtp --listen-address=127.0.0.1:2525 /tmp/trigger.sh

```

### Ограничения

Письмо — не больше 10 МБ. На письмо побольше tuna ответит кодом `552`, команда не запустится.

## Переменные окружения команды

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

Linux ограничивает одну переменную окружения 128 КБ. Если заголовок длиннее, команда не запустится, а в логе tuna появится `Failed to run command: ... argument list too long`.

## Общие флаги

### С указанием токена

Можно указать специфичный токен через флаг `--token` или переменную окружения `TUNA_TOKEN`. Переопределение происходит в соответствии с политикой [очерёдности конфигурации](https://tuna.am/docs/guides/config-ordering.md).

```shell
tuna trigger webhook --token=tt_***
tuna trigger smtp --token=tt_***

```

### С указанием региона для подключения

Можно указать специфичный [регион](https://tuna.am/docs/tunnels/guides/locations.md) через флаг `--location`/`-l` или переменную окружения `TUNA_LOCATION`. Переопределение происходит в соответствии с политикой [очерёдности конфигурации](https://tuna.am/docs/guides/config-ordering.md).

```shell
tuna trigger webhook --location=nl
tuna trigger smtp --location=nl

```

### Статичный порт

В качестве значения флага `--port`/`-p` может выступать алиас или назначенный порт. Порты можно резервировать в [личном кабинете](https://my.tuna.am/tcp_ports) и после перезапуска туннеля адрес останется прежним. Подробнее о портах читайте в отдельной [инструкции](https://tuna.am/docs/tunnels/ports.md).

```shell
tuna trigger webhook --port=postgres
tuna trigger webhook --port=35000
tuna trigger smtp --port=postgres
tuna trigger smtp --port=35000

```
