Mercur
Overview
Mercur is an open source, multi-vendor marketplace platform built on the Medusa v2 commerce engine. Vendors register themselves, the marketplace operator approves them, and each vendor then manages their own products, offers, promotions, stock and orders from a dedicated panel, while the operator keeps central oversight of every store, order and payout. Because it is built on Medusa, the whole marketplace is also a headless REST API that any storefront, mobile app or point-of-sale client can consume.
This SecureAnyCloud image builds Mercur 2.2.1 and both of its web panels ahead of time, so the marketplace answers as soon as the VM finishes its first boot, with nothing to compile, download or configure.
What you get:
- Mercur 2.2.1 (MIT licensed) with the marketplace REST API, the admin panel and the vendor panel, all served by one Node process
- The admin panel at
/dashboardfor the marketplace operator, and the vendor panel at/sellerfor individual sellers, with seller self-registration enabled - PostgreSQL 16 and Redis 7 on the same VM, both bound to the loopback interface
- nginx as a reverse proxy on port 80, so the marketplace, both panels and the API share one origin
- A unique administrator account, database password, token signing secret and cookie secret generated on the first boot of every VM
mercur-set-origin, a helper that points the appliance at your own domain or TLS terminator without a rebuild- Node.js 22 and an Ubuntu 24.04 LTS base, patched at build time, with unattended security upgrades enabled
- 24/7 SecureAnyCloud support
Key facts:
- Platform: Ubuntu 24.04 LTS
- Default SSH user: azureuser
- Marketplace API: http://<vm-ip>/
- Admin panel: http://<vm-ip>/dashboard
- Vendor panel: http://<vm-ip>/seller
- Application directory: /opt/mercur
- Credentials file: /root/mercur-credentials.txt
- Recommended VM size: Standard_B2s (2 vCPU, 4 GiB)
Prerequisites
- An Azure subscription with permission to create virtual machines.
- An SSH key pair for the
azureuseraccount. - A network security group that allows inbound TCP 22 for SSH and TCP 80 for the marketplace.
- Recommended VM size: Standard_B2s (2 vCPU, 4 GiB). The whole stack runs comfortably inside that envelope.
Step 1 - Deploy from the Azure Marketplace
- In the Azure portal, choose Create a resource and search for Mercur on Ubuntu 24.04 LTS by SecureAnyCloud.
- Choose Create, then select your subscription, resource group and region.
- Set the VM size to Standard_B2s, choose SSH public key as the authentication type and set the username to
azureuser. - On the Networking tab, allow inbound SSH (22) and HTTP (80).
- Choose Review + create, then Create.
Step 2 - Deploy from the Azure CLI
Run these commands on a workstation where the Azure CLI is installed and signed in. They create the VM, open the marketplace port and print the public IP address:
az vm image terms accept --urn sac1647283583153:mercur:default:latest
az vm create \
--resource-group my-resource-group \
--name mercur-01 \
--image sac1647283583153:mercur:default:latest \
--size Standard_B2s \
--admin-username azureuser \
--generate-ssh-keys \
--public-ip-sku Standard
az vm open-port --resource-group my-resource-group --name mercur-01 --port 80
az vm show --resource-group my-resource-group --name mercur-01 \
--show-details --query publicIps --output tsvStep 3 - Connect to your VM
Connect over SSH as azureuser:
ssh azureuser@<vm-ip>Step 4 - Confirm the marketplace is running
First boot generates every per-VM secret and starts the marketplace. Confirm that it has completed:
test -f /var/lib/sac/data/mercur-firstboot.done && echo "first boot: complete"Expected output:
first boot: completeCheck the services:
systemctl is-active mercur.service postgresql redis-server nginxExpected output:
active active active activeCheck the health endpoint:
curl -s -o /dev/null -w 'health endpoint: HTTP %{http_code}\n' http://127.0.0.1/healthzExpected output:
health endpoint: HTTP 200Confirm both panels are being served:
curl -s -o /dev/null -w '/dashboard: HTTP %{http_code}\n' -L http://127.0.0.1/dashboard
curl -s -o /dev/null -w '/seller: HTTP %{http_code}\n' -L http://127.0.0.1/sellerExpected output:
/dashboard: HTTP 200 /seller: HTTP 200Step 5 - Retrieve the administrator password
The image ships with no usable account. First boot creates a single administrator with a password unique to your VM and writes it to a root-only file. Confirm the file permissions:
sudo stat -c '%a %U:%G' /root/mercur-credentials.txtExpected output:
600 root:rootRead the credentials:
sudo cat /root/mercur-credentials.txtThe file contains your marketplace URLs, the administrator email address and the generated password.
Step 6 - Sign in to the admin panel
Open http://<vm-ip>/dashboard in a browser. Sign in with the administrator email address and password from Step 5.
You land on the marketplace console. The left-hand navigation carries the standard commerce sections plus two that make this a marketplace rather than a single store: Stores, the registry of every vendor, and Payouts, what each vendor is owed.
Step 7 - Onboard your first vendor
Vendors register themselves through the vendor panel. Open http://<vm-ip>/seller in a browser and choose Create an account.
You can also register a vendor from the command line. The first command creates a member account:
TOKEN=$(curl -s -X POST -H 'Content-Type: application/json' \
-d '{"email":"vendor@example.com","password":"Choose-A-Strong-Password"}' \
http://127.0.0.1/auth/member/emailpass/register | sed -n 's/.*"token":"\([^"]*\)".*/\1/p')
echo "member registered: ${TOKEN:+yes}"Expected output:
member registered: yesThen create the store that the member owns:
curl -s -X POST -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"name":"Harbourside Supply Co.","email":"vendor@example.com","handle":"harbourside-supply","currency_code":"gbp"}' \
http://127.0.0.1/vendor/sellers | sed -n 's/.*"status":"\([^"]*\)".*/store status: \1/p'Expected output:
store status: pending_approvalA newly registered store is Pending and cannot trade until you approve it. This approval step gives the marketplace operator control over who sells on the platform.
Step 8 - Approve the store
In the admin panel, choose Stores. The vendor you just registered appears in the registry with a Pending status.
Use the row actions to review and approve the store. Once approved, the vendor can sign in at /seller and start listing products. Each vendor sees only their own catalogue and orders, while you keep the full view across every store.
Products added by your vendors appear under Products. Offers records which vendor sells which product and at what price, which lets several independent sellers list against the same catalogue entry.
Step 9 - Point the marketplace at your own domain
The appliance serves both panels from the same origin as the API, so it works on the VM address with no configuration. If you put it behind a domain name, a load balancer or a TLS terminator, set the public origin so that CORS and uploaded file URLs match:
sudo mercur-set-origin https://shop.example.comThe helper updates the marketplace configuration and restarts the service. Run it again whenever the address changes. To return to the default behavior, where the panels follow whatever address the browser used, run:
sudo mercur-set-origin --same-origin http://127.0.0.1Expected output ends with:
MERCUR_SET_ORIGIN_OK same-origin http://127.0.0.1Security
The image contains no usable credential. Every secret is generated on the first boot of your VM:
sudo /usr/local/lib/mercur/mercur-start-guard.shExpected output:
mercur-start-guard: OK - per-VM secrets in effectThis guard runs before the marketplace starts, on every start. It refuses to run if the token signing secret or cookie secret is empty, is the value published in the upstream project, or still holds a build-time value. Upstream's demo catalogue, which ships a published seller login, is never installed.
Recommended hardening:
- Restrict network access. Limit the network security group to the addresses that need it: TCP 80 only from your users, and TCP 22 only from your administrators. The marketplace process also listens on port 9000 directly. Keep that port closed in the network security group so all traffic arrives through nginx.
- Add TLS. Put a TLS certificate in front of the appliance and run
mercur-set-origin https://your-domain. The session cookie automatically becomes a Secure cookie as soon as the proxy in front setsX-Forwarded-Proto: https, so no further change is needed. - Change the administrator password. Do this after your first sign-in, from the account menu in the admin panel.
- Back up the database. Take regular backups of the PostgreSQL database, which holds every store, product, order and payout record.
Maintenance
Restart the marketplace:
sudo systemctl restart mercur.serviceCheck the service state:
sudo systemctl status mercur.service --no-pager | head -4To read the application log, use sudo journalctl -u mercur.service -n 50 --no-pager, or follow it live with sudo journalctl -u mercur.service -f.
Back up the marketplace database:
sudo -u postgres pg_dump mercur | gzip > ~/mercur-backup.sql.gz ls -lh ~/mercur-backup.sql.gzThe base image applies security updates automatically through unattended upgrades.
Server components
- Mercur 2.2.1: multi-vendor marketplace platform
- Node.js 22.x: runtime for the marketplace API and panels
- PostgreSQL 16: stores, products, orders and payouts
- Redis 7: cache, event bus, workflow engine and locking
- nginx 1.24: reverse proxy on port 80
Scripts and log files
- /opt/mercur: application directory
- /opt/mercur/packages/api/.medusa/server: built marketplace server and both panels
- /opt/mercur/panels-pristine: pristine panel bundles used by mercur-set-origin
- /root/mercur-credentials.txt: per-VM administrator credentials
- /usr/local/bin/mercur-set-origin: points the appliance at a public origin
- /stage/scripts/mercur-firstboot.sh: first-boot provisioning script
- /var/log/sac/sac-firstboot.log: first-boot log
On startup
mercur-firstboot.service runs once, on the first boot of your VM. It generates the database password, the token signing secret, the cookie secret and the administrator password. It then points the panels at this VM, applies any outstanding database migrations, and writes the marker that permits mercur.service to start. The unit disables itself afterwards, so later reboots go straight to the marketplace.
Confirm that it ran and then disabled itself:
test -f /var/lib/sac/data/mercur-firstboot.done && echo "first boot: complete" systemctl is-enabled mercur-firstboot.service || trueExpected output:
first boot: complete disableddisabled is the expected state: the unit removes itself from the boot sequence once it has provisioned the VM. systemctl returns a non-zero exit status for a disabled unit, which is why the command ends with || true.
To see what the first boot did, read the log with sudo cat /var/log/sac/sac-firstboot.log.
Troubleshooting
The panels return to the sign-in page. The marketplace signs users in with a session cookie. If a TLS terminator sits in front of the appliance, make sure it forwards X-Forwarded-Proto so the cookie is issued correctly. Then run sudo mercur-set-origin https://your-domain.
The marketplace does not answer on port 80. Check that first boot finished and the service started:
systemctl is-active mercur.service
sudo journalctl -u mercur-firstboot.service -n 20 --no-pagerThe service refuses to start. The start guard blocks startup if the per-VM secrets are missing. Run it directly to see which check failed:
sudo /usr/local/lib/mercur/mercur-start-guard.shUploaded product images do not display. The address used in uploaded file URLs is set on first boot. If you have since moved the appliance to a domain name, run sudo mercur-set-origin https://your-domain.
Support
SecureAnyCloud provides 24/7 support for this image. Contact sales@secureanycloud.com with your Azure subscription ID and the VM name.
Mercur is open source software licensed under the MIT license. SecureAnyCloud is not affiliated with or endorsed by Mercur or Medusa.
Deploy on Azure
Launch Mercur on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com