Medusa setup example

A hands-on, end-to-end example of installing Medusa and its storefront on TurboStack, from project creation over SSH to running each service in production.

This page walks through a full Medusa installation on TurboStack, step by step: the Medusa backend (which includes the admin dashboard) and the optional Next.js storefront. It is a worked example that complements Deploy Medusa on TurboStack - read that page first for the host configuration and the reasoning behind the reverse-proxy pattern.

If you only want the backend, you can skip the storefront steps. Medusa exposes an Application Programming Interface (API) so you can connect your own storefront later.

Before you start

Configure the host as described in Deploy Medusa on TurboStack. The example below assumes two websites (vhosts) under one system user, each with proxy_enabled: true so Nginx proxies public traffic to the Node process:

  • a storefront on port 8000 (for example shop.example.com)
  • the Medusa backend and admin on port 9000 (for example dashboard.example.com)
webserver: nginx
postgresql_version: "18"
system_users:
  - username: prod
    vhosts:
      - server_name: shop.example.com www.shop.example.com
        app_name: frontend
        nodejs_version: "24"
        cert_type: letsencrypt
        proxy_enabled: true
        proxy_upstream_port: "8000"
      - server_name: dashboard.example.com
        app_name: dashboard
        nodejs_version: "24"
        cert_type: letsencrypt
        proxy_enabled: true
        proxy_upstream_port: "9000"

Publish the host so the two websites and PostgreSQL exist, then open an SSH session as the system user for the steps below.

Step 1: Create the Medusa project

Create a directory for the project in your home directory and change into it:

mkdir project
cd project

Run the Medusa installer:

npx create-medusa-app@latest <shopname>

Follow the interactive prompts. When asked, provide your PostgreSQL credentials:

? Would you like to install the Next.js Starter Storefront? Yes
? Enter your Postgres username prod
? Enter your Postgres password [hidden]
? Enter your Postgres user's database name prod

You find the PostgreSQL credentials in the TurboStack interface under the host's Credentials, or on the server in the ~/.pgpass file:

cat ~/.pgpass

The installer is finished when it prints:

Server is ready on port: 9000

Stop the test server with Ctrl + C. You will start it as a persistent service later.

Step 2: Create an admin user

You need an admin account to sign in to the dashboard. Change the values to your own:

npx medusa user -e user@example.com -p <StrongPassword>

Step 3: Allow your dashboard domain

Medusa's admin runs on a development server that only accepts requests for hosts it knows. Add your dashboard domain to the allowedHosts list in medusa-config.ts, found at ~/project/<shopname>/medusa-config.ts. Add the admin block:

import { loadEnv, defineConfig } from '@medusajs/framework/utils'

loadEnv(process.env.NODE_ENV || 'development', process.cwd())

module.exports = defineConfig({
  projectConfig: {
    databaseUrl: process.env.DATABASE_URL,
    http: {
      storeCors: process.env.STORE_CORS,
      adminCors: process.env.ADMIN_CORS,
      authCors: process.env.AUTH_CORS,
      jwtSecret: process.env.JWT_SECRET || "supersecret",
      cookieSecret: process.env.COOKIE_SECRET || "supersecret",
    },
  },
  admin: {
    // Allow the host (and its subdomains) that serve the admin dashboard
    vite: (config) => {
      return {
        ...config,
        server: {
          allowedHosts: [".example.com"],
        },
      }
    },
  },
})

Step 4: Build and run the backend for production

The development server is not suitable for production. From the project directory ~/project/<shopname>/, build the backend:

npx medusa build

The build writes a production bundle to .medusa/server. Change into it and install its dependencies:

cd .medusa/server
npm install

Copy the environment file from the project root into the build directory:

cp ../../.env .env

Start the server once to confirm it works:

npx medusa start

Open https://dashboard.example.com in your browser and sign in with the admin account you created. When the backend loads correctly, stop it with Ctrl + C and start it as a persistent process so it survives your logout and restarts on boot. A Node process manager such as PM2 does this:

pm2 start "npx medusa start" --name medusa-backend

Step 5: Build and run the storefront (optional)

Change into the storefront directory and install its dependencies:

cd ~/project/<shopname>-storefront
npm install

Build and start it once to confirm it listens on port 8000:

npm run build
npm start

When it works, stop it with Ctrl + C and start it as a persistent process:

pm2 start "npm start" --name storefront

The storefront is now reachable at https://shop.example.com, proxied by Nginx to port 8000.

Tip: Non-interactive install

To script the installation, pass the database connection string and the storefront flag directly, so create-medusa-app does not prompt:

npx create-medusa-app@latest <shopname> \
  --db-url "postgres://<username>:<password>@localhost:5432/<dbname>" \
  --with-nextjs-starter

Read the credentials from ~/.pgpass rather than copying them from the interface. If you only need the backend, delete the generated storefront directory afterward.