This comprehensive guide walks you through deploying a production-ready MedusaJS e-commerce platform using Docker on any Linux server.
Prerequisites
Before starting, ensure you have:
- A Linux server with root/sudo access (Ubuntu, Debian, CentOS, RHEL, etc.)
- Docker and Docker Compose installed
- Git installed
- At least 2GB RAM and 20GB disk space
1. Clone Your Project
Clone your MedusaJS project to your server. This guide assumes your repository has a backend directory and a storefront directory at the root level:
git clone <your-medusa-repository-url>
cd your-medusa-project
2. Set Up Backend Configuration
2.1 Navigate to Backend Directory
cd backend
2.2 Download Starter Configuration Files
Find the file contents here: https://github.com/u11d-com/medusa-starter/tree/main/backend
curl -O https://raw.githubusercontent.com/u11d-com/medusa-starter/main/backend/start.sh
curl -O https://raw.githubusercontent.com/u11d-com/medusa-starter/main/backend/Dockerfile
curl -O https://raw.githubusercontent.com/u11d-com/medusa-starter/main/backend/.dockerignore
chmod +x start.sh
2.3 Download and Configure medusa-config.ts
curl -O https://raw.githubusercontent.com/u11d-com/medusa-starter/main/backend/medusa-config.ts
Important: Review the downloaded
medusa-config.tsfile and adjust settings according to your project. If you want to use Meilisearch with the provided stack andmedusa-config.ts, please install the following additional package to your project:
npm install @rokmohar/medusa-plugin-meilisearch
# or
yarn add @rokmohar/medusa-plugin-meilisearch
2.4 Update package.json
Add or modify the start script in your package.json:
{
"scripts": {
"start": "./start.sh"
}
}
3. Set Up Storefront Configuration
3.1 Navigate to Storefront Directory
cd ../storefront
3.2 Download Storefront Files
curl -O https://raw.githubusercontent.com/u11d-com/medusa-starter/main/storefront/Dockerfile
curl -O https://raw.githubusercontent.com/u11d-com/medusa-starter/main/storefront/.dockerignore
3.3 Download Next.js Configuration
curl -O https://raw.githubusercontent.com/u11d-com/medusa-starter/main/storefront/next.config.js
Note: Verify that the configuration matches your project structure and requirements before proceeding.
4. Configure Docker Compose
4.1 Navigate to Project Root
cd ..
4.2 Download Docker Compose Files
curl -O https://raw.githubusercontent.com/u11d-com/medusa-starter/main/compose.yaml
curl -O https://raw.githubusercontent.com/u11d-com/medusa-starter/main/compose.storefront.yaml
4.3 Edit Backend Compose File
Edit compose.yaml to:
- Set your backend environment variables
- Update your backend directory in
context: - Change admin and database credentials for security
5. Launch Backend Services
5.1 Start Services
Launch PostgreSQL, Redis, and the Medusa backend:
docker compose up -d
5.2 Wait for Initialization
Wait 30-60 seconds for services to fully initialize.
5.3 Verify Services
Check that all services are running:
docker compose ps
You should see six healthy services:
postgres(Database)redis(Cache & Event Bus)meilisearch(Search Engine)minio(S3 Compatible Object Storage)zipkin(Distributed Tracing)backend-server(Medusa backend)
6. Set Up Nginx Reverse Proxy
6.1 Install Nginx
sudo apt update
sudo apt install nginx
6.2 Create Nginx Configuration
sudo nano /etc/nginx/sites-available/app.conf
Paste this configuration:
server {
listen 80;
server_name _;
location / {
proxy_pass http://127.0.0.1:8000;
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;
}
location /auth {
proxy_pass http://127.0.0.1:9000;
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;
}
location /app {
proxy_pass http://localhost:9000;
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;
}
location /admin {
proxy_pass http://localhost:9000;
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;
}
location /store {
proxy_pass http://localhost:9000;
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;
}
}
6.3 Remove Default Configuration
sudo rm /etc/nginx/sites-enabled/default
6.4 Enable New Configuration
sudo ln -s /etc/nginx/sites-available/app.conf /etc/nginx/sites-enabled/
6.5 Reload Nginx
sudo systemctl reload nginx
6. Access Admin Panel
Open your browser and navigate to:
http://your-public-ip/app
Important: If you cannot reach Nginx on port 80 (HTTP), be aware that some cloud providers' machine images (for example, Oracle) block the port by default at the OS firewall level. In that case, follow Step 10: Configure Firewall with UFW to ensure HTTP traffic is allowed.
Log in using the credentials you set in compose.yaml:
MEDUSA_ADMIN_EMAILMEDUSA_ADMIN_PASSWORD
6.1 Generate API Key
In the admin panel:
- Go to Settings → Publishable API Keys
- Click "Create"
- Give it a descriptive name (e.g., "Storefront Production")
- Click Save
- Copy the generated key
6.2 Create a Region
In the admin panel:
- Go to Settings → Regions
- Click "Create"
- Fill in the region details.
- Add countries to the region:
- Click "Add Country"
- Select one or more countries from the dropdown
- You can add multiple countries to a single region
- Click "Save"
Important: At least one region with at least one country must be created for the storefront to function properly. Products must be associated with regions to be visible in the storefront.
7. Update Storefront Configuration
7.1 Edit Storefront Compose File
Edit your compose.storefront.yaml:
- Set your storefront environment variables
- Update your storefront directory in
context:
7.2 Add Publishable Key
Paste the publishable key you copied into the environment section:
environment:
- NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY=<your-publishable-key>
8. Deploy Storefront
8.1 Build and Start
docker compose -f compose.storefront.yaml up --build -d
Note: The initial build may take 5-10 minutes depending on your server specifications.
8.2 Access Your Storefront
Navigate to:
http://your-server-ip/
You should see your live MedusaJS storefront running on port 8000.
This comprehensive guide walks you through deploying a production-ready MedusaJS e-commerce platform using Docker on any Linux server.
9. Configure SSL with Let's Encrypt
Secure your site with a free SSL certificate from Let's Encrypt using Certbot.
9.1 Install Certbot
sudo apt update
sudo apt install certbot python3-certbot-nginx -y
9.2 Configure DNS
In your DNS panel (Cloudflare, OVH, Google Domains, etc.), create an A record:
Type: A
Name: yourdomain.com
Value: <your-server-public-IP>
TTL: Auto
Wait a few minutes for DNS propagation.
9.4 Configure your server name in Nginx
Replace:
listen 80;
server_name _;
with:
listen 80;
server_name <your-domain>;
9.3 Obtain SSL Certificate
sudo certbot --nginx -d yourdomain.com
Replace yourdomain.com with your real domain.
Certbot will automatically:
- Detect your existing HTTP server block
- Create an HTTPS server block with proper SSL paths
- Optionally configure HTTP → HTTPS redirection
9.4 Reload Nginx
sudo systemctl reload nginx
9.5 Verify your domain
Storefront:
https://yourdomain.com/
API Endpoints:
https://yourdomain.com/admin
https://yourdomain.com/app
https://yourdomain.com/store
Important: If you cannot reach Nginx on port 443 (HTTPS), be aware that some cloud providers' machine images (for example, Oracle) block the port by default at the OS firewall level. In that case, follow Step 10: Configure Firewall with UFW to ensure HTTPS traffic is allowed.
10. Configure Firewall with UFW (Optional but Recommended)
If you're using Ubuntu or another distribution with UFW (Uncomplicated Firewall), you can secure your server by only allowing necessary traffic.
10.1 Install UFW (if not installed)
sudo apt update
sudo apt install ufw -y
10.2 Set Default Policies
First, set sane defaults (deny all incoming, allow all outgoing):
sudo ufw default deny incoming
sudo ufw default allow outgoing
10.3 Allow SSH, HTTP and HTTPS
sudo ufw allow OpenSSH
sudo ufw allow http
sudo ufw allow https
If you are running SSH on a non-standard port (e.g. 2222), also allow it:
sudo ufw allow 2222/tcp
10.4 Enable UFW
Then enable UFW and verify the status:
VERY IMPORTANT: Before enabling UFW, make sure you have allowed SSH (and your custom SSH port, if you use one). Otherwise, you may lock yourself out of the server when the firewall is enabled.
sudo ufw enable
sudo ufw status verbose
After enabling, UFW will:
- Allow incoming SSH, HTTP (80) and HTTPS (443) traffic (based on the rules you added)
- Deny all other incoming connections by default
- Allow all outgoing traffic by default
You usually do not need to open Docker's internal ports (8000, 9000, database, etc.) directly in UFW, because they are not exposed publicly and Nginx acts as the secure external entry point.