Установка CRM-агента

Не хотите читать всё это?

Просто скиньте в любой ИИ-чат (Claude, ChatGPT и т.д.) ссылку на https://pastukhov.com/agents/crm/install.md или на https://pastukhov.com/llms.txt и попросите сгенерировать конфигурационные файлы и команды. Он прочитает документацию, задаст несколько вопросов о вашей настройке и выдаст готовую конфигурацию. Экономьте время — пусть модель читает за вас.

Вы также можете связаться со мной через Telegram — я всегда рад помочь. И это не просто вежливость — мне действительно нравится общаться с единомышленниками, особенно если вы так же увлечены программированием, как и я.

«CRM-агент» — это CRM на вашем сервере, в которой данные ведёт ИИ-агент, а вы наблюдаете и командуете. Разворачивается он одним контейнером Docker, а отдельная база данных не обязательна: по умолчанию внутри уже есть встроенная. Рядом по желанию ставится ваш Pastukhov Agent — тогда CRM можно управлять словами в чате, а без него всё, кроме чата с агентом, работает как обычно.

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

  • Сервер или компьютер с Docker — подойдёт Windows, Linux или macOS, а для постоянной работы достаточно недорогого сервера.
  • Один свободный порт для интерфейса (в примерах ниже — 3991). Отдельная база данных не нужна: если не указывать строку подключения, продукт заведёт встроенную базу сам.
  • Логин и пароль первого входа. Их можно задать заранее переменными CRM_APP_LOGIN и CRM_APP_PASSWORD; если не задавать, администратором станет первый зарегистрировавшийся в интерфейсе.
  • Ключ управления для агента (CRM_APP_HASH) — если вы хотите, чтобы ваш ИИ-агент менял данные сам, а не вы вручную. В переменной хранится не сам ключ, а его отпечаток: ключ вы придумываете один раз и выдаёте агенту, а продукт запоминает отпечаток и по нему узнаёт его. Пока отпечаток не задан, изменения запрещены, а просмотр в интерфейсе работает.
  • По желанию — адрес и ключ вашего Pastukhov Agent. Без них работает всё, кроме чата с ИИ-агентом внутри продукта.

Установка через Docker Compose

Создайте файл compose.yml с таким содержимым. Служба здесь одна: отдельная база данных продукту не нужна, поэтому всё умещается в один контейнер. Постоянных папок две — в одной живут данные, в другой описания ваших скриптов.

services:
  crmagent-ru:
    image: maxpastukhov/crm-agent:min-latest
    container_name: crmagent-ru
    ports:
      - "3991:80"
    volumes:
      - crmagent-data-ru:/data
      # The scripts yml config tree (apps/crm) — a named volume so API-edited
      # definitions survive container recreation (seeded on first boot).
      - crmagent-config-ru:/project/apps/crm
    environment:
      - ASPNETCORE_ENVIRONMENT=Production
      - ASPNETCORE_URLS=http://+:80
      - CRM_APP_BRAND=pastukhov
      - CRM_APP_DATA=/data
      # CRM_APP_BASE_PATH=/crm  # serve from a first-level subfolder (see ../subfolder-hosting.md)
      # The image ships the minimal idle-memory runtime posture (workstation GC,
      # non-concurrent GC, 1 MB GC regions, W^X and diagnostics IPC off, glibc arenas
      # capped — see the app Dockerfile and dev/idle-memory.md). Compose entries here
      # override the image, e.g. put Server GC back on for a busy instance:
      # - DOTNET_gcServer=1
    restart: unless-stopped
    sysctls:
      fs.inotify.max_user_watches: "524288"
      fs.inotify.max_user_instances: "512"

volumes:
  crmagent-data-ru:
  crmagent-config-ru:

Разберём построчно, что здесь написано и зачем:

  • image — русская сборка продукта с русским интерфейсом и названием «CRM-агент».
  • ports — адрес, по которому откроется интерфейс: 3991 снаружи, 80 внутри контейнера. Число снаружи можно взять любое свободное.
  • volumes — две постоянные папки. В /data живут база и все данные, в /project/apps/crm — описания ваших скриптов и их настройки. Без этих папок всё исчезнет при пересоздании контейнера, а описания скриптов пришлось бы заводить заново.
  • CRM_APP_BRAND — выбор бренда: pastukhov включает русское название и русский язык по умолчанию.
  • CRM_APP_DATA — та самая постоянная папка внутри контейнера, куда продукт складывает всё своё: она же подключена томом выше.
  • CRM_APP_BASE_PATH — закомментированная строка для размещения в подпапке сайта: раскомментируйте, если хотите открывать CRM по адресу вида ваш-сайт/crm.
  • Комментарии про память и строка # - DOTNET_gcServer=1 — подсказка для нагруженного экземпляра: в образе уже заданы настройки минимального потребления, а эту строку можно раскомментировать, если одновременной работы много (подробнее — в разделе «Экономия ресурсов в простое»).
  • restart — перезапуск после перезагрузки сервера, чтобы CRM снова поднялась сама.
  • sysctls — две настройки ядра Linux, увеличивающие лимит наблюдения за файлами: без них продукт хуже замечает изменения в своих папках на больших объёмах.

Затем запустите:

docker compose up -d

Интерфейс появится на порту 3991: http://<адрес-сервера>:3991.

Запуск одной командой

Если файл с настройками заводить не хочется, всё то же самое делается одной командой docker run:

docker run -d \
  --name crmagent-ru \
  -p 3991:80 \
  -v crmagent-data-ru:/data \
  -v crmagent-config-ru:/project/apps/crm \
  -e ASPNETCORE_ENVIRONMENT=Production \
  -e ASPNETCORE_URLS=http://+:80 \
  -e CRM_APP_BRAND=pastukhov \
  -e CRM_APP_DATA=/data \
  --sysctl fs.inotify.max_user_watches=524288 \
  --sysctl fs.inotify.max_user_instances=512 \
  --restart unless-stopped \
  maxpastukhov/crm-agent:min-latest

Остальные переменные удобно передать файлом через флаг --env-file .env — так их проще менять, не переписывая длинную команду.

Экономия ресурсов в простое

Пока в CRM никто не работает, продукт не тратит ни процессор, ни лишнюю память. Постоянных фоновых проверок у него нет: он просыпается по событию — пришёл запрос, пришло письмо, наступил заранее назначенный срок. Замер на сервере показал в покое 0,0–0,3 % процессора; прежняя версия тратила 0,77 % постоянно.

Память тоже возвращается серверу. Если в CRM полных 15 минут ничего не происходит, накопленные данные освобождаются. Срок настраивается переменной CRM_APP_IDLE_TRIM_MINUTES: по умолчанию 15 минут, 0 выключает. Посмотреть, сколько продукт занимает сейчас, можно по служебному адресу /api/health — он защищён входом, как и остальные.

В образе уже заданы настройки минимального потребления памяти, поэтому отдельно настраивать ничего не нужно. Если экземпляр нагруженный и хочется запаса на пиках, в compose.yml есть закомментированная строка # - DOTNET_gcServer=1: раскомментируйте её.

Переменные окружения

Настройки задаются переменными окружения — их прописывают один раз в compose.yml и меняют без правки кода. Почти все имена начинаются с CRM_APP_; для чата с агентом имена, наоборот, привычные — без приставки.

ПеременнаяЧто делает
CRM_APP_DBвыбор базы данных. Не указана — продукт работает на встроенной базе в файле /data/data.db; указана строка подключения — работает на PostgreSQL
CRM_APP_DATAпапка постоянных данных: база, ключи входа, настройки бренда. По умолчанию /data
CRM_APP_BRANDpastukhov — русское название продукта и русский язык интерфейса по умолчанию
CRM_APP_BASE_PATHразмещение в подпапке сайта, например /crm; не задано — работа в корне домена
CRM_APP_HASHотпечаток ключа управления: по нему ваш ИИ-агент меняет данные по API (адресам управления, к которым он обращается). Хранится в виде необратимой суммы SHA-256; переменная не задана — изменения запрещены, а просмотр работает
CRM_APP_LOGIN, CRM_APP_PASSWORDучётная запись администратора, создаваемая при запуске. Если их не задавать, администратором становится первый зарегистрировавшийся в интерфейсе
CRM_APP_INTAKE_ALLOW_ORIGINсписок сайтов, с которых принимаются заявки. Не указан — заявки принимаются с любых сайтов; указан — только перечисленные
CRM_APP_COMPRESSIONсжатие ответов сервера. Включено по умолчанию, =0 выключает
CRM_APP_JOB_KEEP_DAYSсколько дней хранить завершённые фоновые задачи. По умолчанию 30
CRM_APP_IDLE_TRIM_MINUTESсколько минут полного покоя ждать, прежде чем освободить накопленные данные и вернуть память серверу. По умолчанию 15, 0 выключает
CRM_APP_SEARCH_INDEX_FOLDERпапка, где лежит поисковый список для поиска по всему продукту. По умолчанию — рядом с данными, в папке search-index
CRM_APP_BOOT_FULL=1 — полная проверка устройства базы при запуске. Нужна для диагностики, обычно не требуется
CRM_APP_SSL=auto — продукт сам выпускает и подписывает сертификат HTTPS для доступа по прямому адресу с портом. Если перед продуктом стоит ваш прокси со своим сертификатом, эта переменная не нужна
AGENT_API_URL, AGENT_API_KEYадрес и ключ вашего Pastukhov Agent: с ними внутри CRM появляется чат с ИИ-агентом. Не заданы — чат скрыт, всё остальное работает

Файл .env рядом с проектом

Часть настроек и все секреты удобнее держать не в переменных окружения, а в файле .env в корне папки проекта — внутри контейнера это /project/.env. Записи в нём простые, по одной в строке: CRM_APP_HASH=ваш-отпечаток; строки, начинающиеся с #, служат пояснениями. Чтобы файл был виден контейнеру, подключите его томом, а если он лежит в другом месте — укажите путь переменной CRM_APP_ENV_FILE.

Файл читается при запуске, а дальше перечитывается на ходу: правки в нём применяются без перезапуска и видны всем программам, которые запускает продукт. Настройки, которые читаются только при запуске (база данных, бренд, адрес продукта, адрес и ключ агента), вступят в силу после перезапуска. Если одна и та же настройка задана и в файле, и в окружении контейнера, применяется значение из файла. Файл продукт сам добавляет в список исключений git, чтобы секреты не попали в репозиторий.

Не путайте этот файл с тем, который передают при запуске контейнера флагом --env-file: там Docker читает файл на вашем компьютере и просто расставляет переменные, а .env рядом с проектом читает и перечитывает сам продукт.

Размещение в подпапке сайта

Продукт можно повесить не на корень домена, а на подпапку — например, https://ваш-сайт/crm. Есть два способа, и они не смешиваются.

  • Просто указать папку. Задайте CRM_APP_BASE_PATH=/crm — продукт сам отрежет приставку и перенаправит старые адреса в новый вид. Служебные адреса проверки домена (/.well-known/) при этом остаются в корне.
  • Отдать папку вашему прокси. В этом случае в контейнере ничего менять не нужно: прокси сообщает продукту приставку заголовком X-Forwarded-Prefix. Так удобнее, когда у вас уже настроен nginx или похожий сервер.

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

# переход на WebSocket (в общем разделе http {})
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen 443 ssl;
    server_name host.tld;

    client_max_body_size 100m;                       # загрузка файлов и вставленных картинок

    location /crm/ {
        proxy_pass http://crmagent:80/;              # слэш на конце отрезает приставку подпапки
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Prefix /crm;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;      # живые обновления: /appHub и /agentChatHub
        proxy_set_header Connection $connection_upgrade;
        proxy_read_timeout 3600s;                    # длинные ответы чата
        proxy_send_timeout 3600s;
        proxy_buffering off;                         # потоковая передача ответов
    }
}

Оба способа и проверка изоляции между папками описаны в файле install/subfolder-hosting.md рядом с продуктом.

Первый вход

Откройте интерфейс в браузере. Если вы задали CRM_APP_LOGIN и CRM_APP_PASSWORD, входите этими данными; иначе первый зарегистрировавшийся становится администратором, после чего свободная регистрация закрывается — посторонний в вашу установку уже не попадёт. Сессия входа живёт 90 дней, так что каждый день логиниться не придётся. Если продукт стоит за единым входом вашей организации (когда логин проверяет внешняя система), пользователи создаются автоматически при первом обращении.

Установка через Pastukhov MultiAgent

Если у вас несколько серверов, удобнее ставить продукт из Pastukhov MultiAgent: он сам поднимает контейнер, выдаёт постоянный адрес и HTTPS, подключает базу. «CRM-агент» есть в каталоге продуктов (порт 6080). MultiAgent передаёт продукту переменные CRM_APP_SSL, CRM_APP_DB и отпечаток ключа управления CRM_APP_HASH, а связанный Pastukhov Agent получает адрес продукта и ключ в переменных CRM_APP_URL и CRM_APP_KEY — по ним он и обращается к CRM. Подробнее о самом MultiAgent — на странице MultiAgent.

Лицензия и обновления

Пробный период — 30 дней бесплатно, без ограничений внутри. Цены те же, что у соседних продуктов: персональная — 19 700 ₽, корпоративная — 49 700 ₽, сервисная — 97 000 ₽, все пожизненные, с 12 месяцами бесплатных обновлений. Скажем честно: лицензия ограничивает ровно одно действие — отправку сообщения в чат с ИИ-агентом. Клиентская база, хронология, качество данных, импорт и выгрузки, свои поля, лиды, сделки, деньги, маркетинг, коммуникации, сервис, экраны и управление по API работают без неё. Подробнее — на странице Лицензирование.

Дальше стоит заглянуть в Начало работы — там коротко о том, как продукт устроен и с чего начать.

← Вернуться на главную раздела CRM-агент