# Переход на сессии и API-ключи

Начиная с версии **0.39** tuna-cli входит в аккаунт не по токену, а через сессию устройства. Для серверов, CI и всего, что работает без человека, вместо токена используется API-ключ. Старые токены продолжают работать, но устарели.

## Что поменялось

Раньше у аккаунта был один токен `tt_…` на все устройства. `tuna login` сохранял его в конфигурационный файл, а тот же токен копировали в CI, Docker и сервисы. Отозвать доступ одного устройства было нельзя: перевыпуск токена ломал туннели везде.

Теперь доступ разделён:

| Где                               | Чем входит                                                          | Где хранится                                |
| --------------------------------- | ------------------------------------------------------------------- | ------------------------------------------- |
| CLI на ноутбуке                   | сессия устройства                                                   | системное хранилище ключей                  |
| Tuna Desktop                      | пока токен, как раньше; сессии появятся в следующей версии          | как раньше                                  |
| Сервер без браузера               | сессия, подтверждённая по ссылке с другого устройства, или API-ключ | хранилище ключей или конфигурационный файл  |
| CI, Docker, Kubernetes, Terraform | API-ключ                                                            | переменная `TUNA_API_KEY` или секрет CI     |
| Фоновый сервис `tuna service`     | отдельный ключ сервиса                                              | файл, доступный только пользователю сервиса |

Что это даёт:

* **Каждое устройство — отдельная сессия.** Список сессий виден в [профиле](https://my.tuna.am/profile?lang=ru) и в `tuna session list`. Если ноутбук потерян, завершите его сессию: туннели этого устройства остановятся сразу, остальные продолжат работать.
* **Сессию нельзя тихо скопировать.** Сессия хранит короткоживущий токен доступа и токен обновления, который меняется при каждом обновлении. Если старый токен обновления попытаются использовать повторно, сервер завершит сессию целиком.
* **Ключ — по задаче.** Для CI, сервера или коллеги можно выпустить отдельный [API-ключ](https://my.tuna.am/api_keys?lang=ru) с нужными правами и удалить его, не затрагивая остальные.

Жёсткого срока у сессии нет. Она завершается, если устройство не пользовалось ею 30 дней. Запущенный туннель продлевает сессию сам.

## Что будет со старым токеном

Ничего не сломается. Все токены `tt_…` перенесены в API-ключи с правом на запуск туннелей (`tunnels:connect`): они поднимают туннели, как раньше, а в API, как и раньше, не ходят. Старые версии CLI и Tuna Desktop продолжают работать.

Новый CLI принимает старый токен, но предупреждает о замене:

* переменная `TUNA_TOKEN` → используйте `TUNA_API_KEY`;
* флаг `--token` → `--api-key`;
* поле `token` в [конфигурационном файле](https://tuna.am/docs/guides/config-file.md) → войдите через `tuna login` или сохраните API-ключ;
* команда `tuna config save-token` → `tuna login --with-api-key`.

Сроков отключения старых токенов пока нет. Когда решим, предупредим заранее.

При регистрации токен больше не выпускается: вместо страницы токена в кабинете теперь страница [API-ключей](https://my.tuna.am/api_keys?lang=ru).

## Как перейти

### Ноутбук

Войдите заново:

```bash
tuna login

```

Откроется браузер, после подтверждения CLI сохранит сессию в системное хранилище ключей: Keychain в macOS, Credential Manager в Windows, Secret Service в Linux. Если хранилища нет, добавьте `--insecure-storage`: сессия сохранится в файл `credentials.json` рядом с конфигурационным файлом.

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

```bash
tuna login --hostname=work-laptop

```

После входа старый токен из конфигурационного файла можно удалить: `tuna logout` завершит сессию и спросит, удалить ли сохранённый ключ. Если на этом ключе работают фоновые сервисы, сначала [переустановите их](#service).

Tuna Desktop пока входит как раньше, по токену: вход через сессии в нём появится в следующей версии. Делать в нём ничего не нужно.

### Сервер без браузера

Если вы заходите на сервер по SSH, войдите по ссылке:

```bash
tuna login --no-browser

```

CLI покажет ссылку и код. Откройте ссылку на любом устройстве, где вы вошли в кабинет, и проверьте, что код совпадает. CLI сам распознаёт SSH-сессию и предлагает этот способ первым.

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

### CI, Docker и скрипты

1. Создайте [API-ключ](https://my.tuna.am/api_keys?lang=ru). Выберите набор «Для туннелей» или включите «Запуск туннелей»: без права `tunnels:connect` ключ не поднимает туннели.
2. Положите ключ в секреты CI или окружение контейнера под именем `TUNA_API_KEY` вместо `TUNA_TOKEN`.

```bash
export TUNA_API_KEY=<ваш_ключ>
tuna http 8080 -s=myapp

```

В Docker Compose:

```yaml
services:
  tuna:
    image: yuccastream/tuna:latest
    command: http web:80 -s=myapp --inspect=false
    environment:
      - TUNA_API_KEY=<ваш_ключ>

```

Сохранить ключ на машине, чтобы не передавать его каждый раз, можно командой `tuna login --with-api-key`. Она читает ключ из стандартного ввода, поэтому он не останется в истории оболочки:

```bash
echo "$TUNA_API_KEY" | tuna login --with-api-key

```

Если ключ без права на туннели, CLI предупредит об этом при входе.

### Фоновые сервисы

Сервисы, установленные старым CLI, работают со старым токеном и продолжат работать. Чтобы перевести сервис на отдельный ключ, войдите через `tuna login` и переустановите его с той же командой. Старый CLI ставил на Linux и FreeBSD системные сервисы, поэтому удаляйте их через `sudo`, а в Windows — из PowerShell от имени администратора:

```bash
tuna service list
sudo tuna service uninstall --name=web
tuna service install --name=web -- tuna http 8080 -s=web

```

Без `sudo` новый CLI на Linux ставит пользовательский сервис `systemd --user`. Если нужен системный, запустите `install` через `sudo`: root не видит вашу сессию, поэтому CLI попросит подтвердить выпуск ключа по ссылке.

`install` выпустит ключ только для этого сервиса и привяжет его к типу туннеля и адресу, если в команде есть `--subdomain`, `--domain` или `--port`. `uninstall` отзовёт ключ. Подробнее — в разделе [Запуск в фоне](https://tuna.am/docs/tunnels/guides/service.md).

### Terraform и Kubernetes-оператор

[Terraform-провайдер](https://tuna.am/docs/guides/terraform.md) и [Kubernetes-оператор](https://tuna.am/docs/tunnels/kubernetes-operator.md) с самого начала работают на API-ключах: `api_key` или `TUNA_API_KEY` у провайдера, `credentials.apiKey` у оператора. Менять в них ничего не нужно.

## Вопросы и ответы

### Мой CI с `TUNA_TOKEN` перестанет работать после обновления?

Нет. Новый CLI принимает `TUNA_TOKEN` и только пишет предупреждение в лог. Переименуйте переменную в `TUNA_API_KEY`, когда будет удобно: значение подойдёт то же самое, старый токен уже перенесён в API-ключ.

### Где взять токен, если его больше не показывают в кабинете?

Для своего компьютера токен не нужен: войдите через `tuna login`. Для CI и серверов создайте [API-ключ](https://my.tuna.am/api_keys?lang=ru) с правом на запуск туннелей.

### Как проверить, что CLI больше не использует старый токен?

```bash
tuna whoami

```

Команда покажет аккаунт. Если CLI всё ещё берёт переменную `TUNA_TOKEN` или поле `token` из конфигурационного файла, он предупредит об этом.

### Как выйти на одном устройстве и не задеть остальные?

На самом устройстве выполните `tuna logout`. Если доступа к устройству нет, завершите его сессию в [профиле](https://my.tuna.am/profile?lang=ru): туннели устройства остановятся сразу, а CLI завершится.

### Что будет с сервисами после `tuna logout`?

Сервисы, установленные новым CLI, работают на своих ключах, и `tuna logout` их не трогает. Сервисы на старом токене или на ключе из конфигурационного файла перестанут работать, если удалить этот ключ, — поэтому `logout` спрашивает, удалять ли его. Без терминала ключ остаётся, удалить его можно флагом `--yes`.

### В системе нет хранилища ключей. Что делать?

На серверах без графической сессии хранилища часто нет. Войдите с флагом `--insecure-storage`, чтобы сохранить сессию в файл, или используйте API-ключ.
