---
title: Environment Variables
description: Reference for Spree deployment environment variables — database, web server, background jobs, SMTP, file storage, and application settings.
---

Spree uses environment variables for all deployment configuration. No secrets or credentials are stored in the codebase.

## Required

These two variables are all a production deployment strictly needs:

| Variable | Description | Example |
| --- | --- | --- |
| `DATABASE_URL` | Database connection URL — see [Database Configuration](database.md) | `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`](#urls-and-hosts) too — without it, generated URLs point at `localhost`.

## URLs and Hosts

`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).

> **WARNING:** When neither `RAILS_HOST` nor `CDN_HOST` is configured, image and attachment URLs fall back to the store's URL setting, which is `localhost` on a fresh install — API responses will contain `https://localhost/...` URLs.

| 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](render.md), 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](cdn.md). 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](#ssl)).

## Web Server

| 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

Background jobs (emails, image processing, webhooks, imports) run inside the web container by default — no extra service needed. See [Background Jobs](background_jobs.md) 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 |

## Email (SMTP)

> **TIP:** This configuration powers all emails Spree sends — customer transactional emails (order confirmation, shipping notification; on by default) and staff notifications. A storefront can optionally take over customer emails via webhooks — see [Emails](emails.md).

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](emails.md) 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`](#urls-and-hosts).

## Application

| Variable | Default | Description |
| --- | --- | --- |
| `RAILS_ENV` | `production` | Runtime environment — leave as `production` when deploying |
| `RAILS_LOG_LEVEL` | `info` | Log level (`debug`, `info`, `warn`, `error`) |

## File Storage (S3 / Cloudflare R2)

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](assets.md) for the full guide.

### Amazon S3

| 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 |

### Cloudflare R2

| 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 |

## Search (Meilisearch)

Optional. When configured, Spree uses [Meilisearch](../../integrations/search/meilisearch.md) 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:

```ruby
# config/initializers/spree.rb
Spree.search_provider = 'Spree::SearchProvider::Meilisearch'
```


```bash Spree CLI (Docker)
spree rake spree:search:reindex
```

```bash Without Spree CLI
bundle exec rake spree:search:reindex
```


## Error Tracking (Sentry)

| Variable | Default | Description |
| --- | --- | --- |
| `SENTRY_DSN` | — | [Sentry](https://sentry.io/) DSN. When set, errors are reported to Sentry |

## SSL

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 |

## Local Development

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 |
