# Medusa setup example

This page walks through a full [Medusa](https://medusajs.com/) 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](deploy.md) - 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](deploy.md). 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`)

```yaml
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](../../technologies/ssh/what-is.md)
session as the system user for the steps below.

> [!NOTE]
> If you only want the backend, remove the storefront vhost.

## Step 1: Create the Medusa project

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

```bash
mkdir project
cd project
```

> [!WARNING]
> Do not place the project inside `public_html`. That directory is served publicly and would expose
> source and configuration files.

Run the Medusa installer:

```bash
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:

```bash
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.

> [!NOTE]
> If you only want the backend, answer `No` to the storefront prompt.

## Step 2: Create an admin user

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

```bash
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:

```javascript
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:

```bash
npx medusa build
```

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

```bash
cd .medusa/server
npm install
```

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

```bash
cp ../../.env .env
```

Start the server once to confirm it works:

```bash
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:

```bash
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:

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

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

```bash
npm run build
npm start
```

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

```bash
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:

```bash
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.

## Related

- [Deploy Medusa on TurboStack](deploy.md) - the host YAML and the reverse-proxy pattern.
- [Medusa best practices](best-practices.md) - performance and stability.
- [Troubleshooting Medusa](troubleshooting.md) - logs and common fixes.
- [What is SSH?](../../technologies/ssh/what-is.md)
- [Applications overview](../index.md)
