Saleor on AWS User Guide
Overview
This image runs Saleor, the GraphQL-first open source e-commerce platform. Built on Python and Django with a modern React admin Dashboard, Saleor exposes every commerce capability - products, variants, collections, channels, pricing, carts, checkout, orders, fulfilment, payments, gift cards, discounts, customers and permissions - through a single, strongly typed GraphQL API. It powers headless storefronts, mobile apps and integrations against one consistent schema.
Saleor 3.23 is deployed from the official saleor-platform Docker Compose stack, pinned to the 3.23 image tags. The stack comprises the Saleor GraphQL API, the Saleor Dashboard admin single page application, a PostgreSQL 15 database, a Valkey (Redis-compatible) cache and Celery broker, a Celery worker for background jobs and a local mail capture service for transactional email. Docker Engine and the Docker Compose plugin are installed from the official Docker package repository, and the stack runs as a saleor.service systemd unit that brings it up on boot.
An nginx reverse proxy on port 80 is the single public entry point. It proxies the GraphQL API paths (/graphql/, /media/ and related) to the API container and serves everything else - the Dashboard - from the Dashboard container. The Dashboard is configured to talk to the API on the same origin, so it works from any browser that reaches the instance with no per host rebuild.
The PostgreSQL database, the Valkey state and your media uploads live on a dedicated, independently resizable EBS data volume mounted at /var/lib/saleor, so your catalogue, orders, customers and media survive instance replacement. On the first boot of every deployed instance a one shot service runs the database migrations against a clean database, generates a fresh Django secret key and JWT signing key, generates an administrator password and creates the first Dashboard administrator. No demo data and no shared or default credentials ship in the image. The administrator password is written to /root/saleor-credentials.txt with mode 0600 so that only the root user can read it.
Prerequisites
Before you deploy this image you need:
- An Amazon Web Services account where you can launch EC2 instances
- IAM permissions to launch instances, create security groups, and subscribe to AWS Marketplace products
- An EC2 key pair in the target Region for SSH access to the instance
- A VPC and subnet in the target Region, with a security group allowing inbound port 22 from your management network and port 80 for the Dashboard and API
- The AWS CLI (version 2) installed locally if you plan to deploy from the command line
Step 1: Launch the Instance from the AWS Marketplace
Sign in to the AWS Management Console, open the EC2 service, and select Launch instance. Under Application and OS Images choose AWS Marketplace AMIs and search for Saleor. Select the cloudimg listing and choose Select, then Continue on the subscription summary.
Pick an instance type of t3.large or larger; Saleor runs several containers including PostgreSQL and a Celery worker, so it needs the memory. Choose your EC2 key pair under Key pair (login). Under Network settings select your VPC and subnet, and either create or select a security group that opens port 22 from your management network and port 80 for the Dashboard and API. Leave the root volume at the default size or larger.
Select Launch instance. First boot initialisation runs the database migrations and creates the administrator; on a fresh instance this takes a minute or two after the instance state becomes Running and the status checks pass.
Step 2: Launch the Instance from the AWS CLI
The following block launches an instance from the cloudimg Saleor Marketplace AMI into an existing subnet and security group. Replace <ami-id> with the AMI ID shown on the Marketplace listing, <key-name> with your EC2 key pair name, <subnet-id> with your subnet ID, and <security-group-id> with a security group that opens ports 22 and 80 as described above.
aws ec2 run-instances \
--image-id <ami-id> \
--instance-type t3.large \
--key-name <key-name> \
--subnet-id <subnet-id> \
--security-group-ids <security-group-id> \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=saleor}]'
When the instance reaches the Running state and its status checks pass, note its public IP address or DNS name from the EC2 console or with aws ec2 describe-instances.
Step 3: Connect to Your Instance
Connect over SSH using your key pair and the login user for your operating system variant.
| OS variant | SSH login user |
|---|---|
| Ubuntu 24.04 | ubuntu |
ssh -i <key-name>.pem ubuntu@<public-ip>
Step 4: Retrieve the Admin Password
The Dashboard administrator password is unique to your instance and was generated on first boot. Read the credentials file as root:
sudo cat /root/saleor-credentials.txt
The file lists the Dashboard URL, the GraphQL endpoint, the administrator email (admin@cloudimg.local) and the generated password. Keep this password somewhere safe.
Step 5: Sign In to the Dashboard
The Saleor Dashboard is served on port 80 by nginx. In a browser, go to:
http://<instance-public-ip>/
You are presented with the Saleor sign in page. Sign in with the email admin@cloudimg.local and the password from the credentials file. The Dashboard home then loads, with the catalogue, fulfilment, customers, discounts and configuration navigation on the left and your store overview in the centre.

Open Catalog then Products to manage your products, variants, collections and channels. This is where you build and curate the catalogue that your storefronts read over the GraphQL API.

Open Orders to review and manage customer orders, with their payment and fulfilment status, totals and channel.

Step 6: Confirm Saleor Is Running
Over SSH, confirm the systemd unit, Docker and nginx are active and that the Compose stack containers are up:
sudo systemctl is-active saleor nginx docker
sudo /opt/saleor/saleor-compose.sh ps --format '{{.Service}} {{.Status}}'
You should see the services reported as active and the api, dashboard, db, cache and worker containers all running.
Step 7: Use the GraphQL API
Every Saleor capability is exposed through the GraphQL API at the /graphql/ path on port 80. A simple, public query returns the shop name and confirms the API is reachable:
curl -s http://127.0.0.1/graphql/ \
-H 'Content-Type: application/json' \
--data '{"query":"{ shop { name } }"}'
To make authenticated calls, obtain an access token with the tokenCreate mutation. The following reads the administrator email and password from the credentials file and requests a token over loopback:
SALEOR_EMAIL=$(sudo grep '^saleor.admin.email=' /root/saleor-credentials.txt | cut -d= -f2-)
SALEOR_PASS=$(sudo grep '^saleor.admin.pass=' /root/saleor-credentials.txt | cut -d= -f2-)
curl -s http://127.0.0.1/graphql/ \
-H 'Content-Type: application/json' \
--data "{\"query\":\"mutation{tokenCreate(email:\\\"$SALEOR_EMAIL\\\",password:\\\"$SALEOR_PASS\\\"){token errors{message}}}\"}"
A successful request returns a JSON object containing a token (a signed JWT). Pass it as a bearer token on subsequent authenticated calls, for example to read the current user:
SALEOR_EMAIL=$(sudo grep '^saleor.admin.email=' /root/saleor-credentials.txt | cut -d= -f2-)
SALEOR_PASS=$(sudo grep '^saleor.admin.pass=' /root/saleor-credentials.txt | cut -d= -f2-)
SALEOR_TOKEN=$(curl -s http://127.0.0.1/graphql/ -H 'Content-Type: application/json' \
--data "{\"query\":\"mutation{tokenCreate(email:\\\"$SALEOR_EMAIL\\\",password:\\\"$SALEOR_PASS\\\"){token}}\"}" \
| python3 -c 'import sys,json;print(json.load(sys.stdin)["data"]["tokenCreate"]["token"])')
curl -s http://127.0.0.1/graphql/ \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $SALEOR_TOKEN" \
--data '{"query":"{ me { email isStaff } }"}'
From outside the instance, replace 127.0.0.1 with the instance public IP. See the Saleor documentation for the full GraphQL schema.
Step 8: The Data Volume
The Saleor data tier lives on a dedicated EBS volume mounted at /var/lib/saleor. This holds the PostgreSQL database (under db), the Valkey state (under cache) and your media uploads (under media), keeping them off the operating system disk and letting you resize or snapshot them independently. Confirm the mount with:
df -h /var/lib/saleor
To grow the data tier, expand the EBS volume in the AWS console, then grow the filesystem on the instance with sudo resize2fs on the underlying device. Because this volume holds your catalogue, orders, customers and media, snapshotting it captures the complete state of your Saleor deployment.
Step 9: Enable HTTPS
The Dashboard and the GraphQL API are served over plain HTTP on port 80 by nginx. For production use, place them behind TLS. Obtain a certificate for your domain (for example with a managed certificate on an Application Load Balancer in front of the instance, or with Certbot installed on the instance), then configure nginx to listen on 443 with your certificate and proxy to the API and Dashboard containers exactly as the bundled site does for port 80. Restrict the security group so ports 80 and 443 are reachable only from the networks that need the store and the API.
Step 10: Backup and Maintenance
Back up your deployment by snapshotting the /var/lib/saleor EBS volume, which captures the PostgreSQL database, the cache state and all media. Apply operating system security updates with sudo apt-get update && sudo apt-get upgrade and reboot when a new kernel is installed; the Saleor stack, Docker and nginx all start automatically on boot. To pull a newer Saleor image version, update the image tags in /opt/saleor/docker-compose.yml, then run sudo /opt/saleor/saleor-compose.sh pull followed by sudo /opt/saleor/saleor-compose.sh up -d and apply any new migrations.
Support
This image is published and supported by cloudimg. Support covers deployment, channels and catalogue configuration, the GraphQL API, webhooks and the App framework, payments and fulfilment, PostgreSQL and media storage, TLS and runtime tuning. Contact cloudimg through the support channel listed on the AWS Marketplace listing.
Saleor is a trademark of its respective owner. All other product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.