Self-Hosting Guide: Deploy Medusa for E-Commerce
Self-Hosting Guide: Deploy Medusa for E-Commerce
Medusa is the open source Shopify alternative — a headless commerce platform with no transaction fees, full API access, and a modular architecture. Self-hosting means you own your store completely.
Requirements
- VPS with 2 GB RAM minimum (4 GB recommended)
- Node.js 20+ or Docker
- Domain name (e.g.,
store.yourdomain.com) - PostgreSQL database
- Redis
- 20+ GB disk
Step 1: Create Medusa Project
# Create new Medusa project
npx create-medusa-app@latest my-store
cd my-store
# Or clone for Docker setup
git clone https://github.com/medusajs/medusa.git
cd medusa
Step 2: Docker Compose Setup
# docker-compose.yml
services:
medusa:
build: .
container_name: medusa
restart: unless-stopped
ports:
- "9000:9000"
environment:
- DATABASE_URL=postgresql://medusa:your-strong-password@db:5432/medusa
- REDIS_URL=redis://redis:6379
- JWT_SECRET=your-jwt-secret
- COOKIE_SECRET=your-cookie-secret
- STORE_CORS=https://store.yourdomain.com
- ADMIN_CORS=https://admin.yourdomain.com
depends_on:
- db
- redis
db:
image: postgres:16-alpine
container_name: medusa-db
restart: unless-stopped
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=medusa
- POSTGRES_USER=medusa
- POSTGRES_PASSWORD=your-strong-password
redis:
image: redis:7-alpine
container_name: medusa-redis
restart: unless-stopped
volumes:
- redis_data:/data
volumes:
postgres_data:
redis_data:
Generate secrets:
openssl rand -hex 32 # JWT_SECRET
openssl rand -hex 32 # COOKIE_SECRET
Step 3: Start Medusa
docker compose up -d
# Run migrations and seed
docker exec medusa npx medusa db:migrate
docker exec medusa npx medusa seed --seed-file=data/seed.json
Admin dashboard at http://localhost:9000/app
API at http://localhost:9000
Step 4: Reverse Proxy (Caddy)
# /etc/caddy/Caddyfile
# API and Admin
admin.yourdomain.com {
reverse_proxy localhost:9000
}
# Storefront (Step 6)
store.yourdomain.com {
reverse_proxy localhost:3000
}
sudo systemctl restart caddy
Step 5: Set Up Payments
Stripe (recommended):
npm install medusa-payment-stripe
Configure in medusa-config.js:
module.exports = {
plugins: [{
resolve: 'medusa-payment-stripe',
options: {
api_key: process.env.STRIPE_API_KEY,
webhook_secret: process.env.STRIPE_WEBHOOK_SECRET,
},
}],
}
Set environment variables:
STRIPE_API_KEY=sk_live_your_key
STRIPE_WEBHOOK_SECRET=whsec_your_secret
No transaction fees from Medusa — only Stripe's standard 2.9% + $0.30.
Step 6: Deploy Storefront
Next.js Starter (recommended):
npx create-medusa-app@latest --with-nextjs-starter
cd my-store-storefront
# Configure
echo "NEXT_PUBLIC_MEDUSA_BACKEND_URL=https://admin.yourdomain.com" > .env.local
# Build and start
npm run build
npm start
Or build a custom storefront with any framework using the Medusa JS SDK:
import Medusa from '@medusajs/js-sdk'
const medusa = new Medusa({ baseUrl: 'https://admin.yourdomain.com' })
// List products
const { products } = await medusa.store.products.list()
// Get product details
const { product } = await medusa.store.products.retrieve('prod_123')
// Create cart
const { cart } = await medusa.store.carts.create({})
// Add item to cart
await medusa.store.carts.lineItems.create(cart.id, {
variant_id: 'variant_123',
quantity: 1,
})
// Complete checkout
const { order } = await medusa.store.carts.complete(cart.id)
Step 7: Configure Products
In the admin dashboard (admin.yourdomain.com/app):
-
Products → Add Product
- Title, description, images
- Variants (size, color)
- Pricing (multiple currencies)
- Inventory tracking
-
Collections → organize products into groups
-
Gift Cards → create gift card products
-
Discounts → percentage or fixed amount codes
Step 8: Configure Shipping and Tax
Shipping:
- Settings → Regions → add your regions
- Settings → Shipping → add shipping options per region
- Configure flat rate, free shipping, or calculated rates
Tax:
- Settings → Tax → configure tax rates per region
- Or integrate TaxJar for automatic calculation
Email notifications:
npm install medusa-plugin-sendgrid
# or
npm install medusa-plugin-resend
Step 9: Set Up Admin Users
# Create admin user via CLI
docker exec medusa npx medusa user --email admin@yourdomain.com --password your-password
Or invite via Admin Dashboard → Settings → Team.
Production Hardening
File storage (S3 for product images):
npm install medusa-file-s3
// medusa-config.js
plugins: [{
resolve: 'medusa-file-s3',
options: {
s3_url: 'https://s3.yourdomain.com',
bucket: 'medusa-uploads',
region: 'us-east-1',
access_key_id: process.env.S3_ACCESS_KEY,
secret_access_key: process.env.S3_SECRET_KEY,
},
}],
Backups:
# Database backup (daily cron)
docker exec medusa-db pg_dump -U medusa medusa > /backups/medusa-$(date +%Y%m%d).sql
# File storage backup (if using local)
tar czf /backups/medusa-uploads-$(date +%Y%m%d).tar.gz ./uploads
Updates:
npm install @medusajs/medusa@latest
npx medusa db:migrate
docker compose restart medusa
Monitoring:
- Monitor API endpoint (port 9000)
- Monitor storefront (port 3000)
- Track order completion rates
- Set up alerts for failed payments
Resource Usage
| Products | RAM | CPU | Disk |
|---|---|---|---|
| 1-100 | 2 GB | 2 cores | 10 GB |
| 100-1K | 4 GB | 4 cores | 30 GB |
| 1K-10K | 8 GB | 8 cores | 50 GB |
VPS Recommendations
| Provider | Spec (500 products) | Price |
|---|---|---|
| Hetzner | 4 vCPU, 8 GB RAM | €8/month |
| DigitalOcean | 2 vCPU, 4 GB RAM | $24/month |
| Linode | 2 vCPU, 4 GB RAM | $24/month |
vs Shopify Basic ($39/month + 2.9% fees): At $10K/month revenue, Shopify costs $639/month. Medusa on Hetzner costs $8/month + Stripe's 2.9%.
Compare e-commerce platforms on OSSAlt — features, transaction fees, and flexibility side by side.