Пошаговые инструкции intermediate 27 мин

Как запустить ИИ-агента на сервере: Docker, HTTPS, очереди, логи и rollback

Пошаговая инструкция по запуску ИИ-агента на сервере: VPS, Docker Compose, Nginx, HTTPS, API, worker, Redis, Postgres, vector store, логи, backup и rollback.

Инструкция production Docker ИИ-агент на сервере Docker Compose Nginx HTTPS VPS Redis Postgres

Что получится в результате

Соберем production-like запуск ИИ-агента на VPS или выделенном сервере. Агент будет работать как отдельное приложение с публичным API, закрытыми внутренними endpoints, HTTPS, очередью задач, базой данных, vector store, секретами в `.env`, healthcheck, логами, мониторингом, резервным копированием и понятным откатом.

В результате будет рабочий контур:

  1. сервер описан в `server_inventory`;
  2. домен и DNS записаны в `domain_config`;
  3. пользователь Linux описан в `deploy_user`;
  4. код лежит в `/opt/ai-agent`;
  5. секреты лежат в `.env.production`;
  6. приложение упаковано в Docker image;
  7. сервисы описаны в `docker-compose.yml`;
  8. web API агента слушает только внутренний порт;
  9. Nginx принимает публичный HTTPS;
  10. `/health` проверяет готовность сервиса;
  11. Redis хранит очередь задач;
  12. worker выполняет долгие agent runs;
  13. Postgres хранит состояние агента;
  14. Qdrant или другой vector store хранит embeddings;
  15. tool policy ограничивает действия агента;
  16. логи пишутся в `agent_run_log`;
  17. ошибки пишутся в `agent_error_log`;
  18. метрики пишутся в `agent_metrics`;
  19. backup сохраняет базу и конфиги;
  20. rollback возвращает предыдущую версию.

Первая версия должна уметь принимать webhook или API-запрос, создавать задачу, выполнять agent run в worker, отдавать результат, логировать ошибки и безопасно переживать перезапуск сервера.

Что понадобится

Минимальный набор:

  1. VPS на Ubuntu 22.04 или 24.04;
  2. домен или поддомен, например `agent.example.com`;
  3. SSH-доступ к серверу;
  4. отдельный deploy-пользователь;
  5. Docker и Docker Compose;
  6. Nginx или Caddy;
  7. TLS-сертификат через Let's Encrypt;
  8. Git-репозиторий с кодом агента;
  9. LLM API key или доступ к локальной модели;
  10. Postgres для состояния;
  11. Redis для очереди;
  12. Qdrant, Chroma или другой vector store, если нужен RAG;
  13. `.env.production` с секретами;
  14. тестовый запрос для проверки;
  15. список tools, которые агенту разрешено вызывать.

Для MVP не нужен Kubernetes. Docker Compose достаточно, если один сервер, понятные лимиты и есть ручной rollback.

Шаг 1. Зафиксируйте целевую архитектуру

Не начинайте с установки пакетов. Сначала опишите, что именно будет работать на сервере.

Минимальная схема:

client_or_webhook
  -> nginx_https
  -> agent_api
  -> redis_queue
  -> agent_worker
  -> postgres
  -> vector_store
  -> llm_provider

Создайте `deployment_architecture`:

id
component_key
component_type
public_access
internal_port
depends_on
healthcheck_url
is_required

Заполните компоненты:

  1. `nginx_https` - public reverse proxy;
  2. `agent_api` - private API;
  3. `agent_worker` - background worker;
  4. `postgres` - state database;
  5. `redis` - queue;
  6. `qdrant` - vector store;
  7. `backup_job` - scheduled backup;
  8. `monitoring` - health and metrics.

Проверка: публичным должен быть только HTTPS-вход, внутренние порты не должны торчать наружу.

Шаг 2. Подберите сервер

Создайте `server_inventory`.

Колонки:

id
hostname
provider
region
cpu_cores
ram_gb
disk_gb
os_version
public_ip
private_ip
purpose
created_at

Для обычного агента с облачной LLM берите:

  1. 2 CPU;
  2. 4 GB RAM;
  3. 40 GB SSD;
  4. Ubuntu 22.04 или 24.04;
  5. swap 2-4 GB;
  6. ежедневный snapshot у провайдера.

Для агента с локальной LLM требования выше:

  1. 8-16 CPU;
  2. 32-64 GB RAM;
  3. GPU, если модель должна отвечать быстро;
  4. 100-500 GB SSD под модели и индексы.

Проверка: сервер должен выдерживать не только web API, но и worker, Redis, Postgres, vector store и логи.

Шаг 3. Настройте DNS

Создайте `domain_config`.

Колонки:

id
domain
record_type
record_name
record_value
ttl
is_active
checked_at

Для поддомена:

record_type: A
record_name: agent
record_value: SERVER_PUBLIC_IP
ttl: 300

Проверьте DNS:

dig +short agent.example.com

Ожидаемый результат:

SERVER_PUBLIC_IP

Проверка: домен резолвится на IP сервера до настройки HTTPS.

Шаг 4. Создайте deploy-пользователя

Не запускайте агента от `root`.

Команды:

adduser deploy
usermod -aG sudo deploy
usermod -aG docker deploy

Создайте `deploy_user`:

id
username
home_dir
ssh_key_fingerprint
sudo_allowed
docker_allowed
created_at

Правила:

  1. вход по SSH-ключу;
  2. парольный SSH выключен после проверки;
  3. root login выключен после проверки;
  4. права на проект принадлежат `deploy`;
  5. `.env.production` читается только владельцем.

Проверка: `deploy` может выполнить `docker compose ps`, но приложение не работает от `root`.

Шаг 5. Обновите сервер и поставьте базовые пакеты

Под пользователем с sudo выполните:

sudo apt update
sudo apt upgrade -y
sudo apt install -y ca-certificates curl git ufw fail2ban htop jq unzip

Включите firewall:

sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status

Проверка: снаружи доступны только `22`, `80`, `443`, а порты `8000`, `5432`, `6379`, `6333` закрыты.

Шаг 6. Установите Docker и Compose

Команды:

curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker deploy
docker --version
docker compose version

Перезайдите по SSH, чтобы группа `docker` применилась.

Проверка:

docker run --rm hello-world

Ожидаемый результат: Docker скачивает тестовый image и завершает контейнер без ошибки.

Шаг 7. Создайте структуру проекта

Создайте директории:

sudo mkdir -p /opt/ai-agent
sudo chown -R deploy:deploy /opt/ai-agent
cd /opt/ai-agent
mkdir -p app data/postgres data/redis data/qdrant logs backups releases scripts nginx

Структура:

/opt/ai-agent
  app
  data
    postgres
    redis
    qdrant
  logs
  backups
  releases
  scripts
  nginx

Создайте `deployment_paths`:

id
path_key
absolute_path
owner
permissions
backup_required

Проверка: `deploy` может писать в `/opt/ai-agent/logs`, но `.env.production` не читается чужими пользователями.

Шаг 8. Скопируйте код агента

Вариант через Git:

cd /opt/ai-agent/app
git clone git@github.com:company/ai-agent.git .
git checkout main

Вариант через архив:

cd /opt/ai-agent/app
unzip ai-agent-release.zip

Создайте `release_registry`:

id
release_id
git_sha
branch
image_tag
deployed_by
deployed_at
status

Первый release:

release_id: 2026-05-23-001
branch: main
status: prepared

Проверка: на сервере есть код, а `git rev-parse --short HEAD` показывает конкретный commit.

Шаг 9. Подготовьте переменные окружения

Создайте `/opt/ai-agent/.env.production`.

Пример:

APP_ENV=production
APP_PORT=8000
PUBLIC_BASE_URL=https://agent.example.com

DATABASE_URL=postgresql://agent_user:CHANGE_ME@postgres:5432/agent_db
REDIS_URL=redis://redis:6379/0
VECTOR_STORE_URL=http://qdrant:6333

LLM_PROVIDER=openai
LLM_MODEL=gpt-4.1-mini
LLM_API_KEY=CHANGE_ME

AGENT_MAX_STEPS=8
AGENT_TIMEOUT_SECONDS=90
AGENT_DAILY_BUDGET_USD=20
AGENT_ENABLE_WRITE_TOOLS=false
AGENT_ENABLE_WEB_SEARCH=false

LOG_LEVEL=info
SENTRY_DSN=

Права:

chmod 600 /opt/ai-agent/.env.production

Создайте `secret_registry`:

id
secret_key
storage_place
rotation_required
last_rotated_at
owner

Проверка: `.env.production` не попадает в Git и не выводится в логи.

Шаг 10. Опишите состояние агента в базе

Создайте таблицы для production-состояния.

`agent_runs`:

id
run_id
request_id
user_id
status
input_json
output_json
error_message
started_at
finished_at
created_at

`agent_tasks`:

id
task_id
run_id
task_type
payload_json
status
attempts
next_retry_at
created_at
updated_at

`agent_tool_calls`:

id
run_id
tool_name
input_json
output_json
status
duration_ms
created_at

`agent_run_log`:

id
run_id
level
message
context_json
created_at

Проверка: после тестового запуска в базе виден run, task, tool calls и финальный статус.

Шаг 11. Напишите Dockerfile

Пример для Python/FastAPI-агента:

FROM python:3.12-slim

WORKDIR /app

RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 8000

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

Если агент на Node.js:

FROM node:22-alpine

WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE 8000
CMD ["npm", "run", "start"]

Проверка: image собирается локально на сервере командой `docker build -t ai-agent:local .`.

Шаг 12. Создайте `docker-compose.yml`

Файл `/opt/ai-agent/docker-compose.yml`:

services:
  agent_api:
    build:
      context: ./app
    image: ai-agent:production
    env_file:
      - .env.production
    command: ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
    expose:
      - "8000"
    depends_on:
      - postgres
      - redis
      - qdrant
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://localhost:8000/health"]
      interval: 30s
      timeout: 5s
      retries: 3

  agent_worker:
    image: ai-agent:production
    env_file:
      - .env.production
    command: ["python", "-m", "worker"]
    depends_on:
      - postgres
      - redis
      - qdrant
    restart: unless-stopped

  postgres:
    image: postgres:16
    environment:
      POSTGRES_DB: agent_db
      POSTGRES_USER: agent_user
      POSTGRES_PASSWORD: CHANGE_ME
    volumes:
      - ./data/postgres:/var/lib/postgresql/data
    restart: unless-stopped

  redis:
    image: redis:7-alpine
    command: ["redis-server", "--appendonly", "yes"]
    volumes:
      - ./data/redis:/data
    restart: unless-stopped

  qdrant:
    image: qdrant/qdrant:latest
    volumes:
      - ./data/qdrant:/qdrant/storage
    restart: unless-stopped

В production замените `CHANGE_ME` на пароль из `.env.production` или используйте Docker secrets.

Проверка:

cd /opt/ai-agent
docker compose config

Команда должна показать итоговый compose без ошибок.

Шаг 13. Сделайте endpoint `/health`

`/health` не должен вызывать LLM. Он должен быстро проверять базовые зависимости.

Ответ:

{
  "status": "ok",
  "app": "agent_api",
  "db": "ok",
  "redis": "ok",
  "vector_store": "ok",
  "version": "2026-05-23-001"
}

Правила:

  1. timeout до 2 секунд;
  2. без секретов;
  3. без проверки дорогих LLM-запросов;
  4. статус `degraded`, если vector store недоступен;
  5. статус `fail`, если база или Redis недоступны.

Проверка:

curl -fsS http://localhost:8000/health

Ожидаемый результат: JSON со статусом `ok`.

Шаг 14. Запустите сервисы первый раз

Команды:

cd /opt/ai-agent
docker compose build
docker compose up -d
docker compose ps

Проверьте логи:

docker compose logs --tail=100 agent_api
docker compose logs --tail=100 agent_worker

Создайте `deployment_events`:

id
release_id
event_type
status
message
created_at

Проверка: `agent_api`, `agent_worker`, `postgres`, `redis`, `qdrant` находятся в статусе running или healthy.

Шаг 15. Настройте Nginx как reverse proxy

Файл `/opt/ai-agent/nginx/agent.conf`:

server {
    listen 80;
    server_name agent.example.com;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 120s;
    }
}

Если Nginx стоит на хосте, добавьте upstream на опубликованный порт. Если Nginx в Docker, добавьте его отдельным сервисом и прокидывайте только `80` и `443`.

Проверка:

sudo nginx -t
sudo systemctl reload nginx
curl -I http://agent.example.com/health

Ожидаемый результат: HTTP-ответ от агента через домен.

Шаг 16. Включите HTTPS

Через Certbot:

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d agent.example.com

Проверьте автообновление:

sudo certbot renew --dry-run

Создайте `tls_certificate`:

id
domain
issuer
expires_at
auto_renew_enabled
checked_at

Проверка:

curl -I https://agent.example.com/health

Ожидаемый результат: `200` или `204`, сертификат валидный, редирект с HTTP на HTTPS работает.

Шаг 17. Закройте внутренние endpoints

Публичными могут быть только:

  1. `/health`;
  2. `/webhook/...`, если нужен входящий webhook;
  3. `/api/run`, если есть авторизация;
  4. `/api/result/...`, если есть авторизация.

Закрытыми должны быть:

  1. `/debug`;
  2. `/metrics`, если нет basic auth или allowlist;
  3. `/admin`;
  4. `/queue`;
  5. `/tools`;
  6. `/internal`;
  7. `/docs`, если там видны схемы приватного API.

Создайте `endpoint_policy`:

id
path_pattern
public_access
auth_required
allowed_methods
rate_limit_key
is_active

Проверка: запрос к `/internal/tools` снаружи возвращает `403` или `404`.

Шаг 18. Добавьте авторизацию API

Для MVP можно начать с API key.

Заголовок:

Authorization: Bearer YOUR_AGENT_API_KEY

Создайте `api_clients`:

id
client_key
name
api_key_hash
allowed_scopes_json
rate_limit_per_minute
is_active
created_at

Scopes:

  1. `agent.run`;
  2. `agent.result.read`;
  3. `webhook.receive`;
  4. `admin.read`;
  5. `admin.write`.

Проверка: запрос без token получает `401`, запрос с неправильным token получает `403`.

Шаг 19. Настройте входящий API-запрос

Endpoint `POST /api/run` должен принимать понятный JSON.

Пример:

{
  "request_id": "req-001",
  "user_id": "u-123",
  "task_type": "answer_question",
  "input": {
    "question": "Как подключить агента к Telegram?",
    "context": "Пользователь на тарифе Pro"
  }
}

Ответ API:

{
  "run_id": "run-001",
  "status": "queued"
}

Правила:

  1. API не выполняет долгий agent run синхронно;
  2. API кладет задачу в очередь;
  3. worker забирает задачу;
  4. результат можно получить по `GET /api/runs/{run_id}`;
  5. каждый запрос имеет `request_id` для идемпотентности.

Проверка: повторный запрос с тем же `request_id` не создает дубль run.

Шаг 20. Настройте очередь задач

Создайте `queue_config`.

Колонки:

id
queue_name
worker_count
max_retries
timeout_seconds
dead_letter_enabled
is_active

Очереди:

  1. `agent_runs` - обычные задачи;
  2. `agent_long_runs` - долгие задачи;
  3. `embeddings` - индексация документов;
  4. `webhooks` - входящие webhook;
  5. `dead_letter` - задачи после ошибок.

Правила:

  1. timeout agent run: 90-180 секунд;
  2. retries: 2-3;
  3. exponential backoff;
  4. dead letter после последней ошибки;
  5. отдельная очередь для embeddings, чтобы они не блокировали ответы.

Проверка: если LLM API временно недоступен, задача повторяется, а не теряется.

Шаг 21. Настройте worker

Worker должен выполнять задачи отдельно от web API.

Минимальная логика:

  1. взять задачу из Redis;
  2. создать запись в `agent_runs`;
  3. загрузить policy;
  4. собрать prompt;
  5. вызвать LLM;
  6. вызвать разрешенные tools;
  7. сохранить результат;
  8. обновить статус;
  9. записать логи;
  10. отправить webhook о завершении, если нужен.

Статусы run:

  1. `queued`;
  2. `running`;
  3. `waiting_tool`;
  4. `completed`;
  5. `failed`;
  6. `cancelled`;
  7. `timeout`.

Проверка: остановите worker на минуту, создайте задачу, включите worker и убедитесь, что задача обработалась.

Шаг 22. Подключите Postgres

Проверьте подключение из контейнера:

docker compose exec agent_api python - <<'PY'
import os
print(os.environ["DATABASE_URL"])
PY

Миграции запускайте отдельной командой:

docker compose exec agent_api python -m app.migrate

Создайте `database_migrations`:

id
migration_name
batch
status
executed_at

Правила:

  1. миграции запускаются до переключения трафика;
  2. destructive migrations не делаются без backup;
  3. rollback миграций проверяется отдельно;
  4. индексы добавляются на `run_id`, `request_id`, `status`, `created_at`;
  5. большие таблицы логов чистятся по retention policy.

Проверка: приложение стартует после миграций, а старые runs читаются.

Шаг 23. Подключите vector store

Если агент использует RAG, поднимите Qdrant или подключите внешний vector DB.

Коллекция:

collection_name: agent_knowledge
vector_size: зависит от embedding-модели
distance: cosine

Создайте `vector_collections`:

id
collection_name
embedding_model
vector_size
distance
documents_count
last_indexed_at

Правила:

  1. embeddings пересоздаются при смене embedding-модели;
  2. chunks имеют `source_url`;
  3. удаленные документы выключаются через `is_active`;
  4. индексация идет отдельной очередью;
  5. API агента не должен падать, если идет reindex.

Проверка: тестовый вопрос находит chunk из базы знаний и возвращает ссылку на источник.

Шаг 24. Ограничьте tools

Создайте `tool_policy`.

Колонки:

id
tool_name
enabled
requires_approval
allowed_scopes_json
blocked_inputs_json
max_calls_per_run
timeout_seconds

Правила для первого запуска:

  1. `search_knowledge_base` включен;
  2. `read_customer_profile` только read-only;
  3. `send_message` выключен или требует approval;
  4. `write_to_crm` выключен;
  5. `delete_record` выключен;
  6. `refund_payment` выключен;
  7. `web_search` выключен, если не нужен;
  8. каждый tool имеет timeout;
  9. каждый tool пишет лог.

Проверка: агент не может выполнить write-действие без явного разрешения.

Шаг 25. Добавьте rate limit

Создайте `rate_limit_rules`.

Колонки:

id
scope
limit_per_minute
limit_per_day
burst
action_on_limit
is_active

Стартовые лимиты:

  1. `api_client`: 60 запросов в минуту;
  2. `user`: 20 запусков в минуту;
  3. `agent_run`: 8 LLM calls на run;
  4. `tool_call`: 20 tool calls на run;
  5. `daily_budget`: лимит расходов в день.

Проверка: серия из 100 запросов за минуту получает `429`, а сервер не ложится.

Шаг 26. Настройте бюджет LLM

Создайте `llm_usage_log`.

Колонки:

id
run_id
provider
model
input_tokens
output_tokens
estimated_cost_usd
created_at

Создайте `budget_policy`:

id
scope
daily_limit_usd
monthly_limit_usd
action_on_limit
is_active

Правила:

  1. записывать tokens после каждого LLM call;
  2. останавливать новые runs при превышении дневного лимита;
  3. показывать понятную ошибку вместо падения;
  4. использовать дешевую модель для классификации;
  5. дорогую модель включать только для сложных задач.

Проверка: тестовый лимит `0.01` останавливает новые дорогие запросы.

Шаг 27. Настройте логи

Создайте `agent_error_log`.

Колонки:

id
run_id
error_type
error_message
stack_hash
context_json
created_at

Логируйте:

  1. старт run;
  2. завершение run;
  3. LLM request без секретов;
  4. LLM error;
  5. tool call;
  6. tool error;
  7. timeout;
  8. retry;
  9. rate limit;
  10. guardrail block.

В Docker смотрите:

docker compose logs --tail=200 agent_api
docker compose logs --tail=200 agent_worker

Проверка: ошибка LLM API видна в логах, но API key там не появляется.

Шаг 28. Настройте метрики

Создайте `agent_metrics`.

Колонки:

id
metric_date
total_runs
completed_runs
failed_runs
timeout_runs
avg_latency_ms
p95_latency_ms
total_cost_usd
tool_errors
created_at

Смотрите:

  1. процент ошибок;
  2. p95 latency;
  3. среднюю стоимость run;
  4. количество timeout;
  5. длину очереди;
  6. количество retries;
  7. частоту guardrails;
  8. нагрузку CPU/RAM/disk.

Проверка: после 10 тестовых runs метрики заполняются и показывают не нули.

Шаг 29. Добавьте алерты

Создайте `alert_rules`.

Колонки:

id
rule_key
condition
severity
target_channel
is_active

Первый набор:

  1. `/health` недоступен 2 минуты;
  2. error rate выше 10%;
  3. очередь больше 100 задач;
  4. disk usage выше 80%;
  5. дневной LLM budget выше 80%;
  6. Postgres недоступен;
  7. Redis недоступен;
  8. сертификат истекает меньше чем через 14 дней.

Проверка: временно остановите `agent_api` и убедитесь, что alert создается.

Шаг 30. Настройте backup

Создайте `/opt/ai-agent/scripts/backup.sh`.

#!/usr/bin/env bash
set -euo pipefail

BACKUP_DIR="/opt/ai-agent/backups/$(date +%Y-%m-%d_%H-%M-%S)"
mkdir -p "$BACKUP_DIR"

docker compose exec -T postgres pg_dump -U agent_user agent_db > "$BACKUP_DIR/postgres.sql"
tar -czf "$BACKUP_DIR/qdrant.tar.gz" -C /opt/ai-agent/data qdrant
cp /opt/ai-agent/.env.production "$BACKUP_DIR/env.production.copy"

Права:

chmod 700 /opt/ai-agent/scripts/backup.sh

Создайте `backup_runs`:

id
backup_id
status
backup_path
size_mb
started_at
finished_at

Проверка: backup создается, а восстановление проверено на тестовой папке или staging-сервере.

Шаг 31. Настройте log rotation

Если логи пишутся в файлы, создайте `/etc/logrotate.d/ai-agent`.

/opt/ai-agent/logs/*.log {
    daily
    rotate 14
    compress
    missingok
    notifempty
    copytruncate
}

Если логи только Docker:

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "50m",
    "max-file": "5"
  }
}

Проверка: логи не растут бесконечно и не забивают диск.

Шаг 32. Подготовьте rollback

Создайте `rollback_plan`.

Колонки:

id
release_id
previous_release_id
image_tag
db_backup_id
rollback_command
tested_at

Простой rollback через image tag:

cd /opt/ai-agent
docker compose pull
docker compose up -d

Более понятный вариант:

docker tag ai-agent:previous ai-agent:production
docker compose up -d agent_api agent_worker

Правила:

  1. храните предыдущий image;
  2. храните backup базы до миграций;
  3. не удаляйте старый `.env.production`;
  4. проверяйте `/health` после rollback;
  5. фиксируйте rollback в `deployment_events`.

Проверка: на staging выполните rollback до предыдущей версии и убедитесь, что API отвечает.

Шаг 33. Создайте deploy-скрипт

Файл `/opt/ai-agent/scripts/deploy.sh`:

#!/usr/bin/env bash
set -euo pipefail

cd /opt/ai-agent/app
git fetch origin
git checkout main
git pull --ff-only

cd /opt/ai-agent
./scripts/backup.sh
docker compose build agent_api
docker compose up -d
docker compose ps
curl -fsS https://agent.example.com/health

Права:

chmod 700 /opt/ai-agent/scripts/deploy.sh

Проверка: deploy-скрипт либо завершается успешно, либо падает до переключения на нерабочее состояние.

Шаг 34. Проверьте безопасность секретов

Проверки:

grep -R "LLM_API_KEY" /opt/ai-agent/logs || true
find /opt/ai-agent -name ".env*" -ls
ls -la /opt/ai-agent/.env.production

Правила:

  1. API keys не в Git;
  2. API keys не в Dockerfile;
  3. API keys не в логах;
  4. `.env.production` имеет права `600`;
  5. backup с `.env` хранится отдельно и защищенно;
  6. при утечке ключ можно быстро заменить;
  7. debug mode выключен в production.

Проверка: ни один публичный endpoint не возвращает env, stack trace или конфиг.

Шаг 35. Проверьте сетевую поверхность

На сервере:

sudo ss -tulpn
sudo ufw status numbered

Снаружи:

nmap -Pn agent.example.com

Ожидаемо открыты:

  1. `80`;
  2. `443`;
  3. `22`, если SSH не вынесен на другой порт или не закрыт allowlist.

Не должны быть открыты:

  1. `5432`;
  2. `6379`;
  3. `6333`;
  4. `8000`;
  5. внутренние admin ports.

Проверка: Postgres, Redis и vector store недоступны из интернета.

Шаг 36. Сделайте тестовый запуск агента

Отправьте тестовый запрос:

curl -sS https://agent.example.com/api/run \
  -H "Authorization: Bearer YOUR_AGENT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "request_id": "test-001",
    "user_id": "test-user",
    "task_type": "answer_question",
    "input": {
      "question": "Составь короткий ответ клиенту о статусе заявки"
    }
  }'

Проверьте:

  1. API вернул `run_id`;
  2. task появилась в Redis;
  3. worker взял task;
  4. run перешел в `running`;
  5. LLM вызван один раз;
  6. result записан в Postgres;
  7. run перешел в `completed`;
  8. логи не содержат секретов;
  9. стоимость записана;
  10. `/api/runs/{run_id}` возвращает результат.

Проверка: весь путь от API до результата работает без ручного запуска команд.

Шаг 37. Проверьте отказоустойчивость

Сделайте три теста.

Остановите worker:

docker compose stop agent_worker

Создайте задачу, затем включите worker:

docker compose start agent_worker

Остановите Redis:

docker compose stop redis

Проверьте `/health`.

Остановите LLM-доступ, например временно подставьте неверный ключ на staging.

Ожидаемые реакции:

  1. без worker задачи ждут в очереди;
  2. без Redis `/health` становится `fail`;
  3. при ошибке LLM задача получает retry;
  4. после max retries задача уходит в dead letter;
  5. API не раскрывает stack trace клиенту.

Проверка: агент деградирует управляемо, а не ломается молча.

Шаг 38. Настройте systemd для compose

Чтобы Docker Compose поднимался после перезагрузки, создайте unit.

Файл `/etc/systemd/system/ai-agent.service`:

[Unit]
Description=AI Agent Docker Compose
Requires=docker.service
After=docker.service

[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/ai-agent
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down
TimeoutStartSec=0

[Install]
WantedBy=multi-user.target

Команды:

sudo systemctl daemon-reload
sudo systemctl enable ai-agent
sudo systemctl start ai-agent
sudo systemctl status ai-agent

Проверка: после `sudo reboot` сервисы снова поднимаются.

Шаг 39. Настройте staging перед production

Если агент будет работать с клиентами, сделайте staging.

Отличия staging:

  1. отдельный домен `agent-staging.example.com`;
  2. отдельная база;
  3. отдельные API keys;
  4. маленький LLM budget;
  5. тестовые tools;
  6. fake webhook;
  7. отключенные write-действия;
  8. тестовая база знаний.

Создайте `environment_registry`:

id
env_key
base_url
database_name
llm_budget_usd
write_tools_enabled
created_at

Проверка: staging не может случайно отправить сообщение реальному клиенту.

Шаг 40. Минимальный результат для запуска

MVP готов, если выполнены условия:

  1. домен указывает на сервер;
  2. HTTPS работает;
  3. Docker Compose поднимает все сервисы;
  4. `/health` возвращает `ok`;
  5. API требует авторизацию;
  6. внутренние endpoints закрыты;
  7. задача создается через `/api/run`;
  8. worker выполняет задачу;
  9. результат сохраняется;
  10. logs и error logs пишутся;
  11. Postgres и Redis не доступны из интернета;
  12. vector store работает, если нужен RAG;
  13. tool policy запрещает опасные действия;
  14. rate limit возвращает `429`;
  15. backup создается;
  16. rollback проверен;
  17. сервисы стартуют после reboot;
  18. LLM budget ограничен;
  19. alert приходит при падении `/health`;
  20. секреты не попадают в логи.

Финальная проверка: перезагрузите сервер, дождитесь запуска, отправьте тестовый `/api/run`, получите результат, проверьте логи, метрики и backup. Если все проходит без ручного запуска worker, агент готов к ограниченному production-трафику.

Что нельзя автоматизировать в первой версии

В первой версии не автоматизируйте:

  1. самостоятельное изменение production-конфига агентом;
  2. выдачу новых API keys агентом;
  3. удаление данных из Postgres;
  4. удаление vector collection;
  5. изменение DNS;
  6. изменение firewall;
  7. запуск shell-команд по просьбе пользователя;
  8. write-tools без approval;
  9. оплату, возвраты и финансовые операции;
  10. auto-deploy без тестов;
  11. auto-rollback без понятного условия;
  12. чтение `.env.production` через tool;
  13. публичный доступ к debug endpoints;
  14. обучение на production-логах без очистки данных;
  15. хранение персональных данных без retention policy.

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

Частые вопросы

Можно ли запускать ИИ-агента без Docker?

Можно, через systemd и виртуальное окружение, но Docker Compose проще для повторяемого запуска: отдельно web API, worker, Redis, Postgres и vector store.

Нужно ли сразу использовать Kubernetes?

Нет. Для одного сервера и первого production MVP Docker Compose обычно достаточно. Kubernetes имеет смысл, когда нужны несколько серверов, autoscaling, сложная сеть и отдельная команда эксплуатации.

Где хранить ключи от LLM API?

В `.env.production`, secret manager или Docker secrets. Нельзя хранить ключи в Git, Dockerfile, публичных логах, prompt-текстах и админских debug endpoints.

Что делать, если агент начал ошибаться после релиза?

Остановите auto-send или write-tools, откатите image на предыдущий tag, проверьте `agent_error_log`, сравните prompts и tools, затем прогоните тестовые runs на staging.

Как понять, что сервер готов к реальным пользователям?

Сервер готов, если проходит полный тест: HTTPS, auth, `/health`, queue, worker, Postgres, vector store, логи, rate limit, backup, rollback, restart после reboot и отсутствие открытых внутренних портов.

Дальше по теме

Похожие материалы