> ## Documentation Index
> Fetch the complete documentation index at: https://spreecommerce.org/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Environment Variables

> 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](/docs/developer/deployment/database) | `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.
</Warning>

| 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](/docs/developer/deployment/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](/docs/developer/deployment/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](#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](/docs/developer/deployment/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            |

## 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](/docs/developer/deployment/emails).
</Tip>

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](/docs/developer/deployment/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`](#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](/docs/developer/deployment/assets) 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](/docs/integrations/search/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:

```ruby theme={"theme":"night-owl"}
# config/initializers/spree.rb
Spree.search_provider = 'Spree::SearchProvider::Meilisearch'
```

<CodeGroup>
  ```bash Spree CLI (Docker) theme={"theme":"night-owl"}
  spree rake spree:search:reindex
  ```

  ```bash Without Spree CLI theme={"theme":"night-owl"}
  bundle exec rake spree:search:reindex
  ```
</CodeGroup>

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