# tuna ❤️ JetKVM

[JetKVM](https://jetkvm.com/) — это компактное IP-KVM устройство на базе Rockchip RV1106 (ARM Cortex-A7). Оно позволяет удалённо управлять компьютером: видеть экран, управлять клавиатурой и мышью, монтировать образы дисков — всё через веб-интерфейс в браузере.

По умолчанию JetKVM доступен только в локальной сети. С помощью Tuna вы можете открыть доступ к нему через интернет — без «белого» IP, без VPN, без проброса портов на роутере.

![Tuna + JetKVM](/docs/img/tunnels/guides/jetkvm_tuna.png)

к сведению

Данная инструкция протестирована на JetKVM с системной версией **v0.2.7** и выше. На более ранних версиях `/userdata/init.d/` не поддерживается — обновите JetKVM через веб-интерфейс (Settings → Device → Check for updates).

***

## Подготовка

Помимо установки инструкция по настройке разделена на 2 типа, в зависимости от наличия платной подписки Tuna.

1. [На бесплатном тарифе](#%D1%82%D0%B8%D0%BF-1-%D0%B1%D0%B5%D1%81%D0%BF%D0%BB%D0%B0%D1%82%D0%BD%D1%8B%D0%B9-%D1%82%D0%B0%D1%80%D0%B8%D1%84--http-%D1%82%D1%83%D0%BD%D0%BD%D0%B5%D0%BB%D1%8C)
2. [С платной подпиской](#%D1%82%D0%B8%D0%BF-2-%D0%BF%D0%BE%D0%B4%D0%BF%D0%B8%D1%81%D0%BA%D0%B0--ssh-%D0%B8-http-%D1%82%D1%83%D0%BD%D0%BD%D0%B5%D0%BB%D0%B8)

### Что потребуется

* JetKVM с системной версией **v0.2.7 или новее**
* **Developer Mode** включен в веб-интерфейсе JetKVM (Settings → Advanced → Developer Mode)
* **SSH-ключ** добавлен через веб-интерфейс JetKVM
* Аккаунт на [tuna.am](https://my.tuna.am/) (бесплатный или с подпиской)
* Токен авторизации со [страницы токена](https://my.tuna.am/token)

### Особенности системы JetKVM

JetKVM работает на кастомной embedded Linux (Buildroot + Rockchip SDK). Важные отличия от обычного Linux:

| Особенность       | Значение                                       |
| ----------------- | ---------------------------------------------- |
| Оболочка          | `/bin/sh` (BusyBox ash). **bash отсутствует**  |
| SSH-сервер        | Dropbear (нет scp, sftp, rsync)                |
| Init-система      | BusyBox init + скрипты в `/userdata/init.d/`   |
| Persistent-раздел | `/userdata/` — сохраняется при OTA-обновлениях |

Структура хранилища:

| Путь         | Назначение              | Сохраняется при OTA |
| ------------ | ----------------------- | ------------------- |
| `/`          | Корневая ФС             | Нет                 |
| `/userdata/` | Пользовательские данные | **Да**              |

Мы будем хранить tuna в `/userdata/tuna/`, чтобы бинарник и конфигурация сохранялись при обновлениях.

### Подключение по SSH

Включите Developer Mode в веб-интерфейсе JetKVM и добавьте публичный RSA-ключ (Settings → Advanced → Developer Mode). Затем подключитесь:

```bash
ssh root@<IP-адрес-JetKVM>

```

Или откройте терминал в веб интерфейсе:

![JetKVM terminal](/docs/img/tunnels/guides/jetkvm_terminal.png)

подсказка

IP-адрес можно найти на встроенном экране JetKVM или в DHCP-таблице роутера.

### Установка tuna на JetKVM

Подключитесь к JetKVM по SSH и установите бинарник:

```bash
mkdir -p /userdata/tuna
INSECURE=true INSTALL_DIR=/userdata/tuna sh -c "$(wget -qO- http://releases.tuna.am/tuna/get.sh)"

```

Почему `INSECURE=true`?

На JetKVM отсутствуют корневые CA-сертификаты, поэтому wget не может проверить SSL-сертификат сервера. Флаг `INSECURE=true` переключает скрипт на загрузку по HTTP. Это безопасно, так как бинарник tuna после загрузки можно проверить по контрольной сумме.

подсказка

Раздел `/userdata` сохраняется при OTA-обновлениях, поэтому tuna не придётся переустанавливать после обновления прошивки.

Сохраните [токен](https://my.tuna.am/token) авторизации:

```bash
/userdata/tuna/tuna --config=/userdata/tuna/.tuna.yml config save-token <ВАШ_ТОКЕН>

```

подсказка

Рекомендуем создать дополнительный токен для устройства.

***

## Система автозапуска JetKVM

В отличие от NanoKVM, где автозапуск настраивается через `/etc/inittab` с директивой `respawn`, на JetKVM используются init-скрипты в директории `/userdata/init.d/`, каталог нужно создать.

```bash
mkdir -p /userdata/init.d

```

При загрузке init-система JetKVM выполняет все скрипты из `/userdata/init.d/`, чьи имена соответствуют паттерну `S??*` (например, `S99tuna-http`). Скрипты вызываются с аргументом `start`, при остановке — с аргументом `stop`.

Критические правила для init-скриптов

Несоблюдение этих правил может привести к тому, что устройство **перестанет загружаться**:

1. **Используйте `#!/bin/sh`** — на JetKVM нет `/bin/bash`. Шебанг `#!/bin/bash` приведёт к ошибке и может заблокировать загрузку.
2. **Не используйте расширение `.sh`** — файлы с расширением `.sh` включаются через `source` (а не вызываются как отдельный процесс). Команда `exit` в таком скрипте завершит весь init-процесс.
3. **Не блокируйте загрузку** — все долгоживущие процессы должны запускаться **в фоне** с `&`. Если скрипт не возвращает управление, загрузка зависнет.
4. **Обрабатывайте аргумент `start`** — init-система вызывает скрипт как `S99tuna-http start`. Без `case "$1"` скрипт может выполниться некорректно.

Нет автоматического перезапуска

В отличие от NanoKVM (где `inittab respawn` автоматически перезапускает упавший процесс), на JetKVM `/etc/inittab` перезаписывается при OTA-обновлениях. Поэтому мы используем цикл `while true` внутри init-скрипта для автоперезапуска при падении.

Тестируйте перед перезагрузкой

Всегда запускайте скрипт вручную (`/userdata/init.d/S99tuna-http start`) и убедитесь, что промпт вернулся. Если после запуска консоль «зависла» — скрипт заблокирует загрузку при перезагрузке.

***

## Тип 1. Бесплатный тариф — HTTP-туннель

На бесплатном тарифе доступен HTTP-туннель с динамическим адресом. Этого достаточно, чтобы открыть веб-интерфейс JetKVM в интернет и управлять компьютером через браузер.

Ограничения бесплатного тарифа

* Динамический адрес меняется при каждом переподключении туннеля
* Чтобы адрес не менялся, добавьте в команду запуска свой [бесплатный постоянный поддомен](https://tuna.am/docs/tunnels/http.md#free-subdomain): `--subdomain=<ваш-поддомен>`
* Текущий адрес всегда можно посмотреть в [личном кабинете](https://my.tuna.am/tunnels)

### Создание init-скрипта

```bash
cat << 'INITEOF' > /userdata/init.d/S99tuna-http
#!/bin/sh

PIDFILE=/tmp/tuna-http.pid
LOGFILE=/tmp/tuna-http.log

wait_network() {
    i=0
    while ! ip route | grep -q default; do
        sleep 1
        i=$((i + 1))
        if [ "$i" -ge 60 ]; then
            echo "$(date): network timeout" >> "$LOGFILE"
            return 1
        fi
    done
    return 0
}

start() {
    echo "$(date): starting tuna-http" >> "$LOGFILE"
    (
        wait_network || exit 1
        while true; do
            /userdata/tuna/tuna \
                --config=/userdata/tuna/.tuna.yml \
                --log="$LOGFILE" \
                http \
                --inspect=false \
                --basic-auth=tuna:SecurePasswd \
                --https-redirect \
                80 >> "$LOGFILE" 2>&1
            echo "$(date): tuna-http exited, restarting in 5s" >> "$LOGFILE"
            sleep 5
        done
    ) &
    echo $! > "$PIDFILE"
}

stop() {
    if [ -f "$PIDFILE" ]; then
        kill "$(cat "$PIDFILE")" 2>/dev/null
        pkill -f "/userdata/tuna/tuna.*http" 2>/dev/null
        rm -f "$PIDFILE"
    fi
}

case "$1" in
    start) start ;;
    stop) stop ;;
    restart) stop; sleep 1; start ;;
    *) echo "Usage: $0 {start|stop|restart}" ;;
esac
INITEOF
chmod +x /userdata/init.d/S99tuna-http

```

### Пояснение init-скрипта

| Элемент                | Описание                                                                                    |
| ---------------------- | ------------------------------------------------------------------------------------------- |
| `S99tuna-http`         | Имя **без** `.sh` — init вызывает скрипт с аргументом `start`, а не включает через `source` |
| `wait_network()`       | Ожидает появления default route (максимум 60 секунд)                                        |
| `( ... ) &`            | Субшелл запускается **в фоне** — не блокирует загрузку                                      |
| `while true`           | Автоматический перезапуск tuna при падении (пауза 5 секунд)                                 |
| `echo $! > "$PIDFILE"` | Сохраняет PID субшелла для корректной остановки                                             |
| `pkill -f`             | При остановке убивает и обёртку, и дочерний процесс tuna                                    |

### Пояснение флагов tuna

| Флаг                           | Обязательный | Описание                                                                                                                   |
| ------------------------------ | ------------ | -------------------------------------------------------------------------------------------------------------------------- |
| `--inspect=false`              | Нет          | Отключает инспектор трафика (не нужен для KVM), чтобы не расходовать RAM                                                   |
| `--basic-auth=admin:ВашПароль` | Нет          | Дополнительная HTTP-авторизация ([подробнее](#%D0%B7%D0%B0%D1%87%D0%B5%D0%BC-%D0%BD%D1%83%D0%B6%D0%B5%D0%BD---basic-auth)) |
| `--https-redirect`             | Нет          | Перенаправляет HTTP на HTTPS                                                                                               |
| `80`                           | Да           | Порт веб-интерфейса JetKVM                                                                                                 |

Также можно [ограничить доступ по IP-подсетям](#%D0%BE%D0%B3%D1%80%D0%B0%D0%BD%D0%B8%D1%87%D0%B5%D0%BD%D0%B8%D0%B5-%D0%BF%D0%BE-ip-%D0%BF%D0%BE%D0%B4%D1%81%D0%B5%D1%82%D1%8F%D0%BC).

### Проверка

Запустите скрипт вручную:

```bash
/userdata/init.d/S99tuna-http start

```

Убедитесь, что промпт вернулся (скрипт не заблокировал консоль). Проверьте, что процесс запущен:

```bash
ps | grep tuna

```

В выводе должна быть строка с `/userdata/tuna/tuna ... http ...`. Если процесса нет — смотрите раздел [Диагностика неполадок](#%D0%B4%D0%B8%D0%B0%D0%B3%D0%BD%D0%BE%D1%81%D1%82%D0%B8%D0%BA%D0%B0-%D0%BD%D0%B5%D0%BF%D0%BE%D0%BB%D0%B0%D0%B4%D0%BE%D0%BA).

В логах вы увидите URL вашего туннеля:

```bash
cat /tmp/tuna-http.log

```

Также текущий адрес доступен в [личном кабинете](https://my.tuna.am/).

***

## Тип 2. Подписка — SSH и HTTP туннели

С [подпиской](https://tuna.am/#pricing) вы получаете:

* **Фиксированный поддомен** для HTTP-туннеля — адрес не меняется
* **SSH-туннель** — прямой доступ к консоли JetKVM из любой точки мира

### HTTP-туннель с фиксированным адресом

```bash
cat << 'INITEOF' > /userdata/init.d/S99tuna-http
#!/bin/sh

PIDFILE=/tmp/tuna-http.pid
LOGFILE=/tmp/tuna-http.log

wait_network() {
    i=0
    while ! ip route | grep -q default; do
        sleep 1
        i=$((i + 1))
        if [ "$i" -ge 60 ]; then
            echo "$(date): network timeout" >> "$LOGFILE"
            return 1
        fi
    done
    return 0
}

start() {
    echo "$(date): starting tuna-http" >> "$LOGFILE"
    (
        wait_network || exit 1
        while true; do
            /userdata/tuna/tuna \
                --config=/userdata/tuna/.tuna.yml \
                --log="$LOGFILE" \
                http \
                --subdomain=jetkvm \
                --inspect=false \
                --basic-auth=admin:ВашПароль \
                --https-redirect \
                80 >> "$LOGFILE" 2>&1
            echo "$(date): tuna-http exited, restarting in 5s" >> "$LOGFILE"
            sleep 5
        done
    ) &
    echo $! > "$PIDFILE"
}

stop() {
    if [ -f "$PIDFILE" ]; then
        kill "$(cat "$PIDFILE")" 2>/dev/null
        pkill -f "/userdata/tuna/tuna.*http" 2>/dev/null
        rm -f "$PIDFILE"
    fi
}

case "$1" in
    start) start ;;
    stop) stop ;;
    restart) stop; sleep 1; start ;;
    *) echo "Usage: $0 {start|stop|restart}" ;;
esac
INITEOF
chmod +x /userdata/init.d/S99tuna-http

```

Отличие от бесплатной версии — флаг `--subdomain=jetkvm`, который закрепляет за вами постоянный адрес. После перезапуска туннеля URL останется прежним.

к сведению

Поддомен из примера уже может быть занят. Зарезервируйте свой поддомен заранее в [личном кабинете](https://my.tuna.am/domains), затем используйте его в флаге `--subdomain=ваш-поддомен`.

#### Пояснение флагов HTTP-туннеля

| Флаг                           | Обязательный | Описание                                                                                                                   |
| ------------------------------ | ------------ | -------------------------------------------------------------------------------------------------------------------------- |
| `--subdomain=jetkvm`           | Нет          | Фиксирует постоянный адрес туннеля (только с подпиской)                                                                    |
| `--inspect=false`              | Нет          | Отключает инспектор трафика (не нужен для KVM), чтобы не расходовать RAM                                                   |
| `--basic-auth=admin:ВашПароль` | Нет          | Дополнительная HTTP-авторизация ([подробнее](#%D0%B7%D0%B0%D1%87%D0%B5%D0%BC-%D0%BD%D1%83%D0%B6%D0%B5%D0%BD---basic-auth)) |
| `--https-redirect`             | Нет          | Перенаправляет HTTP на HTTPS                                                                                               |
| `80`                           | Да           | Порт веб-интерфейса JetKVM                                                                                                 |

Также можно [ограничить доступ по IP-подсетям](#%D0%BE%D0%B3%D1%80%D0%B0%D0%BD%D0%B8%D1%87%D0%B5%D0%BD%D0%B8%D0%B5-%D0%BF%D0%BE-ip-%D0%BF%D0%BE%D0%B4%D1%81%D0%B5%D1%82%D1%8F%D0%BC).

### SSH-туннель

SSH-туннель позволяет подключаться к консоли JetKVM через интернет. Это удобно для администрирования, обновления прошивки и диагностики.

```bash
cat << 'INITEOF' > /userdata/init.d/S98tuna-ssh
#!/bin/sh

PIDFILE=/tmp/tuna-ssh.pid
LOGFILE=/tmp/tuna-ssh.log

wait_network() {
    i=0
    while ! ip route | grep -q default; do
        sleep 1
        i=$((i + 1))
        if [ "$i" -ge 60 ]; then
            echo "$(date): network timeout" >> "$LOGFILE"
            return 1
        fi
    done
    return 0
}

start() {
    echo "$(date): starting tuna-ssh" >> "$LOGFILE"
    (
        wait_network || exit 1
        while true; do
            /userdata/tuna/tuna \
                --config=/userdata/tuna/.tuna.yml \
                --log="$LOGFILE" \
                ssh \
                --port=jetkvm-ssh \
                --record-session=false \
                --password-auth=false >> "$LOGFILE" 2>&1
            echo "$(date): tuna-ssh exited, restarting in 5s" >> "$LOGFILE"
            sleep 5
        done
    ) &
    echo $! > "$PIDFILE"
}

stop() {
    if [ -f "$PIDFILE" ]; then
        kill "$(cat "$PIDFILE")" 2>/dev/null
        pkill -f "/userdata/tuna/tuna.*ssh" 2>/dev/null
        rm -f "$PIDFILE"
    fi
}

case "$1" in
    start) start ;;
    stop) stop ;;
    restart) stop; sleep 1; start ;;
    *) echo "Usage: $0 {start|stop|restart}" ;;
esac
INITEOF
chmod +x /userdata/init.d/S98tuna-ssh

```

#### Пояснение флагов SSH-туннеля

| Флаг                     | Обязательный | Описание                                                                                                                                                                                                                 |
| ------------------------ | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `--port=jetkvm-ssh`      | Нет          | Фиксирует порт SSH-туннеля. Без этого флага порт будет назначаться случайно при каждом запуске. [Алиас для порта](https://my.tuna.am/tcp_ports) нужно зарезервировать заранее перед запуском.                            |
| `--record-session=false` | Нет          | Отключает запись SSH-сессий на диск. На embedded устройствах с ограниченным хранилищем рекомендуется отключать, чтобы не занимать место.                                                                                 |
| `--password-auth=false`  | Нет          | Запрещает подключение по паролю — доступ только по SSH-ключам ([подробнее](#%D0%B0%D1%83%D1%82%D0%B5%D0%BD%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F-%D0%B2-ssh-%D1%82%D1%83%D0%BD%D0%BD%D0%B5%D0%BB%D0%B5)) |

Также можно задать [статичный логин и пароль](#%D0%B0%D1%83%D1%82%D0%B5%D0%BD%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F-%D0%B2-ssh-%D1%82%D1%83%D0%BD%D0%BD%D0%B5%D0%BB%D0%B5) или [ограничить доступ по IP-подсетям](#%D0%BE%D0%B3%D1%80%D0%B0%D0%BD%D0%B8%D1%87%D0%B5%D0%BD%D0%B8%D0%B5-%D0%BF%D0%BE-ip-%D0%BF%D0%BE%D0%B4%D1%81%D0%B5%D1%82%D1%8F%D0%BC).

### Проверка туннелей

Запустите оба скрипта вручную:

```bash
/userdata/init.d/S99tuna-http start
/userdata/init.d/S98tuna-ssh start

```

Убедитесь, что оба процесса запущены:

```bash
ps | grep tuna

```

В выводе должны быть две строки — с `http` и `ssh`. Если какого-то процесса нет — смотрите раздел [Диагностика неполадок](#%D0%B4%D0%B8%D0%B0%D0%B3%D0%BD%D0%BE%D1%81%D1%82%D0%B8%D0%BA%D0%B0-%D0%BD%D0%B5%D0%BF%D0%BE%D0%BB%D0%B0%D0%B4%D0%BE%D0%BA).

Посмотрите логи:

```bash
cat /tmp/tuna-http.log
cat /tmp/tuna-ssh.log

```

В логах HTTP-туннеля будет URL, а в логах SSH-туннеля — инструкция для подключения с указанием адреса и порта.

***

## Управление туннелями

Автоперезапуск при падении обеспечивается циклом `while true` внутри init-скрипта. Для управления туннелями используйте следующие команды.

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

```bash
ps | grep tuna

```

### Остановка туннеля

```bash
# Остановить HTTP-туннель
/userdata/init.d/S99tuna-http stop

# Остановить SSH-туннель
/userdata/init.d/S98tuna-ssh stop

```

### Запуск туннеля

```bash
# Запустить HTTP-туннель
/userdata/init.d/S99tuna-http start

# Запустить SSH-туннель
/userdata/init.d/S98tuna-ssh start

```

### Перезапуск туннеля

```bash
# Перезапустить HTTP-туннель
/userdata/init.d/S99tuna-http restart

# Перезапустить SSH-туннель
/userdata/init.d/S98tuna-ssh restart

```

### Полное отключение автозапуска

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

```bash
# Отключить автозапуск HTTP-туннеля
mv /userdata/init.d/S99tuna-http /userdata/init.d/disabled-tuna-http

# Включить обратно
mv /userdata/init.d/disabled-tuna-http /userdata/init.d/S99tuna-http

```

***

## Восстановление после OTA-обновления

Бинарник, конфигурация и init-скрипты хранятся в `/userdata/`, который **сохраняется при OTA-обновлениях**. После обновления прошивки через веб-интерфейс JetKVM туннели продолжат работать без дополнительных действий.

к сведению

В отличие от NanoKVM, на JetKVM не нужно восстанавливать `/etc/inittab` после обновления — автозапуск через `/userdata/init.d/` полностью переживает OTA.

При полной перепрошивке (когда `/userdata` был очищен) потребуется заново установить бинарник, сохранить токен и создать init-скрипты.

***

## Дополнительные настройки безопасности

### Зачем нужен `--basic-auth`

У JetKVM есть собственная авторизация в веб-интерфейсе. Однако, учитывая [историю уязвимостей в IoT-устройствах](https://owasp.org/www-project-internet-of-things/), мы настоятельно рекомендуем добавить дополнительный уровень защиты. При открытии доступа через интернет лучше перестраховаться — флаг `--basic-auth` добавит стандартную HTTP-авторизацию (логин и пароль в браузере) ещё до того, как запрос дойдёт до JetKVM.

```bash
--basic-auth=mylogin:MyStr0ngP@ss

```

Важно

Задайте **свои** логин и пароль. Не используйте значения из примеров.

### Аутентификация в SSH-туннеле

**Вариант 1. По SSH-ключам (рекомендуется)**

Флаг `--password-auth=false` отключает вход по паролю. Для подключения потребуется предварительно добавить публичный SSH-ключ в [личном кабинете](https://my.tuna.am/public_keys).

Подробная инструкция: [Настройка SSH-ключей](https://tuna.am/docs/guides/ssh-keys.md)

warning

Туннельные ноды имеют публичный адрес. Злоумышленники могут просканировать порты и начать подбор пароля. Для долгоживущих SSH-туннелей настоятельно рекомендуем отключить парольную аутентификацию.

**Вариант 2. Статичный логин и пароль**

Если SSH-ключи не подходят, можно задать фиксированные учётные данные:

```bash
--auth=user:pass

```

Замените `user` и `pass` на свои значения.

### Ограничение по IP-подсетям

Для HTTP и SSH туннелей можно ограничить доступ по IP-адресам.

Разрешить доступ только с определённых подсетей:

```bash
--cidr-allow="203.0.113.0/24"

```

Запретить доступ из определённых подсетей:

```bash
--cidr-deny="198.51.100.0/24"

```

Можно комбинировать — разрешить подсеть, но исключить отдельные адреса:

```bash
--cidr-allow="10.0.0.0/24" --cidr-deny="10.0.0.33/32"

```

Осторожно

Используйте фильтрацию по IP с осторожностью. Если вы ошибётесь с подсетью или ваш IP-адрес изменится — вы потеряете удалённый доступ к JetKVM. Убедитесь, что у вас есть альтернативный способ управления устройством (например, локальный доступ).

***

## Диагностика неполадок

### Устройство не загружается после добавления init-скрипта

Экстренное восстановление

Если JetKVM перестал загружаться после добавления скрипта в `/userdata/init.d/`, наиболее частые причины:

1. **Шебанг `#!/bin/bash`** — bash на JetKVM отсутствует
2. **Скрипт блокирует загрузку** — процесс не запущен в фоне (`&`)
3. **Расширение `.sh`** — скрипт был включён через `source`, что сломало init-процесс
4. **Синтаксическая ошибка** — прерывает выполнение init

**Способы восстановления:**

* **UART serial console** — если есть доступ к UART-порту JetKVM, подключитесь через serial console (115200 baud) и удалите или переименуйте проблемный скрипт
* **Factory reset** — нажмите и удерживайте кнопку сброса на JetKVM (внимание: это может очистить `/userdata/`)

### Процесс tuna не запускается

Проверьте, что процесс присутствует в списке:

```bash
ps | grep tuna

```

Если в выводе нет строк с `/userdata/tuna/tuna` — проверьте:

1. Скрипт существует и имеет права на выполнение:

```bash
ls -la /userdata/init.d/S9*tuna*

```

2. Скрипт запускается без ошибок:

```bash
/userdata/init.d/S99tuna-http start

```

3. Бинарник tuna работает:

```bash
/userdata/tuna/tuna version

```

### Просмотр логов

Логи туннелей записываются в `/tmp/` и доступны до перезагрузки устройства:

```bash
# Логи HTTP-туннеля
cat /tmp/tuna-http.log

# Логи SSH-туннеля
cat /tmp/tuna-ssh.log

```

Для наблюдения за логами в реальном времени:

```bash
tail -f /tmp/tuna-http.log

```

### Типичные ошибки в логах

| Ошибка                    | Причина                             | Решение                                                                                    |
| ------------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------ |
| `token is invalid`        | Неверный или просроченный токен     | Повторите `config save-token` с актуальным токеном со [страницы](https://my.tuna.am/token) |
| `Domain already reserved` | Поддомен занят другим пользователем | Выберите другое имя через `--subdomain=`                                                   |
| `port alias not found`    | Алиас порта не зарезервирован       | Зарезервируйте алиас в [личном кабинете](https://my.tuna.am/tcp_ports)                     |
| `connection refused`      | Нет доступа к интернету             | Проверьте сеть: `ping -c 3 8.8.8.8`                                                        |
| `exec format error`       | Неправильная архитектура бинарника  | Убедитесь, что используете `tuna_linux_arm` (ARMv7)                                        |

### Нет доступа к интернету

Проверьте, что JetKVM имеет сетевое подключение:

```bash
# Проверить наличие IP-адреса
ip addr

# Проверить маршрут по умолчанию
ip route

# Проверить доступ в интернет
ping -c 3 8.8.8.8

```

### Логи пропали после перезагрузки

Логи хранятся в `/tmp/`, который очищается при перезагрузке. Это нормальное поведение. Если нужно сохранять логи между перезагрузками, измените путь в init-скриптах:

```bash
LOGFILE=/userdata/tuna/tuna-http.log

```

warning

Частая запись логов может сократить ресурс хранилища. Используйте это только для временной отладки.

### Туннель работал и перестал

1. Проверьте логи на наличие ошибок
2. Убедитесь, что токен всё ещё действителен в [личном кабинете](https://my.tuna.am/token)
3. Проверьте, что скрипт в `/userdata/init.d/` на месте и исполняем:

```bash
ls -la /userdata/init.d/S9*tuna*

```

***

## Ссылки

* [JetKVM — официальный сайт](https://jetkvm.com/)
* [JetKVM — GitHub](https://github.com/jetkvm/kvm)
* [JetKVM — документация](https://jetkvm.com/docs)
* [HTTP-туннель — все флаги](https://tuna.am/docs/tunnels/http.md)
* [SSH-туннель — все флаги](https://tuna.am/docs/tunnels/ssh.md)
* [Настройка SSH-ключей](https://tuna.am/docs/guides/ssh-keys.md)
* [Запуск tuna как сервис](https://tuna.am/docs/tunnels/guides/service.md)

***

## Мониторинг доступности

Помимо туннелей для удалённого доступа, вы можете настроить мониторинг доступности JetKVM. Heartbeat-мониторинг будет отправлять вам уведомления, если устройство потеряет связь с интернетом или перестанет отвечать.

**Полная инструкция:** [Мониторинг доступности JetKVM](https://tuna.am/docs/monitors/examples/jetkvm.md)
