- PVSM.RU - https://www.pvsm.ru -

ssh‑commander: SSH‑панель с AI‑агентом для своих VPS

Сделал для себя ssh‑commander: терминал, файловый менеджер, управление Docker и AI‑агент в одном окне. Можно работать с сервером руками, а когда нужна помощь, передать вывод агенту или поставить ему задачу. Он сам смотрит файлы и логи, предлагает команды, а изменения выполняет после подтверждения.

Приложение запускается локально через Docker, интерфейс открывается в браузере. К серверам подключается по SSH. Код открыт под MIT [1], подписки нет. Для агента нужен свой API‑ключ; без него ручные инструменты тоже работают.

Для скриншотов поднял отдельный стенд с тестовыми данными. Ответы Deepseek и результаты команд настоящие.

Для скриншотов поднял отдельный стенд с тестовыми данными. Ответы Deepseek и результаты команд настоящие.

Зачем я это сделал

Несколько моих веб‑проектов нужно было перевезти на новый сервер. Чтобы ничего не забыть, я запустил AI‑агента на старом сервере и попросил изучить конфигурацию и собрать документ для переноса. Где лежат проекты, как запускаются сервисы, какие конфиги нужно забрать.

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

Так появился ssh‑commander. Слева выбираешь сервер, сверху переключаешься между терминалом, файлами и другими разделами. Справа остается чат с агентом. Можно открыть лог, отправить нужный фрагмент в чат и продолжить разбираться в том же окне.

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

Что есть в приложении

  • Терминал. Несколько вкладок на сервер, история команд, восстановление сессии после перезагрузки страницы. Выделение или последний вывод можно отправить агенту одним кликом.

  • Файлы по SFTP. Загрузка и скачивание, редактор с подсветкой, поиск, просмотр растущих логов. Есть анализатор занятого места: можно пройти от большого каталога до конкретных файлов.

  • Docker. Контейнеры, образы, логи, запуск и остановка, Compose, терминал внутри контейнера.

Еще есть разделы для PostgreSQL и MySQL, Nginx, systemd, портов и cron. Полный перечень возможностей есть в README [2].

Переключился с файлов на терминал. Диалог остался на месте.

Переключился с файлов на терминал. Диалог остался на месте.

У агента есть память для каждого сервера: локальный файл MEMORY.md [3], который подгружается в начале следующей сессии. Туда можно записать, где лежат проекты и как они запускаются. Запись требует подтверждения. В один диалог можно подключить несколько серверов; у каждой команды видно, на какой машине она выполняется.

Пример из использования: PDF, свободное место и сломанный бэкап

Когда приложение уже работало, на одном из серверов закончилось место. Агент нашел дубли больших PDF и предложил освободить почти 1,5 ГБ. Заодно предложил перевести работу с PDF на Yandex S3.

Мы убрали дубли, потом настроили работу с S3 и перенесли туда документы. Когда понадобилось удалить с диска PDF, которые уже были перенесены, выяснилось, что нет актуального бэкапа всех медиафайлов в S3. Хотя резервное копирование было настроено раньше.

Агент быстро выяснил причину. Синхронизация сломалась, когда мы удалили дубли PDF: процесс бэкапа попытался удалить соответствующие файлы в S3, но у сервисного аккаунта не хватало прав на удаление. Операция падала, и бэкап перестал обновляться.

То есть перед очисткой оставшихся локальных файлов нашлась проблема с резервным копированием. Агент связал ее с нашим предыдущим действием и нашел недостающие права.

Что агент делает сам, а что нужно подтверждать

Агент может сам прочитать обычный файл, посмотреть логи, список контейнеров или свободное место. Для записи файла, перезапуска контейнера и произвольной shell‑команды нужно подтверждение. Внизу чата появляется плашка: можно раскрыть команду целиком, затем подтвердить или отклонить ее.

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

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

Для команд чтения есть отдельный инструмент exec_readonly с разрешающим списком. Изначально я использовал запрещающий список, но при проверке обнаружились обходы: например, /bin/rm и rm не совпадали с проверяемым именем. Поэтому теперь автоматически проходит только ограниченный набор команд. У них отдельно проверяются флаги, а конвейеры, перенаправления и подстановки запрещены.

Команда

Пройдет без подтверждения

df -h

Да

find /opt -name '*.conf'

Да

find /tmp -delete

Нет: удаление файлов

sort -o /tmp/list.txt /etc/hosts

Нет: запись в файл

Интерпретаторов и сетевых клиентов в этом списке нет. Сложную команду агент может предложить через обычный exec, с подтверждением. Иногда так приходится подтверждать и безобидный запрос. Для своего инструмента я считаю этот компромисс приемлемым. Вот фильтр [4] и его тесты [5].

Для больших задач есть режим планирования. Модель составляет план по уже собранным сведениям, без вызова инструментов. Если нужна свежая информация, ее нужно получить до перехода в этот режим. Одобрение плана запускает работу, но не отменяет подтверждения отдельных изменений.

Ограничения

Агент может предложить неправильную команду. Перед подтверждением ее нужно прочитать, а после выполнения проверить результат. Бэкапы по‑прежнему нужны.

При работе с внешним AI‑провайдером прочитанные файлы и логи передаются ему. Чтение путей, похожих на файлы секретов, например .env или приватных ключей, требует подтверждения. В выводе инструментов скрываются распознанные секреты. Это проверки по шаблонам: они могут что‑то пропустить и не обезличивают логи.

Prompt injection тоже остается проблемой: в файле или логе может оказаться текст с посторонними инструкциями для модели. Проверки команд и подтверждения при этом сохраняются, но гарантировать правильность предложений агента они не могут.

Панель рассчитана на одного пользователя, по умолчанию доступна только на 127.0.0.1 и защищена паролем. SSH‑пароли, пароли БД и API‑ключ хранятся локально открытым текстом; пароль панели хранится как хеш. Каталоги data/ и keys/ вместе с резервными копиями нужно защищать от чужого доступа.

Как попробовать

Нужны Docker с Compose v2 на вашем компьютере и SSH‑доступ к Linux‑серверу. В Linux или macOS готовый образ версии 0.1.1 запускается так:

mkdir ssh-commander
cd ssh-commander
curl --fail --location https://raw.githubusercontent.com/lexuss1979/ssh-commander/v0.1.1/docker-compose.release.yml --output compose.yaml
docker compose up -d

Откройте http://localhost:8080 [6], задайте пароль панели и добавьте сервер. В поле адреса укажите IP или hostname VPS [7]. localhost [8] здесь будет адресом самого контейнера.

Для агента добавьте API‑ключ в настройках. Есть пресеты провайдеров и настройка собственного OpenAI‑совместимого API с поддержкой вызова инструментов. Расходы идут по тарифу провайдера, в приложении есть учет токенов и оценка стоимости по диалогам. На скриншотах используется deepseek-v4-flash. И сам я использую именно эту модель — это очень быстро и недорого.

Установка, в том числе на Windows [9] и первое подключение [10] описаны отдельно. Если хочется посмотреть код: TypeScript, Node.js и ssh2 на бэкенде, React и xterm.js во фронтенде. Есть описание архитектуры [11].

Репозиторий: lexuss1979/ssh‑commander [1]. Если попробуете, напишите, что получилось и чего не хватило. Ошибки и предложения можно оставлять в issues.

Автор: Lexuss1979

Источник [12]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/ssh/459195

Ссылки в тексте:

[1] открыт под MIT: https://github.com/lexuss1979/ssh-commander

[2] README: https://github.com/lexuss1979/ssh-commander/blob/v0.1.1/README.ru.md

[3] MEMORY.md: http://MEMORY.md

[4] фильтр: https://github.com/lexuss1979/ssh-commander/blob/v0.1.1/server/src/ai/guard.ts

[5] его тесты: https://github.com/lexuss1979/ssh-commander/blob/v0.1.1/server/test/guard.test.ts

[6] http://localhost:8080: http://localhost:8080

[7] VPS: https://www.reg.ru/?rlink=reflink-717

[8] localhost: http://localhost

[9] Установка, в том числе на Windows: https://github.com/lexuss1979/ssh-commander/blob/v0.1.1/docs/installation.md

[10] первое подключение: https://github.com/lexuss1979/ssh-commander/blob/v0.1.1/docs/getting-started.ru.md

[11] описание архитектуры: https://github.com/lexuss1979/ssh-commander/blob/v0.1.1/docs/architecture.md

[12] Источник: https://habr.com/ru/articles/1089196/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1089196