Installing Medusa and Related Services

Last Updated: May 23, 2023

This guide gives step-by-step instructions on how to get Medusa and all of its related services up and running on a fresh Ubuntu 22.04 server. This is the second part in a series of guides that will cover how to deploy Medusa. After Part 1, you should have a server up and running on AWS. If you haven’t done that yet, go back and do it now. This guide will pick up where that one left off.


  • Set Up the Environment
  • Postgres
  • Redis
  • Meilisearch
  • Medusa
  • Medusa Admin
  • Notifications Provider
  • Payment Provider
  • File Service
  • Search

Set Up the Environment

Update Ubuntu

Before anything else, let’s make sure the server is up to date.

sudo apt update && sudo apt upgrade -y


Setting your timezone is useful so that customer order date/times (and any other created_at values in your database) make sense and don’t have to be translated form GMT. Set your timezone and then reboot to make sure the change takes effect.

This example is for New York. Change it to your timezone. You can find the full list of available options here.

sudo timedatectl set-timezone America/New_York
sudo reboot

Install Node.js v18.x

curl -fsSL | sudo -E bash -
sudo apt-get install -y nodejs
node -v

If you don’t see v18.x, something went wrong. Avoid using Node v20. Many apps and libraries are not yet compatible with it.

Install Yarn

sudo npm install --global yarn
yarn -v

Configure Yarn

These changes will make it easier to run the Medusa CLI from the command line.

yarn config set prefix ~/.yarn
nano ~/.bashrc

Use the down arrow key to go to the bottom of the file and add the following line:

export PATH="$PATH:`yarn global bin`"

Press CTRL+X to exit, then Y to save, then ENTER to confirm.

Reload your bash profile:

source ~/.bashrc


Install Postgres

sudo apt -y install postgresql
sudo systemctl enable postgresql

Generate a password for the postgres user

An easy way to generate good keys is by using the openssl command. The maximum length of a Postgres password is 63 characters. The command below will generate a 60 character password. You can generate a longer password if you want, but it will be truncated to 63 characters.

openssl rand -hex 30

Update the password and create a database for Medusa

First, we open the postgres client.

sudo -u postgres psql

Then, we update the password for the postgres user and create a database for Medusa.

ALTER USER postgres PASSWORD 'the-password-you-generated-above';
create database medusa;


Install Redis

curl -fsSL | 
  sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] $(lsb_release -cs) main" 
  | sudo tee /etc/apt/sources.list.d/redis.list
sudo apt update
sudo apt install redis
sudo systemctl enable redis-server
sudo service redis-server start
redis-cli ping

You should see PONG as the response. Otherwise, something went wrong.


Install Meilisearch

curl -OL ""
sudo apt install ./meilisearch.deb
meilisearch --version

Meilisearch is now installed, but we still need to set it up as a proper systemd service, which is not done for us out of the box. We also need to generate a ‘master key,’ which you can think of as the meilisearch password.

Generate a Key

An easy way to generate good keys is by using the openssl command.

openssl rand -hex 32

Configuring as a Service

There are a lot of benefits to running meilisearch as a service in this sort of all-in-one Medusa setup. This way, if the server goes down for any reason, the meilisearch service will automatically restart. You also don’t have to keep the master key handy to cut and paste every time you want to start meilisearch.

Create a working directory and then create a systemd service file:

sudo mkdir /var/meilisearch
sudo nano /etc/systemd/system/meilisearch.service

Copy and paste the following into the file:


ExecStart=/usr/bin/meilisearch --env "production" --master-key "the-key-you-generated-above"


Press CTRL+X to exit, then Y to save, then ENTER to confirm.

Now, enable the service and start it:

sudo systemctl enable meilisearch
sudo service meilisearch start


If any step below fails, check the Backend Setup guide in the Medusa Docs in case something has been changed.

Install Medusa CLI and Create a New Project

yarn global add @medusajs/medusa-cli
medusa new medusa-backend
cd medusa-backend
yarn install

Update the Environment Variables

Create two more strings using openssl rand -hex 32. One will be used for the session secret and the other for the cookie secret.

openssl rand -hex 32
openssl rand -hex 32
nano .env

Add the two strings to the .env file and update the database credentials and your CORS settings.




A full discussion of CORS is outside the scope of this guide. For now, just add the urls you will be using to access the admin and store.

Press CTRL+X to exit, then Y to save, then ENTER to confirm.

Run the Migrations and Seed the Database

This will create the tables in the database.

npx @medusajs/medusa migrations run

If you want to seed the database with some sample data, you can run the following command:

npx @medusajs/medusa seed -f data/seed.json

If you don’t want to seed the database, you should add a user so that you can log into the the admin app.

npx @medusajs/medusa user -e '[email protected]' -p 'some-password'

Enable Redis for Caching and the Event Bus

Before starting our server, let’s also make sure we enable Redis.

nano medusa-config.js

Uncomment the Redis-related lines in modules and projectConfig:

const modules = {
   eventBus: {
      resolve: "@medusajs/event-bus-redis",
      options: {
         redisUrl: REDIS_URL
   cacheService: {
      resolve: "@medusajs/cache-redis",
      options: {
         redisUrl: REDIS_URL
const projectConfig = {
   redis_url: REDIS_URL

Calm Your Mind and Think Happy Thoughts

Now, the moment of truth. Start the server:

yarn dev

If everything went well, you should see some startup messages, and then the following message:

Server is ready on port: 9000

Install the Admin

Install the Admin Package

yarn add @medusajs/admin

Configure the Admin

Uncomment the following lines in the plugins array in medusa-config.js:

   resolve: "@medusajs/admin",
   /** @type {import('@medusajs/admin').PluginOptions} */
   options: {
      autoRebuild: true,

Notifications Provider

You will want to install a notification provider to send email notifications to your customers. The most popular option is medusa-plugin-sendgrid. We will use AWS SES in this guide because I am most familiar with it

Install the Plugin

The following instructions are for AWS SES. If you are using a different provider, you will need to adjust the instructions accordingly.

yarn add medusa-plugin-ses

Update Your Environment Variables

Open your .env file and add the following:

SES_FROM="[email protected] <[email protected]>"
  • SES_REGION will be for example “us-east-1”

  • Obtain the access key id and secret access key by creating an IAM user with SES send permissions.

  • The SES_FROM email address must be a verified sender in your AWS account.

  • The template path is where the Handlebars email templates will be stored.

Update Your Config File

Open your medusa-config.js file and add the following:

    resolve: `medusa-plugin-ses`,
    options: {
      access_key_id: process.env.SES_ACCESS_KEY_ID,
      secret_access_key: process.env.SES_SECRET_ACCESS_KEY,
      region: process.env.SES_REGION,
      from: process.env.SES_FROM,
      enable_endpoint: process.env.SES_ENABLE_ENDPOINT,
      template_path: process.env.SES_TEMPLATE_PATH,
      order_placed_template: 'order_placed',
      order_shipped_template: 'order_shipped',
      customer_password_reset_template: 'customer_password_reset',
      gift_card_created_template: 'gift_card_created',
      //order_canceled_template: 'order_canceled',
      //order_refund_created_template: 'order_refund_created',
      //order_return_requested_template: 'order_return_requested',
      //order_items_returned_template: 'order_items_returned',
      //swap_created_template: 'swap_created',
      //swap_shipment_created_template: 'swap_shipment_created',
      //swap_received_template: 'swap_received',
      //claim_shipment_created_template: 'claim_shipment_created',
      //user_password_reset_template: 'user_password_reset',
      //medusa_restock_template: 'medusa_restock',

You only need to uncomment the templates you want to use. If there is no template for a type of event, then no notifications will be sent for events of that type.


Create a ‘data/templates’ folder if you used the default SES_TEMPLATE_PATH variable above. You can specify a full or absolute path.

medusa-server  // root directory
            |-order_placed  // or whatever you name your templates and specify in the config file
            |- etc   

Payment Provider

There are several payment providers to choose from, and not all are available in all regions. My personal preference is Stripe.

Refer to this guide to set up Stripe

File Service Provider

You will need to choose a file service provider to store your product images. The most popular options are AWS S3 and MinIO.

Refer to this guide to set up AWS S3

Install Search Plugin

We’re already most of the way there since we installed meilisearch along with our other services earlier. We just need to install the plugin and configure it.

Install medusa-plugin-meilisearch

yarn add medusa-plugin-meilisearch

Update Your Environment Variables

Open your .env file and add the following:


Open medusa-config.js and add the following to the plugins array:

const plugins = [
    resolve: `medusa-plugin-meilisearch`,
    options: {
      config: {
        host: process.env.MEILISEARCH_HOST,
        apiKey: process.env.MEILISEARCH_API_KEY,
      settings: {
        products: {
          indexSettings: {
            searchableAttributes: [
            displayedAttributes: [
          primaryKey: "id",
          transform: (product) => ({ 
            // other attributes...

Up next