Deploy Spree

Open-source eCommerce platform with a REST API and admin dashboard

Deploy Spree

Just deployed

/var/lib/postgresql/data

Just deployed

/meili_data

Just deployed

/data

spree-worker

spree/spree:5.6.1

Just deployed

spree-storage

Bucket

Just deployed

Deploy and Host Spree on Railway

Spree is an open-source headless commerce platform built on Ruby on Rails, under the BSD 3-Clause licence. It ships a REST API, a TypeScript SDK, a React admin dashboard and a production-ready Next.js storefront, so brands, B2B wholesalers and marketplaces can run a real store with no platform fees and no vendor lock-in. Teams self-host Spree when a hosted platform cannot express their pricing or checkout: price lists per customer group, per-country markets, gift cards and digital products are all in the open-source core.

Deploy Spree on Railway and this template wires the production shape for you. The spree service runs Puma, the admin dashboard and the REST API. spree-worker is a dedicated Solid Queue process handling emails, image processing, imports, webhooks and search indexing off the request path. Postgres holds the catalogue and orders and — because Spree uses the Solid stack — the job queue, cache and Action Cable messages, so there is no Redis to run. meilisearch gives typo-tolerant product search, mailpit captures outbound email, and a Railway bucket holds product images through Active Storage.

Diagram of Spree web, worker, Postgres, Meilisearch and Mailpit on Railway

Getting Started with Spree on Railway

Set ADMIN_EMAIL and ADMIN_PASSWORD before you click Deploy — Spree's first-boot seed reads them once and creates your administrator account. Leave them blank and it prints a one-time claim link in the logs instead, which is not what you want on a public URL. When the deploy is green, open the app's domain: / redirects to /admin. Start at Products → New Product, give it a name, price, SKU and stock count, then drop an image into the Media panel — the upload goes straight to your Railway bucket, and the thumbnail confirms object storage is wired. Create a draft order from Orders → New Order to check pricing and inventory. Invite a colleague from Settings → Users: the invitation lands in the Mailpit inbox on its own domain, proving the worker and mail path work end to end. Visit /jobs for the Solid Queue dashboard.

Spree admin product catalogue listing four active products with prices Spree product editor showing media, pricing and inventory fields Spree draft order with two line items and customer contact details

About Hosting Spree

Spree is API-first: the admin dashboard, the Next.js storefront, a mobile app and a point of sale all talk to the same REST API, so you can start with one backend and add channels later. Self-hosting earns its keep when you need to own customer and order data outright, or when your pricing rules are too specific for a SaaS product.

  • Sales channels, markets and multi-currency cross-border selling
  • B2B price lists, customer groups and gated catalogues
  • Promotions engine, gift cards, store credit and digital products
  • Stripe, Adyen and PayPal payment plugins bundled in the image

Web and worker run the same image; the web service hands jobs over by setting SOLID_QUEUE_IN_PUMA=false. Meilisearch switches on purely by the presence of MEILISEARCH_URL, so it needs no code change. Mailpit is capture-only — swap it for a real provider before you take orders.

Why Deploy Spree on Railway

Standing up six moving parts by hand is a day of work.

  • Every service, volume and connection string pre-wired
  • Managed Postgres with backups, and no Redis to operate
  • Private networking between app, worker, search and mail
  • HTTPS domain issued automatically for the admin and API
  • Scale by raising replicas or worker threads
  • Usage-based pricing with no per-order commerce fees

Common Use Cases

  • A direct-to-consumer brand running the Next.js storefront against a self-hosted API
  • B2B wholesale with negotiated price lists per customer group and gated catalogues
  • A headless backend for a mobile app or point of sale sharing one catalogue

Dependencies for Spree

  • ghcr.io/spree/spree — the Rails application, admin dashboard and REST API
  • ghcr.io/railwayapp-templates/postgres-ssl:18 — catalogue, orders, jobs, cache, Action Cable
  • getmeili/meilisearch:v1.53 — product search index with facets and typo tolerance
  • axllent/mailpit:v1.31 — SMTP sink and web inbox for outbound mail
  • Railway object storage — product images and attachments via Active Storage

Postgres is the only hard dependency; Solid Queue, Solid Cache and Solid Cable all live inside it, which is why there is no separate queue or cache. Meilisearch earns its place once a catalogue passes roughly a thousand products, and Mailpit makes order mail visible from day one instead of silently disappearing.

Environment Variables Reference

VariableServicePurpose
DATABASE_URLspree, spree-workerPostgres connection string
SECRET_KEY_BASEspreeSigns sessions and cookies; shared with the worker
RAILS_HOSTspree, spree-workerPublic host used in emails and image URLs
ADMIN_EMAIL / ADMIN_PASSWORDspreeFirst administrator, created at first boot
MISSION_CONTROL_*spreeBasic auth for the /jobs dashboard
SOLID_QUEUE_IN_PUMAspreefalse while a dedicated worker runs
WEB_CONCURRENCYspreePuma processes; each needs about 1 GB
MEILISEARCH_URL / MEILISEARCH_API_KEYspree, spree-workerEnables the Meilisearch search provider
SMTP_HOST / SMTP_PORTspree, spree-workerOutbound mail; unset disables delivery
CLOUDFLARE_*spree, spree-workerBucket credentials for uploads

Deployment Dependencies

Hardware Requirements for Self-Hosting Spree

ResourceMinimumRecommended
CPU1 vCPU2–4 vCPU
RAM1 GB4 GB across web, worker and search
Storage5 GB Postgres volume10 GB plus object storage for media
RuntimeRuby 4.0 / Rails 8.1 (in the image)Same, plus PostgreSQL 18

Raise WEB_CONCURRENCY only alongside memory, and never set it to auto: it counts the machine's cores, not your container's limit.

Self-Hosting Spree with Docker

The official image runs migrations on boot and needs only a database. The following is a minimal Docker Compose file:

services:
  postgres:
    image: postgres:18-alpine
    environment:
      POSTGRES_HOST_AUTH_METHOD: trust
    volumes: [pg:/var/lib/postgresql/data]
  web:
    image: ghcr.io/spree/spree:latest
    environment:
      DATABASE_URL: postgres://postgres@postgres:5432/spree_production
      SECRET_KEY_BASE: replace-with-a-long-random-string
      RAILS_HOST: localhost:3000
      ADMIN_EMAIL: you@example.com
      ADMIN_PASSWORD: choose-a-strong-password
    ports: ["3000:3000"]
volumes: { pg: }

To split background processing out, set SOLID_QUEUE_IN_PUMA=false on the web service and run the same image with a different command:

docker run --rm -e DATABASE_URL=... -e SECRET_KEY_BASE=... \
  ghcr.io/spree/spree:latest ./bin/jobs

To customise the store instead, scaffold it with npx create-spree-app@latest my-store, run spree eject, and build the backend/Dockerfile it produces.

How Much Does Spree Cost to Self-Host?

Spree's core is free and open source under the BSD 3-Clause licence, with no per-order or per-transaction fees — you keep the code, the data and the infrastructure. A paid Enterprise Edition adds extra modules and SLA-backed support, but nothing here depends on it. On Railway you pay only for the compute, storage and bandwidth used, so a small store costs a few dollars a month and grows with traffic rather than with revenue.

FAQ

What is Spree?

Spree is an open-source headless commerce platform written in Ruby on Rails. It ships a REST API, a TypeScript SDK, a React admin dashboard and an optional Next.js storefront, and powers direct-to-consumer brands, B2B wholesalers and marketplaces.

What does this Railway template deploy?

Five services — the Spree web application, a background worker, PostgreSQL, Meilisearch and Mailpit — plus an object storage bucket for media. Every connection string, volume and domain is configured before the first boot.

Why does the template include a separate worker service?

Spree runs emails, image processing, imports, webhooks and search indexing as background jobs. Keeping them in spree-worker means a large import cannot slow down checkout. Drop the service and set SOLID_QUEUE_IN_PUMA=true to run everything in one container.

Do I need Redis to self-host Spree?

No. Solid Queue, Solid Cache and Solid Cable all store their data in PostgreSQL — one fewer service to operate and back up.

How do I create the first admin user in self-hosted Spree?

Set ADMIN_EMAIL and ADMIN_PASSWORD before the first deploy; the seed creates the account. Further administrators are invited from Settings → Users.

How do I send real emails from Spree instead of using Mailpit?

Point SMTP_HOST, SMTP_PORT, SMTP_USERNAME and SMTP_PASSWORD at any provider — Resend, Postmark, Mailgun or Amazon SES — and set the store's From address under Settings → Emails.


Template Content

More templates in this category

View Template
Rocky Linux
Hosted Rocky Linux 9 workspace with SSH and persistent storage. 🚀

codestorm
44
View Template
Foundry Virtual Tabletop
A Self-Hosted & Modern Roleplaying Platform

Lucas
71
View Template
Letta Code Remote
Run a Letta Code agent 24/7. No inbound ports, just deploy.

Letta
51