Как и любого уважающего себя молодого человека меня нередко преследуют мысли об открытии своего собственного технологического стартапа, ну или хотя бы магазина рыболовных приспособлений у метро. Но каждый раз все разбивается о суровые реалии нашего мира. Любое дело подразумевает наличие команды, учет товаров, обслуживание клиентов и многое другое. 

А как обслужить клиента и удобно хранить информацию о нем? Для этого существует CRM — система управления отношениями с клиентами, которая помогает бизнесу собирать, хранить и использовать данные о клиентах, автоматизировать продажи и улучшать обслуживание. 

Многие существующие на рынке CRM-решения выставляют огромный ценник и, на фоне не всегда высокой маржинальности реализуемой услуги или товара, многие идеи теряют свою актуальность в силу существенных издержек, ведь нередко поддержание работоспособности подобных программных решений занимает значимую часть общих расходов компании. Однако нет большей неудачи, чем перестать пытаться. В гонке за сокращением расходов существующей только в моем воображении компании, был найден следующий выход.

Конечно, кроме шуток, нужно отдавать себе отчет в том, что найти мощную, бесплатную и отказоустойчивую систему — утопия, но для организации работы на первых этапах, прежде чем усиливаться и переезжать на более мощные серверы, можно попробовать пойти по пути наименьшего сопротивления. Поэтому поступаем следующим образом: создадим бесплатную виртуальную машину и Objective storage с помощью Evolution free tier. Конфигурация следующая:

Для тестов и запуска первого проекта этого хватит с головой. А дальше всегда можно переместить программную инфраструктуру на более мощное железо и увеличить объем ресурсов. Ниже подробная инструкция о том, как и что делать.

Шаг 1. Разверните ресурсы в облаке

Создайте группу безопасности с названием crm-service и добавьте в нее правила.

Правило входящего трафика:

  • Протокол: TCP.

  • Порт: 443.

  • Тип источника: IP-адрес.

  • Источник: «ваш ip/32»

Правило входящего трафика:

  • Протокол: TCP.

  • Порт: 80.

  • Тип источника: IP‑адрес.

  • Источник: 0.0.0.0/0.

Правило исходящего трафика:

  • Протокол: Любой.

  • Тип адресата: IP‑адрес.

  • Адресат: 0.0.0.0/0.

Обращаю ваше внимание, в группах безопасности не указывайте 0.0.0.0/0, иначе весь интернет будет ломиться на ваши порты, воспользуйтесь сервисом и укажите личный ip‑адрес. Также рекомендую сразу настраивать личный домен.

На странице Сети → Группы безопасности убедитесь, что отображается группа безопасности crm-service со статусом Создана.

Создайте бесплатную виртуальную машину со следующими параметрами:

  • Название: crm-service.

  • Образ: публичный образ Ubuntu 22.04.

  • Подключить публичный IP: оставьте опцию включенной.

  • Тип IP: оставьте прямой IP-адрес.

  • Группы безопасности: SSH-access_ru.AZ-1 и crm-service.

  • Логин: crm.

  • Метод аутентификации: Публичный ключ и Пароль.

  • Публичный ключ: укажите ключ, созданный ранее.

  • Пароль: задайте пароль.

  • Имя хоста: crm-service.

На странице Инфраструктура → Виртуальные машины убедитесь, что отображается виртуальная машина crm-service со статусом Запущена.

Создайте бакет в Object Storage со следующими параметрами

  • Название: crm-service.

  • Максимальный размер: 15 ГБ.

  • Класс хранения по умолчанию: Стандартный.

  • Перейдите в раздел Object Storage API. Сохраните значения ID тенанта и Регион.

Создайте сервисный аккаунт со следующими параметрами:

  • Название: crm-service.

  • Описание: Аккаунт Object Storage.

  • Проект: Пользователь сервисов.

  • Evolution Object Storage Роли: s3e.viewer, s3e.editor.

Сгенерируйте ключи доступа для сервисного аккаунта. Сохраните Secret ID и Secret Key.

Шаг 2. Настройте окружение на виртуальной машине

Подключитесь к виртуальной машине crm-service через серийную консоль или по SSH.

Обновите систему и установите необходимые зависимости:

sudo apt update && sudo apt upgrade -y &&\

sudo apt install -y curl apt-transport-https\

                         ca-certificates\

                         software-properties-common\

                         gnupg2\

                         lsb-release

Установите Docker:

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt update

sudo apt install docker-ce docker-ce-cli containerd.io -y

Дайте текущему пользователю права на запуск Docker:

sudo usermod -aG docker $USER
newgrp docker

Установите Docker Compose:

sudo apt-get install docker-compose-plugin -y

Проверьте, что Docker и Docker Compose установлены корректно:

docker --version
docker compose version

Установите сервер nginx:

sudo apt install nginx -y
sudo systemctl start nginx
sudo systemctl enable nginx

Установите Let’s Encrypt и плагин для nginx:

sudo apt install certbot python3-certbot-nginx -y

Шаг 3. Настройте nginx и HTTPS

Настройте межсетевой экран:

sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable

Создайте конфигурационный файл:

sudo nano /etc/nginx/sites-available/crm.conf

Вставьте конфигурацию, заменив <IP-ADDRESS> на IP-адрес вашей виртуальной машины:

server {
   listen 80;
   server_name crm.<IP-ADDRESS>.nip.io www.crm.<IP-ADDRESS>.nip.io;

   # Proxy all other requests to Twenty CRM
   location / {
      proxy_pass http://localhost:3000;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection 'upgrade';
      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_cache_bypass $http_upgrade;
      proxy_read_timeout 300;
      proxy_connect_timeout 300;
      proxy_send_timeout 300;
   }
}

Примените конфигурацию и перезапустите nginx:

sudo ln -sf /etc/nginx/sites-available/crm.conf /etc/nginx/sites-enabled/crm.conf
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx

Проверьте, что nginx работает:

sudo systemctl status nginx

Cервис nginx должен быть в статусе active (running).

Перейдите по адресу http://crm.<IP-ADDRESS>.nip.io. Откроется страница с текстом «502 Bad Gateway».

Запустите команду для выпуска SSL-сертификата:

sudo certbot --nginx -d crm.<IP-ADDRESS>.nip.io --redirect --agree-tos -m <EMAIL>

Где:

  • <IP-ADDRESS> — IP-адрес вашей виртуальной машины.

  • <EMAIL> — email для регистрации сертификата.

После выпуска сертификата перейдите по адресу https://crm.<IP-ADDRESS>.nip.io. Откроется страница с текстом «502 Bad Gateway». В свойствах сайта браузер отметит соединение как безопасное.

Шаг 4. Разверните серверное приложение Twenty CRM с помощью Docker Compose

Создайте структуру проекта:

mkdir ~/twenty-crm
cd ~/twenty-crm

Сгенерируйте уникальный ключ и сохраните его, он понадобится в дальнейшем:

openssl rand -base64 32

Сгенерируйте пароль для базы данных и сохраните его, он понадобится в дальнейшем:

openssl rand -base64 15

Создайте файл docker-compose.yml:

nano docker-compose.yml

Вставьте код:

Длинный код
name: twenty

services:
  server:
    image: twentycrm/twenty:${TAG:-latest}
    volumes:
      - server-local-data:/app/packages/twenty-server/.local-storage
    ports:
      - "3000:3000"
    environment:
      NODE_PORT: 3000
      PG_DATABASE_URL: postgres://${PG_DATABASE_USER:-postgres}:${PG_DATABASE_PASSWORD:-postgres}@${PG_DATABASE_HOST:-db}:${PG_DATABASE_PORT:-5432}/default
      SERVER_URL: ${SERVER_URL}
      REDIS_URL: ${REDIS_URL:-redis://redis:6379}
      DISABLE_DB_MIGRATIONS: ${DISABLE_DB_MIGRATIONS}
      DISABLE_CRON_JOBS_REGISTRATION: ${DISABLE_CRON_JOBS_REGISTRATION}
      STORAGE_TYPE: ${STORAGE_TYPE}
      STORAGE_S3_REGION: ${STORAGE_S3_REGION}
      STORAGE_S3_NAME: ${STORAGE_S3_NAME}
      STORAGE_S3_ENDPOINT: ${STORAGE_S3_ENDPOINT}
      STORAGE_S3_ACCESS_KEY_ID: ${STORAGE_S3_ACCESS_KEY_ID}
      STORAGE_S3_SECRET_ACCESS_KEY: ${STORAGE_S3_SECRET_ACCESS_KEY}
      APP_SECRET: ${APP_SECRET:-replace_me_with_a_random_string}
      # MESSAGING_PROVIDER_GMAIL_ENABLED: ${MESSAGING_PROVIDER_GMAIL_ENABLED}
      # CALENDAR_PROVIDER_GOOGLE_ENABLED: ${CALENDAR_PROVIDER_GOOGLE_ENABLED}
      # AUTH_GOOGLE_CLIENT_ID: ${AUTH_GOOGLE_CLIENT_ID}
      # AUTH_GOOGLE_CLIENT_SECRET: ${AUTH_GOOGLE_CLIENT_SECRET}
      # AUTH_GOOGLE_CALLBACK_URL: ${AUTH_GOOGLE_CALLBACK_URL}
      # AUTH_GOOGLE_APIS_CALLBACK_URL: ${AUTH_GOOGLE_APIS_CALLBACK_URL}

      # CALENDAR_PROVIDER_MICROSOFT_ENABLED: ${CALENDAR_PROVIDER_MICROSOFT_ENABLED}
      # MESSAGING_PROVIDER_MICROSOFT_ENABLED: ${MESSAGING_PROVIDER_MICROSOFT_ENABLED}
      # AUTH_MICROSOFT_ENABLED: ${AUTH_MICROSOFT_ENABLED}
      # AUTH_MICROSOFT_CLIENT_ID: ${AUTH_MICROSOFT_CLIENT_ID}
      # AUTH_MICROSOFT_CLIENT_SECRET: ${AUTH_MICROSOFT_CLIENT_SECRET}
      # AUTH_MICROSOFT_CALLBACK_URL: ${AUTH_MICROSOFT_CALLBACK_URL}
      # AUTH_MICROSOFT_APIS_CALLBACK_URL: ${AUTH_MICROSOFT_APIS_CALLBACK_URL}

      # EMAIL_FROM_ADDRESS: ${EMAIL_FROM_ADDRESS:-contact@yourdomain.com}
      # EMAIL_FROM_NAME: ${EMAIL_FROM_NAME:-"John from YourDomain"}
      # EMAIL_SYSTEM_ADDRESS: ${EMAIL_SYSTEM_ADDRESS:-system@yourdomain.com}
      # EMAIL_DRIVER: ${EMAIL_DRIVER:-smtp}
      # EMAIL_SMTP_HOST: ${EMAIL_SMTP_HOST:-smtp.gmail.com}
      # EMAIL_SMTP_PORT: ${EMAIL_SMTP_PORT:-465}
      # EMAIL_SMTP_USER: ${EMAIL_SMTP_USER:-}
      # EMAIL_SMTP_PASSWORD: ${EMAIL_SMTP_PASSWORD:-}

    depends_on:
      db:
        condition: service_healthy
    healthcheck:
      test: curl --fail http://localhost:3000/healthz
      interval: 5s
      timeout: 5s
      retries: 20
    restart: always

  worker:
    image: twentycrm/twenty:${TAG:-latest}
    volumes:
      - server-local-data:/app/packages/twenty-server/.local-storage
    command: ["yarn", "worker:prod"]
    environment:
      PG_DATABASE_URL: postgres://${PG_DATABASE_USER:-postgres}:${PG_DATABASE_PASSWORD:-postgres}@${PG_DATABASE_HOST:-db}:${PG_DATABASE_PORT:-5432}/default
      SERVER_URL: ${SERVER_URL}
      REDIS_URL: ${REDIS_URL:-redis://redis:6379}
      DISABLE_DB_MIGRATIONS: "true"
      DISABLE_CRON_JOBS_REGISTRATION: "true"
      STORAGE_TYPE: ${STORAGE_TYPE}
      STORAGE_S3_REGION: ${STORAGE_S3_REGION}
      STORAGE_S3_NAME: ${STORAGE_S3_NAME}
      STORAGE_S3_ENDPOINT: ${STORAGE_S3_ENDPOINT}
      STORAGE_S3_ACCESS_KEY_ID: ${STORAGE_S3_ACCESS_KEY_ID}
      STORAGE_S3_SECRET_ACCESS_KEY: ${STORAGE_S3_SECRET_ACCESS_KEY}
      APP_SECRET: ${APP_SECRET:-replace_me_with_a_random_string}
      # MESSAGING_PROVIDER_GMAIL_ENABLED: ${MESSAGING_PROVIDER_GMAIL_ENABLED}
      # CALENDAR_PROVIDER_GOOGLE_ENABLED: ${CALENDAR_PROVIDER_GOOGLE_ENABLED}
      # AUTH_GOOGLE_CLIENT_ID: ${AUTH_GOOGLE_CLIENT_ID}
      # AUTH_GOOGLE_CLIENT_SECRET: ${AUTH_GOOGLE_CLIENT_SECRET}
      # AUTH_GOOGLE_CALLBACK_URL: ${AUTH_GOOGLE_CALLBACK_URL}
      # AUTH_GOOGLE_APIS_CALLBACK_URL: ${AUTH_GOOGLE_APIS_CALLBACK_URL}

      # CALENDAR_PROVIDER_MICROSOFT_ENABLED: ${CALENDAR_PROVIDER_MICROSOFT_ENABLED}
      # MESSAGING_PROVIDER_MICROSOFT_ENABLED: ${MESSAGING_PROVIDER_MICROSOFT_ENABLED}
      # AUTH_MICROSOFT_ENABLED: ${AUTH_MICROSOFT_ENABLED}
      # AUTH_MICROSOFT_CLIENT_ID: ${AUTH_MICROSOFT_CLIENT_ID}
      # AUTH_MICROSOFT_CLIENT_SECRET: ${AUTH_MICROSOFT_CLIENT_SECRET}
      # AUTH_MICROSOFT_CALLBACK_URL: ${AUTH_MICROSOFT_CALLBACK_URL}
      # AUTH_MICROSOFT_APIS_CALLBACK_URL: ${AUTH_MICROSOFT_APIS_CALLBACK_URL}

      # EMAIL_FROM_ADDRESS: ${EMAIL_FROM_ADDRESS:-contact@yourdomain.com}
      # EMAIL_FROM_NAME: ${EMAIL_FROM_NAME:-"John from YourDomain"}
      # EMAIL_SYSTEM_ADDRESS: ${EMAIL_SYSTEM_ADDRESS:-system@yourdomain.com}
      # EMAIL_DRIVER: ${EMAIL_DRIVER:-smtp}
      # EMAIL_SMTP_HOST: ${EMAIL_SMTP_HOST:-smtp.gmail.com}
      # EMAIL_SMTP_PORT: ${EMAIL_SMTP_PORT:-465}
      # EMAIL_SMTP_USER: ${EMAIL_SMTP_USER:-}
      # EMAIL_SMTP_PASSWORD: ${EMAIL_SMTP_PASSWORD:-}

depends_on:
      db:
        condition: service_healthy
      server:
        condition: service_healthy
    restart: always

  db:
    image: postgres:16
    volumes:
      - db-data:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: ${PG_DATABASE_USER:-postgres}
      POSTGRES_PASSWORD: ${PG_DATABASE_PASSWORD:-postgres}
    healthcheck:
      test: pg_isready -U ${PG_DATABASE_USER:-postgres} -h localhost -d postgres
      interval: 5s
      timeout: 5s
      retries: 10
    restart: always
  redis:
    image: redis
    restart: always
    command: [ "redis-server", "--maxmemory-policy", "noeviction" ]
volumes:
  db-data:
  server-local-data:

Файл docker-compose.yml содержит закомментированные секции для включения интеграций с Google, Microsoft и email. Для настройки этих интеграций, раскомментируйте необходимые параметры и добавьте значения в файл .env. Подробнее — в документации Twenty CRM.

Создайте файл .env:

nano .env

Вставьте код в файл:

TAG=<TAG>
PG_DATABASE_USER=postgres
PG_DATABASE_PASSWORD=<PG_DATABASE_PASSWORD>
PG_DATABASE_HOST=db
PG_DATABASE_PORT=5432
REDIS_URL=redis://redis:6379
SERVER_URL=https://crm.<IP-ADDRESS>.nip.io
# Use openssl rand -base64 32 for each secret
APP_SECRET=<APP_SECRET>
STORAGE_TYPE=s3
STORAGE_S3_NAME=<OBJECT-STORAGE-NAME>
STORAGE_S3_REGION=<REGION>
STORAGE_S3_ENDPOINT=https://s3.cloud.ru
STORAGE_S3_ACCESS_KEY_ID=<TENANT_ID>:<SECRET_KEY_ID>
STORAGE_S3_SECRET_ACCESS_KEY=<SECRET_KEY>
STORAGE_S3_FORCE_PATH_STYLE=true

Где:

  • <TAG> — тeг docker-образа Twenty CRM. Для этой лабораторной работы используйте значение v1.3.0. Другие теги могут требовать иной конфигурации. Актуальный список тегов доступен на странице docker-образа Twenty CRM.

  • <APP_SECRET> — уникальный ключ, сгенерированный ранее.

  • <PG_DATABASE_PASSWORD> — пароль от базы данных, сгенерированный ранее.

  • <IP-ADDRESS> — IP-адрес вашей виртуальной машины.

  • <OBJECT-STORAGE-NAME> — название бакета Object Storage.

  • <TENANT_ID> — ID тенанта сервиса Object Storage.

  • <REGION> — регион Object Storage.

  • <SECRET_KEY_ID>, <SECRET_KEY> — ID ключа и секретный ключ доступа к Object Storage.

  • <BUCKET_NAME> — название бакета Object Storage.

Запустите сервис:

docker compose up -d

Проверьте, что сервисы запущены:

docker compose ps

На компьютере в браузере откройте страницу https://crm.<IP-ADDRESS>.nip.io. Отобразится страница настройки Twenty CRM.

После того, как вы реализовали все этапы инструкции, проходим регистрацию.

1. Создаем рабочее пространство:

2.Создаем личный профиль:

3. Приглашаем коллег:

4. Попадаем в CRM и начинаем осваивать функционал:

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

Например, я использую раздел Tasks, чтобы трекать свои дневные задачи:

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

Поля гибко настраиваются, что помогает вести базу контактов контрагентов и удобно хранить основную информацию о них:

Сервис Notes позволяет вести и хранить накапливаемую информацию в удобном формате:

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

Workflows — для настройки всякого рода автоматизации. Этот раздел заслуживает отдельной статьи, надеюсь найдутся энтузиасты, которые раскроют весь потенциал этого инструмента.

Профиль и рабочее пространство настраивается максимально юзерфрендли, но при этом гибко:

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

Комментарии (0)