docs/developer/deployment/environment_variables.mdx
Spree uses environment variables for all deployment configuration. No secrets or credentials are stored in the codebase.
These two variables are all a production deployment strictly needs:
| Variable | Description | Example |
|---|---|---|
DATABASE_URL | Database connection URL — see Database Configuration | postgres://user:pass@localhost:5432/spree |
SECRET_KEY_BASE | Secret used to encrypt sessions and cookies. Generate with openssl rand -hex 64 | 2fad5c0b79d25e4765d3018d8c740f8c3a665f0e5c... |
You'll almost always want to set RAILS_HOST too — without it, generated URLs point at localhost.
RAILS_HOST is the canonical public host of your deployment. URLs Spree generates outside a request context use it — links in emails, webhook payloads, and image/attachment URLs in API responses (for the latter, CDN_HOST takes precedence when set).
| Variable | Default | Description |
|---|---|---|
RAILS_HOST | — | Public host, optionally with a port — e.g. store.example.com or 203.0.113.7:8080. Host only, no protocol. On Render, falls back to the platform-provided RENDER_EXTERNAL_HOSTNAME. |
CDN_HOST | — | Optional host for serving static assets and images, e.g. a CDN distribution in front of your app — see CDN. Host only, no protocol. Falls back to RAILS_HOST. |
Generated URLs use https unless both RAILS_FORCE_SSL and RAILS_ASSUME_SSL are set to false (see SSL).
| Variable | Default | Description |
|---|---|---|
PORT | 3000 | Port the web server listens on |
RAILS_MAX_THREADS | 3 | Concurrent requests each web server process handles |
WEB_CONCURRENCY | 1 | Number of web server processes per container. Set to auto for one per CPU core — each process needs roughly 1 GB of RAM |
Background jobs (emails, image processing, webhooks, imports) run inside the web container by default — no extra service needed. See Background Jobs for how this works and when to split out a dedicated worker.
| Variable | Default | Description |
|---|---|---|
SOLID_QUEUE_IN_PUMA | true | Run background jobs inside the web container. Set to false when you run a dedicated worker service (bin/jobs) |
JOB_THREADS | 3 | How many background jobs run concurrently. Raise it on a dedicated worker; the database connection pool sizes itself from this |
JOB_CONCURRENCY | 1 | Number of worker processes — the scaling knob for a dedicated worker |
SPREE_IMPORT_JOB_CONCURRENCY | 75% of JOB_THREADS | How much of the job capacity a single CSV import may occupy, so imports can't starve other work. 0 removes the cap |
MISSION_CONTROL_USER / MISSION_CONTROL_PASSWORD | — | Login for the /jobs dashboard (HTTP Basic auth). Required in production — the dashboard stays locked without them |
Spree works with any SMTP provider (Resend, Postmark, Mailgun, SendGrid, Amazon SES, etc.). Set SMTP_HOST to enable email delivery — when not set, production email delivery is disabled (in development, emails are captured by Mailpit at http://localhost:8025 instead of being sent). See Emails for the full guide.
| Variable | Default | Description |
|---|---|---|
SMTP_HOST | — | SMTP server address (e.g., smtp.sendgrid.net) |
SMTP_PORT | 587 | SMTP server port |
SMTP_USERNAME | — | SMTP auth username |
SMTP_PASSWORD | — | SMTP auth password |
SMTP_FROM_ADDRESS | — | Default "from" email address |
Links in emails use the host configured via RAILS_HOST.
| Variable | Default | Description |
|---|---|---|
RAILS_ENV | production | Runtime environment — leave as production when deploying |
RAILS_LOG_LEVEL | info | Log level (debug, info, warn, error) |
By default, uploaded files (product images, assets) are stored on the local filesystem. Set the appropriate credentials to use cloud storage instead — Spree auto-detects the provider based on which credentials are present. See Asset Storage for the full guide.
| Variable | Default | Description |
|---|---|---|
AWS_ACCESS_KEY_ID | — | AWS access key |
AWS_SECRET_ACCESS_KEY | — | AWS secret key |
AWS_REGION | — | AWS region (e.g., us-east-1) |
AWS_BUCKET | spree-production | S3 bucket name |
| Variable | Default | Description |
|---|---|---|
CLOUDFLARE_ENDPOINT | — | R2 endpoint URL |
CLOUDFLARE_ACCESS_KEY_ID | — | R2 access key |
CLOUDFLARE_SECRET_ACCESS_KEY | — | R2 secret key |
CLOUDFLARE_BUCKET | spree-production | R2 bucket name |
Optional. When configured, Spree uses Meilisearch for product search, filtering, and faceted navigation instead of SQL.
| Variable | Default | Description |
|---|---|---|
MEILISEARCH_URL | http://localhost:7700 | Meilisearch server URL |
MEILISEARCH_API_KEY | — | Meilisearch master key. Not needed for local development — only required when Meilisearch is started with MEILI_MASTER_KEY. |
After setting these, enable the provider and reindex:
# config/initializers/spree.rb
Spree.search_provider = 'Spree::SearchProvider::Meilisearch'
spree rake spree:search:reindex
bundle exec rake spree:search:reindex
| Variable | Default | Description |
|---|---|---|
SENTRY_DSN | — | Sentry DSN. When set, errors are reported to Sentry |
By default, Spree assumes it runs behind an SSL-terminating reverse proxy or load balancer. Set these to false if running without SSL (e.g., local development or behind a proxy that doesn't do SSL termination).
| Variable | Default | Description |
|---|---|---|
RAILS_ASSUME_SSL | true | Treat incoming requests as arriving over HTTPS (trust the proxy's forwarded headers) |
RAILS_FORCE_SSL | true | Redirect HTTP to HTTPS and use secure cookies |
These variables are used when running the server/ app locally (not via DATABASE_URL):
| Variable | Default | Description |
|---|---|---|
DATABASE_HOST | localhost | PostgreSQL host |
DATABASE_PORT | 5432 | PostgreSQL port |
DATABASE_USERNAME | postgres | PostgreSQL user |