Как защитить AI-агента на VPS: firewall, SSH, Docker и backup без боли
Защитить AI-агента на VPS значит сделать три вещи: закрыть лишние порты, убрать привилегии где они не нужны и настроить контроль того, что агент может делать снаружи и внутри сервера. Если коротко, рабочий минимум такой: SSH только по ключам, firewall по принципу deny by default, reverse proxy перед приложением, секреты вне кода, бэкапы с проверкой восстановления и мониторинг не только CPU, но и самих действий агента.
Проблема в том, что AI-агент на VPS — это уже не просто веб-приложение. У него обычно есть доступ к Telegram, почте, CRM, файлам, Docker, внутренним API или базе знаний. И если обычный сайт при взломе чаще всего «просто ломают», то агент можно ещё и заставить делать что-то от вашего имени. Вот тут начинается самое интересное — и местами довольно дорогое.
🛡️ Как закрыть VPS снаружи и пустить только нужный трафик?
Первая задача — сократить поверхность атаки. На практике это означает не «поставить пару галочек», а оставить снаружи только то, что реально нужно для работы.
- 🔒 Откройте только 22 порт для SSH, 80 и 443 для веб-трафика, плюс один-два служебных порта, если без них никак.
- 🔒 Всё остальное — закрыть по умолчанию через UFW или другой firewall.
- 🔒 Если у агента есть webhook или публичный API, ставьте reverse proxy перед приложением, а не публикуйте сервис напрямую.
- 🔒 Для SSH используйте только ключи. Парольный вход лучше выключить совсем, а root-login — тем более.
- 🔒 Fail2ban до сих пор полезен: интернет полон ботов, которые стучатся в SSH без приглашения. Романтика, конечно, сомнительная.
Для большинства self-hosted стеков нормальная схема выглядит так: публично торчит только Nginx или Caddy, а сам агент, база, Redis и панели живут во внутренней сети. Это банально, зато работает.
🔐 Какие настройки SSH и Docker чаще всего открывают дыру?
Самые неприятные проблемы редко выглядят как «сложная хакерская магия». Обычно это скучная классика: контейнер с лишними правами, открытый Docker socket, пользователь с sudo без необходимости, агент запущен от root.
Вот короткая таблица, что действительно важно проверить:
| Мера | Что даёт | Типичная ошибка |
|---|---|---|
| SSH только по ключам | Убирает подбор пароля | Оставляют password auth «на всякий случай» |
| Docker internal network | Прячет внутренние сервисы | Публикуют наружу Redis, Postgres, Grafana |
| Reverse proxy + rate limit | Режет мусорный трафик и шторма запросов | Пускают трафик прямо в приложение |
| Запуск без root | Снижает blast radius | Агенту дают лишние системные права |
| Бэкапы и проверка restore | Позволяет пережить сбой или компрометацию | Бэкап есть, но никто не пробовал восстановиться |
Отдельный красный флаг — доступ контейнера к /var/run/docker.sock. Для AI-агента это особенно опасно: если через промпт, API или внешний инструмент кто-то протолкнёт вредный сценарий, такой агент может начать управлять контейнерами хоста. Это уже не «ой, текст не так ответил», а полноценный путь к захвату окружения.
🔑 Как безопасно хранить ключи, токены и доступы агента?
У AI-агента секретов почти всегда больше, чем у обычного сайта. LLM API, Telegram bot token, SMTP, CRM, базы данных, облака, вебхуки, иногда даже платёжки. Складывать это в один .env и надеяться на лучшее — стратегия уровня «авось пронесёт».
- 🧷 Минимум: храните секреты отдельно от репозитория и не коммитьте их ни при каких обстоятельствах.
- 🧷 Разделяйте доступы: один токен на одну систему, а не универсальный мастер-ключ на всё.
- 🧷 Ротируйте ключи после инцидентов, смены подрядчика и крупных изменений пайплайна.
- 🧷 Да, у токенов тоже должна быть человеческая судьба — короткая и контролируемая.
Если стек небольшой, хватит аккуратной схемы с секретами на уровне хоста и правами доступа только для нужного сервиса. Если проект растёт, переходите к vault-подходу, docker secrets или хотя бы централизованному хранению с аудитом. Главный принцип простой: агент должен видеть только те ключи, которые нужны ему прямо сейчас, а не всю коллекцию цифровых артефактов компании.
📈 Как мониторить не только сервер, но и поведение самого AI-агента?
Вот где многие ошибаются. Они следят за CPU, RAM и диском, но вообще не смотрят, что агент делает в прикладном слое. Для AI-агента этого мало.
Нужно отслеживать два уровня:
- 📊 Инфраструктура: CPU, RAM, место на диске, сетевые пики, рестарты контейнеров, ошибки reverse proxy.
- 📊 Поведение агента: всплеск вызовов инструментов, рост ошибок API, повторяющиеся webhook-запросы, нетипичный объём токенов, аномальное число действий от одного пользователя.
Например, если агент внезапно начал 400 раз в час дергать CRM или пытаться отправить пачку писем, это не «интересная активность», а повод срочно смотреть логи. Такие паттерны часто появляются при prompt injection, циклах автоматизации или банальной ошибке в цепочке вызовов.
Хороший стек наблюдаемости для MVP — healthchecks, системные логи, алерты на падение процессов, логирование действий агента и отдельная метрика на внешние интеграции. Чем раньше вы увидите странное поведение, тем дешевле обойдётся история.
💾 Как сделать backup и восстановление без иллюзий?
Backup AI-агента — это не только база данных. Нужно сохранять минимум четыре слоя:
- 💽 конфиги сервера и reverse proxy;
- 💽 данные приложения и БД;
- 💽 файлы памяти, промптов, навыков и рабочих сценариев;
- 💽 журнал изменений и инструкции по восстановлению.
Рабочая схема без излишеств выглядит так:
- ✅ ежедневный backup БД;
- ✅ ежедневная копия критичных конфигов;
- ✅ еженедельный snapshot VPS;
- ✅ ежемесячная проверка восстановления на отдельном инстансе.
Последний пункт обязателен. Непроверенный бэкап — это скорее философская концепция, чем защита. В момент аварии он может оказаться битым, неполным или бесполезным без пары забытых конфигов.
⚠️ Какие ошибки при защите AI-агента встречаются чаще всего?
- ❌ Публикуют сервис агента напрямую, без reverse proxy и rate limiting.
- ❌ Оставляют SSH по паролю и root-вход «на пару дней», а потом так и живут.
- ❌ Хранят секреты в репозитории, бэкапе или общем .env без разграничения.
- ❌ Выставляют наружу служебные порты Docker, Redis, Postgres, Grafana.
- ❌ Не ограничивают, какие инструменты агент может вызвать и с какими правами.
- ❌ Не обновляют зависимости и забывают про security patches на Ubuntu.
- ❌ Смотрят только на uptime сервера и не логируют действия самого агента.
- ❌ Делают backup, но не тестируют restore.
Если нужен простой приоритет на старт, то он такой: сначала закрыть поверхность атаки, потом убрать лишние права, потом добавить мониторинг и восстановление. Именно в этом порядке, а не наоборот.
❓ FAQ: что ещё важно знать?
Нужен ли firewall, если агент уже стоит за Nginx или Caddy?
Да. Reverse proxy не заменяет firewall. Он фильтрует веб-трафик, а firewall решает, какие порты вообще доступны снаружи.
Нужно ли прятать агент в VPN, если им пользуется только команда?
Если доступ нужен только внутренним пользователям, это сильный ход. Закрытый контур через VPN или allowlist часто полезнее, чем очередной «умный» фильтр на публичном API.
Можно ли запускать AI-агента в Docker и считать, что он уже изолирован?
Не совсем. Контейнер — это не бронекапсула. Если вы дали ему лишние права, пробросили socket или открыли лишние порты, изоляция быстро становится декоративной.
Как понять, что агенту уже нужен отдельный VPS?
Когда на одном сервере начинают жить агент, база, мониторинг, очередь, прокси и ещё пара «временно нужных» сервисов. В этот момент смешение ролей становится риском и для безопасности, и для стабильности.
Что важнее: backup или мониторинг?
Оба нужны, но на разных этапах. Мониторинг помогает заметить проблему рано, backup — пережить её, если всё-таки дошло до сбоя или компрометации.
Нужен ли fail2ban, если SSH только по ключам?
Да, лишним не будет. Он не заменяет ключи, но снижает шум от бесконечных попыток входа и упрощает жизнь в логах.
Короткий вывод: безопасный self-hosted AI-agent на VPS — это не про паранойю, а про дисциплину. Сначала минимизируйте доступ снаружи, потом сузьте права внутри, затем включите наблюдаемость и проверяемое восстановление. Если хотите собрать такого агента без хаоса и самодельных мин, загляните в Telegram: https://t.me/aaakalsin.