Как и любого уважающего себя молодого человека меня нередко преследуют мысли об открытии своего собственного технологического стартапа, ну или хотя бы магазина рыболовных приспособлений у метро. Но каждый раз все разбивается о суровые реалии нашего мира. Любое дело подразумевает наличие команды, учет товаров, обслуживание клиентов и многое другое.
А как обслужить клиента и удобно хранить информацию о нем? Для этого существует 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-системы. Желаю успехов)
