Облачная платформаEvolution

Развертывание CRM-сервиса Twenty на виртуальной машине


С помощью этого руководства вы развернете CRM‑сервис Twenty на виртуальной машине в облаке Cloud.ru Evolution:

  • Вы создадите инфраструктуру, развернете сервис CRM и опубликуете его на сервере nginx, обеспечив безопасный доступ по HTTPS.

  • Вы создадите резервную копию виртуальной машины в сервисе «Резервное копирование» для сохранности данных.

  • В результате вы получите работающее окружение Twenty, развернутое из фиксированного тега образа и готовое к использованию.

Вы будете использовать следующие сервисы:

  • «Виртуальные машины» — сервис, в рамках которого предоставляется виртуальная машина.

  • Object Storage — объектное S3-хранилище с бесплатным хранением файлов объемом до 15 ГБ.

  • «Публичные IP» — сервис для организации доступа к приложению через интернет.

  • Резервное копирование — для создания резервных копий.

  • Docker — система контейнеризации.

  • Docker Compose — инструмент для запуска и управления Docker-контейнерами.

  • Twenty CRM — CRM-сервис с открытым исходным кодом.

  • Бесплатный сервис nip.io для получения публичного доменного имени и сертификата. Вы также можете использовать собственное зарегистрированное доменное имя и SSL-сертификат для организации доступа.

  • Nginx — веб-сервер для проксирования запросов и организации защищенного HTTPS-доступа к приложению.

  • Let’s Encrypt — сервис для автоматического получения бесплатного SSL-сертификата.

Шаги:

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

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

  3. Настройте Nginx и HTTPS.

  4. Разверните приложение.

  5. Удалите доступ по SSH для виртуальной машины.

  6. Обеспечьте сохранность данных приложения.

Перед началом работы

  1. Зарегистрируйтесь в личном кабинете Cloud.ru.

    Если вы уже зарегистрированы, войдите под своей учетной записью.

  2. Сгенерируйте ключевую пару и загрузите публичный ключ в Cloud.ru Evolution.

  3. Получите ключи доступа сервисного аккаунта. Запишите Key ID (логин) и Key Secret (пароль), они будут нужны для выполнения дальнейших шагов.

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

На этом шаге вы подготовите сеть, группу безопасности, виртуальную машину.

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

    Трафик

    Протокол

    Порт

    Тип источника/адресата

    Источник/Адресат

    Входящий

    TCP

    443

    IP-адрес

    0.0.0.0/0

    Входящий

    TCP

    80

    IP-адрес

    0.0.0.0/0

    Исходящий

    IP-адрес

    0.0.0.0/0

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

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

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

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

    • Публичный IP — оставьте Арендовать новый или выберите IP-адрес из списка арендованных.

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

    • Логинcrm-service.

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

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

    • Пароль — задайте пароль пользователя.

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

    • Остальные параметры оставьте по умолчанию или выберите на свое усмотрение.

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

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

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

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

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

  4. Перейдите на вкладку Object Storage API.

  5. Скопируйте и сохраните значения параметров ID тенанта и Регион.

  6. Убедитесь, что в личном кабинете на странице сервиса Object Storage отображается бакет crm-service.

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

На этом шаге вы установите необходимые пакеты и подготовите среду.

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

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

    sudo apt update && sudo apt upgrade -y &&\
    sudo apt install -y curl apt-transport-https\
    ca-certificates\
    software-properties-common\
    gnupg2\
    lsb-release
  3. Установите 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
  4. Предоставьте текущему пользователю права на запуск Docker:

    sudo usermod -aG docker $USER
    newgrp docker
  5. Установите Docker Compose:

    sudo apt-get install docker-compose-plugin -y
  6. Проверьте, что Docker и Docker Compose установлены корректно:

    docker --version
    docker compose version
  7. Установите и запустите Nginx:

    sudo apt install nginx -y
    sudo systemctl enable nginx
    sudo systemctl start nginx
  8. Установите Let’s Encrypt и плагин для Nginx:

    sudo apt install certbot python3-certbot-nginx -y

3. Настройте Nginx и HTTPS

На этом шаге вы зарегистрируете доменное имя, настроите Nginx в качестве защищенного прокси, получите SSL-сертификат и ограничите доступ через межсетевой экран.

  1. В терминале подключения к виртуальной машине настройте межстетевой экран:

    sudo ufw allow OpenSSH
    sudo ufw allow 'Nginx Full'
    sudo ufw enable
  2. Создайте конфигурационный файл:

    sudo nano /etc/nginx/sites-available/crm.conf
  3. Вставьте конфигурацию, заменив <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;
    }
    }
  4. Активируйте конфигурацию и перезапустите 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
  5. Проверьте, что Nginx работает:

    sudo systemctl status nginx

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

  6. Выпустите SSL-сертификат:

    sudo certbot --nginx -d crm.<ip_address>.nip.io --redirect --agree-tos -m <email>

    Где:

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

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

    Внимание

    При выпуске сертификата через nip.io может возникнуть ошибка «too many certificates (25000) already issued for «nip.io»». Это происходит из-за популярности сервиса nip.io. При возникновении ошибки повторите команду выпуска сертификата. Если ошибка сохраняется, рассмотрите использование собственного доменного имени.

  7. Перейдите по адресу https://sonar.<ip_address>.nip.io и убедитесь, что браузер отмечает соединение как безопасное.

4. Разверните приложение

На этом шаге вы развернете серверное приложение Twenty CRM с помощью Docker Compose.

  1. В терминале подключения к виртуальной машине создайте структуру проекта:

    mkdir ~/twenty-crm
    cd ~/twenty-crm
  2. Сгенерируйте уникальный ключ и сохраните его, он понадобится в дальнейшем:

    openssl rand -base64 32
  3. Сгенерируйте пароль для базы данных и сохраните его, он понадобится в дальнейшем:

    openssl rand -base64 15
  4. Создайте файл docker-compose.yml:

    nano docker-compose.yml
  5. Вставьте код:

    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.

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

    nano .env
  7. Вставьте код в файл:

    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.

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

    docker compose up -d
  9. Проверьте, что сервисы запущены:

    docker compose ps
  10. В браузере откройте страницу https://crm.<ip_address>.nip.io, <ip_address> — публичный IP-адрес вашей виртуальной машины.

    Откроется страница настройки Twenty CRM.

    ../_images/img__twenty_crm.webp

5. Отключите SSH-доступ

Когда вы развернули и настроили сервис, закройте доступ по SSH для повышения безопасности.

  1. В личном кабинете на верхней панели слева нажмите Кнопка с изображением девяти точек и выберите Инфраструктура → Виртуальные машины.

  2. В списке виртуальных машин выберите crm-service.

  3. Перейдите на вкладку Сетевые параметры.

  4. В блоке сетевого интерфейса нажмите Горизонтальное меню и выберите Изменить группы безопасности.

  5. Удалите группу SSH-access_ru и сохраните изменения.

  6. Убедитесь, что доступа нет — попробуйте подключиться к виртуальной машине по SSH.

    После отключения доступа по SSH, администрирование сервиса будет доступно через серийную консоль виртуальной машины.

6. Обеспечьте сохранность данных приложения

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

  • Тип ресурсаВиртуальная машина.

  • Ресурсcrm-service.

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

Убедитесь, что в личном кабинете на странице Инфраструктура → Виртуальные машины отображается резервная копия crm-service-backup со статусом «Создана».

Периодически создавайте резервные копии для сохранности данных.

Результат

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

Для создания отказоустойчивого и масштабируемого решения с надежным хранением данных вы можете воспользоваться сервисами Managed PostgreSQL®, Managed Redis и Object Storage.

При необходимости активируйте интеграции с Google, Microsoft и email.