# Trigger tunnel

## Overview

Triggers are commands executed on a specific event. tuna supports two types of events:

* HTTP request (Webhook)
* Email (SMTP)

Starting with version **0.36.0**, the command receives the event data: the request body or the email comes on stdin, and the method, path, headers and addresses come in environment variables.

info

Creating a Trigger tunnel is only available with a [subscription](https://tuna.am/#pricing).

### Example

note

You can see all current flags, hints and examples by calling the help:

```shell
tuna trigger --help
tuna trigger webhook --help
tuna trigger smtp --help

```

Almost all flags have corresponding [environment variables](https://tuna.am/en/docs/guides/environment-variables.md).

### Script to run

For example, create a script `/tmp/trigger.sh` that will create a file and write the phrase `Hello tuna` to it:

/tmp/trigger.sh

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

```

Then make it executable with the command `chmod +x /tmp/trigger.sh`.

The command runs in the background on every event. Its stdout goes to the tuna log at the `debug` level (`--log-level=debug`), stderr at the `error` level.

## HTTP request (Webhook)

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

```

tuna will generate a link:

```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"

```

Now you can send a request to the specified address, and tuna will execute the specified script, for example:

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

```

tuna responds right away without waiting for the command to finish.

### Request data

The request body is passed to the command's stdin as is, binary included. The rest comes in environment variables:

| Variable                     | Value                                                 |
| ---------------------------- | ----------------------------------------------------- |
| `TUNA_REQUEST_METHOD`        | Request method, e.g. `POST`                           |
| `TUNA_REQUEST_PATH`          | URL-encoded path, e.g. `/hooks/a%20b`                 |
| `TUNA_REQUEST_QUERY`         | Query string without `?`, e.g. `id=1&debug=true`      |
| `TUNA_REQUEST_HEADER_<NAME>` | Header value, e.g. `TUNA_REQUEST_HEADER_CONTENT_TYPE` |

The header name is uppercased and every character other than `A-Z` and `0-9` is replaced with `_`: `Content-Type` → `TUNA_REQUEST_HEADER_CONTENT_TYPE`, `X-GitLab-Event` → `TUNA_REQUEST_HEADER_X_GITLAB_EVENT`. Values of repeated headers are joined with `, `. `Host` is passed too: `TUNA_REQUEST_HEADER_HOST`.

A script that prints everything it receives:

/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"}'

```

Reacting only to the right event — deploy on a push to `main` from 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 check

With the `--secret` flag, tuna accepts only requests with the same value in the `X-Webhook-Secret` header. Other requests get `400` and do not run the command. The header itself is not passed to the environment.

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

```

### Limits

The request body is limited to 10 MB. A larger request gets `413` and the command does not run.

## Email (SMTP)

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

```

tuna will generate a link:

```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"

```

Now you can send an email to the specified address, and tuna will execute the specified script, for example:

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

```

The command runs on every accepted email. A connection without an email or without authentication does not run it.

To accept emails only with a username and password, set the `--username` and `--password` flags:

```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

```

### Email data

The whole email (headers and body in RFC 5322 format) is passed to the command's stdin. Addresses and headers come in environment variables:

| Variable                  | Value                                               |
| ------------------------- | --------------------------------------------------- |
| `TUNA_MAIL_FROM`          | Envelope sender (`MAIL FROM`)                       |
| `TUNA_MAIL_TO`            | Envelope recipients (`RCPT TO`) joined with `,`     |
| `TUNA_MAIL_HEADER_<NAME>` | Email header value, e.g. `TUNA_MAIL_HEADER_SUBJECT` |

Header names are built the same way as [for webhook](#webhook-payload). Encoded values like `=?utf-8?b?...?=` are decoded when the charset is `utf-8`, `us-ascii` or `iso-8859-1`. Others come as is.

/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

```

### Local SMTP server address

The trigger SMTP server listens on `127.0.0.1:1025`. If the port is taken by another application, such as Proton Mail Bridge, set a different address with the `--listen-address` flag or the `TUNA_TRIGGER_SMTP_LISTEN_ADDRESS` variable:

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

```

### Limits

An email is limited to 10 MB. A larger one gets code `552` and the command does not run.

## Command environment

Event variables are added to the environment tuna runs with, so the command sees the other variables as well.

Linux limits a single environment variable to 128 KB. If a header is longer, the command does not run and the tuna log shows `Failed to run command: ... argument list too long`.

## Common flags

### Specifying a token

You can specify a particular token using the `--token` flag or the `TUNA_TOKEN` environment variable. Overriding follows the [configuration ordering](https://tuna.am/en/docs/guides/config-ordering.md) policy.

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

```

### Specifying a connection region

You can specify a particular [region](https://tuna.am/en/docs/tunnels/guides/locations.md) using the `--location`/`-l` flag or the `TUNA_LOCATION` environment variable. Overriding follows the [configuration ordering](https://tuna.am/en/docs/guides/config-ordering.md) policy.

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

```

### Static port

The value of the `--port`/`-p` flag can be an alias or an assigned port. You can reserve ports in the [dashboard](https://my.tuna.am/tcp_ports), and after restarting the tunnel the address will remain the same. For more details about ports, see the dedicated [guide](https://tuna.am/en/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

```
