Medusa на Ubuntu 24.04: пошаговая установка
Если вы делаете интернет-магазин и не хотите привязываться к готовому шаблонизатору вроде Shopify или WooCommerce, рано или поздно упрётесь в вопрос: где взять бэкенд для корзины, заказов, товаров и платежей, который отдаёт всё это через API, а фронтенд собираете сами — на чём угодно. Medusa — как раз такой headless-движок на Node.js, и его вполне реально поставить на обычный VPS самостоятельно, без PaaS и без магии. Ниже — рабочий порядок: Node.js, PostgreSQL, Redis, хранилище для изображений товаров и Nginx перед всем этим.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Что такое Medusa и когда она подходит
Medusa — open-source headless-платформа электронной коммерции: она хранит каталог товаров, варианты, корзины, заказы, клиентов, скидки и интеграции с платёжными провайдерами, а отдаёт всё это через REST API. Готового магазина "из коробки" с шаблонами страниц в ней нет — за отображение отвечает отдельный фронтенд, который вы либо пишете сами, либо берёте официальный стартер на Next.js и дорабатываете под себя.
Это похоже на связку Strapi + свой фронтенд, только заточено конкретно под e-commerce: в модель данных уже встроены корзины, варианты товаров с ценами по регионам и валютам, статусы заказов, зоны доставки и цепочки workflow (например, что происходит после оплаты — резерв склада, письмо, создание фулфилмента). Повторять это вручную на голом Express — плохая идея, если у вас не совсем нестандартная модель торговли.
Обратная сторона: Medusa — полноценное Node.js-приложение с базой данных, очередями и фоновыми задачами, а не файлы, которые заливают по FTP. Для магазина на 20 товаров это, возможно, избыточно — присмотритесь к обычной CMS с плагином корзины. Medusa имеет смысл, когда вы строите отдельный фронтенд (сайт плюс, например, мобильное приложение), хотите контролировать логику заказов и не платить процент с оборота платформе.
Подготовка сервера: Node.js, PostgreSQL и Redis
Понадобится VPS с Ubuntu 24.04. Для разработки и тестов хватит 1 vCPU / 2 ГБ RAM, но для продакшена с реальным трафиком и сборкой админки закладывайте от 2 vCPU / 4 ГБ — PostgreSQL, Redis и сам процесс Node.js вместе с админ-панелью на слабой машине начинают конкурировать за память уже на первых реальных заказах.
Ставим Node.js через официальный репозиторий NodeSource. Medusa требует достаточно свежую LTS-версию Node.js — на момент написания это ветка 20.x, но точный минимум лучше сверить с requirements в официальной документации перед установкой, так как он меняется от релиза к релизу:
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
node -v
npm -v
PostgreSQL нужен как основная база данных. Если ставите с нуля — процесс подробно разобран в статье про установку PostgreSQL на Ubuntu 24.04. Кратко создаём базу и пользователя под Medusa:
sudo -u postgres psql
CREATE DATABASE medusa_db;
CREATE USER medusa_user WITH ENCRYPTED PASSWORD 'сложный_пароль';
GRANT ALL PRIVILEGES ON DATABASE medusa_db TO medusa_user;
\q
Redis в Medusa используется под очередь событий, workflow-движок (модуль, который выполняет цепочки шагов вроде "оплата → резерв склада → уведомление") и кэш. В деве можно обойтись без него, но для продакшена он практически обязателен — без Redis workflow-движок падает обратно на менее надёжный in-memory режим, который не переживает перезапуск процесса. Установка описана в статье про настройку Redis на VPS; для локального использования достаточно дефолтного конфига с прослушиванием на 127.0.0.1.
Создаём отдельного системного пользователя под приложение — Node.js-процессы не должны работать от root:
sudo adduser --disabled-password --gecos "" medusa
sudo su - medusa
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверУстановка Medusa через CLI
Дальше всё выполняется от имени пользователя medusa. Официальный способ создать проект — интерактивный генератор:
npx create-medusa-app@latest
Мастер спросит имя проекта, предложит подключиться к базе данных (можно указать уже созданную medusa_db из предыдущего шага — так у вас будет полный контроль над строкой подключения) и спросит, ставить ли сразу фронтенд-стартер на Next.js. Если фронтенд будете делать отдельно или позже — на этом шаге отвечайте "нет", устанавливать только бэкенд и админку.
Установка тянет зависимости и прогоняет первые миграции — занимает несколько минут. После неё в проекте появится файл .env со строкой подключения к базе; проверьте и при необходимости пропишите Redis и адрес API вручную:
DATABASE_URL=postgres://medusa_user:сложный_пароль@127.0.0.1:5432/medusa_db
REDIS_URL=redis://127.0.0.1:6379
STORE_CORS=https://shop.example.com
ADMIN_CORS=https://admin.example.com
AUTH_CORS=https://shop.example.com,https://admin.example.com
JWT_SECRET=сгенерированная_случайная_строка
COOKIE_SECRET=ещё_одна_случайная_строка
JWT_SECRET и COOKIE_SECRET генератор обычно создаёт сам при первой установке — не перезаписывайте их вручную наугад, а если переносите проект между серверами, копируйте оба значения как есть, иначе выданные ранее токены и сессии в админке перестанут проходить проверку.
Убедиться, что всё поднимается, можно в режиме разработки:
cd my-medusa-store
npm run dev
API по умолчанию слушает 127.0.0.1:9000, встроенная админ-панель — там же, по пути /app. Для первой проверки удобно временно пробросить порт через SSH-туннель (ssh -L 9000:127.0.0.1:9000 user@server) и открыть http://127.0.0.1:9000/app в браузере. Пользователя-администратора создают отдельной командой:
npx medusa user -e admin@example.com -p 'сложный_пароль'
Хранилище файлов для изображений товаров
По умолчанию Medusa сохраняет загруженные файлы (изображения товаров) локально на диске сервера. Для одного процесса на одном сервере это формально работает, но у подхода два практических минуса: файлы не переживают миграцию на другой сервер без ручного переноса, а если вы когда-нибудь захотите запустить несколько инстансов API за балансировщиком — локальные файлы у каждого инстанса будут разными.
Правильный вариант для продакшена — S3-совместимое хранилище: официальный провайдер файлового модуля Medusa умеет писать в AWS S3, DigitalOcean Spaces и любое другое S3-совместимое API, включая self-hosted MinIO на своём же сервере или соседнем. Если хотите держать хранилище под своим контролем — разверните MinIO по статье про установку MinIO на Ubuntu 24.04 и создайте отдельный бакет под товарные изображения.
Ставим провайдер в проекте Medusa:
npm install @medusajs/file-s3
И подключаем его как провайдер файлового модуля в medusa-config.ts — общий принцип такой (точные названия полей провайдера уточняйте в актуальной документации Medusa, они менялись между релизами):
modules: [
{
resolve: "@medusajs/medusa/file",
options: {
providers: [
{
resolve: "@medusajs/file-s3",
id: "s3",
options: {
file_url: "https://s3.example.com/medusa-bucket",
access_key_id: process.env.S3_ACCESS_KEY_ID,
secret_access_key: process.env.S3_SECRET_ACCESS_KEY,
region: "us-east-1",
bucket: "medusa-bucket",
endpoint: "https://s3.example.com",
},
},
],
},
},
],
Если пока обходитесь локальным хранилищем — нормально для теста, но перед запуском магазина перенесите хотя бы медиафайлы на S3-совместимое хранилище: диск VPS не резервируется автоматически вместе с базой, и потерять фотографии товаров при сбое диска обиднее, чем текстовые данные, которые есть в бэкапе PostgreSQL.
Продакшен: миграции, сборка и запуск через PM2
Режим dev пересобирает всё на лету и не подходит для постоянной работы. Перед продакшен-запуском прогоняем миграции базы данных и собираем проект:
npx medusa db:migrate
npm run build
Проверяем, что продакшен-режим стартует без ошибок:
NODE_ENV=production npm run start
Если старт проходит чисто — переводим процесс под PM2, чтобы он переживал падения и перезагрузку сервера. Ставим PM2 глобально от sudo-пользователя (не от medusa):
sudo npm install -g pm2
Возвращаемся к пользователю medusa и запускаем:
cd ~/my-medusa-store
NODE_ENV=production pm2 start npm --name medusa -- run start
pm2 save
Автозапуск при перезагрузке сервера настраивается командой pm2 startup — она выведет строку с sudo, которую нужно выполнить от root:
pm2 startup systemd -u medusa --hp /home/medusa
Проверяем, что процесс не уходит в рестарт-луп:
pm2 status
pm2 logs medusa --lines 50
Бесконечные перезапуски почти всегда означают одно из двух: не совпадает DATABASE_URL/REDIS_URL с реальными адресами, либо не прогнаны миграции после обновления зависимостей — при апдейте самой Medusa на новую минорную версию npx medusa db:migrate нужно запускать заново, схема базы может измениться.
Nginx как reverse proxy и HTTPS
Наружу порт 9000 открывать не нужно — ставим перед Medusa Nginx как reverse proxy, он же терминирует HTTPS. Если Nginx ещё не настроен как обратный прокси на сервере — базовая конфигурация разобрана в статье про Nginx как reverse proxy.
Конфиг для Medusa, /etc/nginx/sites-available/medusa:
server {
listen 80;
server_name api.example.com;
client_max_body_size 30M;
location / {
proxy_pass http://127.0.0.1:9000;
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;
}
}
client_max_body_size увеличен под загрузку изображений товаров через админку — с дефолтным лимитом Nginx в 1 МБ первая же загрузка нормальной фотографии товара оборвётся с 413-й ошибкой.
Активируем конфиг и выпускаем сертификат через certbot:
sudo ln -s /etc/nginx/sites-available/medusa /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
sudo certbot --nginx -d api.example.com
Если планируете отдельный домен под фронтенд-стартер (например, shop.example.com) — он поднимается как отдельное Next.js-приложение, тоже за своим Nginx-виртуалхостом, и ходит к API Medusa по домену api.example.com через переменную NEXT_PUBLIC_MEDUSA_BACKEND_URL в своём .env. Не забудьте после этого прописать реальные домены фронтенда и админки в STORE_CORS / ADMIN_CORS / AUTH_CORS из предыдущего шага — с localhost-значениями по умолчанию продакшен-фронтенд не сможет достучаться до API из-за CORS.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Redis обязателен или можно без него?
Технически Medusa стартует и без Redis, откатываясь на менее надёжный режим для очередей и кэша. Для теста на своём ноутбуке это нормально, но в продакшене на VPS ставьте Redis сразу — иначе фоновые задачи (например, обработка webhook от платёжного провайдера) при перезапуске процесса могут теряться.
Чем Medusa отличается от Shopify или простого плагина корзины на WordPress?
Shopify — это SaaS с процентом от оборота и ограничениями кастомизации бэкенд-логики. Medusa — код, который целиком у вас на сервере: вы платите только за хостинг, но и ответственность за апдейты, бэкапы и безопасность тоже на вас.
Нужен ли сразу отдельный фронтенд-стартер на Next.js?
Нет, можно поднять только бэкенд и админку, проверить API через Postman или curl, а фронтенд подключить позже — Medusa не требует конкретного фронтенд-стека, работать с её API можно из чего угодно.
Сколько ресурсов сервера реально нужно для рабочего магазина?
Зависит от каталога и трафика, точных цифр без вашей нагрузки никто не даст. Для старта с небольшим каталогом и умеренным трафиком 2 vCPU / 4 ГБ RAM обычно достаточно с запасом; при росте в первую очередь упрётесь в PostgreSQL, а не в сам процесс Node.js.
Как обновлять Medusa на сервере без даунтайма?
Официальный путь — следить за release notes и прогонять миграции после обновления пакетов. Перед любым мажорным или минорным апдейтом обязательно делайте бэкап базы PostgreSQL и файла .env — если миграция пойдёт не так, откат без свежего бэкапа будет мучительным.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →