@spree/docs 0.1.257 → 0.1.258
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/developer/cli/quickstart.md +11 -0
- package/dist/developer/core-concepts/payments.md +1 -1
- package/dist/developer/create-spree-app/quickstart.md +1 -1
- package/dist/developer/deployment/aws.md +5 -0
- package/dist/developer/deployment/aws_ecs.md +27 -0
- package/dist/developer/deployment/docker.md +10 -0
- package/dist/developer/deployment/environment_variables.md +53 -2
- package/dist/developer/deployment/render.md +1 -1
- package/dist/developer/security/security_policy.md +1 -0
- package/dist/developer/upgrades/5.6-to-6.0.md +35 -0
- package/package.json +1 -1
|
@@ -195,6 +195,17 @@ spree api-key create --name "Admin" --type secret --scopes read_all # Admin
|
|
|
195
195
|
spree api-key revoke <id> # Revoke a key
|
|
196
196
|
```
|
|
197
197
|
|
|
198
|
+
### `spree encryption init`
|
|
199
|
+
|
|
200
|
+
Generate [Active Record encryption](../deployment/environment_variables.md#active-record-encryption) keys — Spree encrypts webhook signing secrets, payment gateway customer IDs and OAuth tokens with them. New projects already have keys; use this for projects created before they were generated at setup.
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
spree encryption init # Add ACTIVE_RECORD_ENCRYPTION_* keys to the project's .env
|
|
204
|
+
spree encryption init --print # Print a fresh set without writing anything (e.g. for your hosting provider)
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
It never overwrites keys `.env` already sets, and there is no `--force`: changing the keys makes data encrypted with them unreadable. Afterwards, recreate the containers so they load the new `.env` (`spree update`, or `spree dev` for an ejected project — `spree restart` keeps the old environment), and back the keys up in your secret manager.
|
|
208
|
+
|
|
198
209
|
### `spree api`
|
|
199
210
|
|
|
200
211
|
Call the Admin API with generic `get`/`post`/`patch`/`delete` commands — zero-config inside a project (a read-only key is minted on first use), env vars or profiles for remote stores. See [Admin API from the CLI](admin-api.md) for the full guide.
|
|
@@ -637,7 +637,7 @@ Maps a Spree customer to their provider-specific customer profile. This enables
|
|
|
637
637
|
| `payment_method_id` | The gateway this customer belongs to | `1` |
|
|
638
638
|
| `customer_id` | The Spree customer | `42` |
|
|
639
639
|
|
|
640
|
-
A customer has at most one record per payment method, and `profile_id` is encrypted with Active Record
|
|
640
|
+
A customer has at most one record per payment method, and `profile_id` is encrypted with [Active Record encryption](../deployment/environment_variables.md#active-record-encryption) where it is configured.
|
|
641
641
|
|
|
642
642
|
> **NOTE:** This one is internal — the API does not expose it. It is listed here because
|
|
643
643
|
> gateway integrations rely on it; nothing a storefront does will read it.
|
|
@@ -63,7 +63,7 @@ my-store/
|
|
|
63
63
|
│ ├── seller-dashboard/ # Seller panel, for marketplaces (React)
|
|
64
64
|
│ └── storefront/ # Next.js storefront (unless --no-storefront)
|
|
65
65
|
│ └── .env.local # API URL + publishable key
|
|
66
|
-
├── .env # SECRET_KEY_BASE, SPREE_PORT, SPREE_VERSION_TAG, SPREE_SAMPLE_DATA
|
|
66
|
+
├── .env # SECRET_KEY_BASE, encryption keys, SPREE_PORT, SPREE_VERSION_TAG, SPREE_SAMPLE_DATA
|
|
67
67
|
├── .spree/ # CLI credentials — gitignored, created on first run
|
|
68
68
|
├── docker-compose.yml # Spree backend (prebuilt image) + Postgres + Meilisearch
|
|
69
69
|
├── docker-compose.dev.yml # Alternative: build from local server/
|
|
@@ -49,6 +49,11 @@ services:
|
|
|
49
49
|
environment:
|
|
50
50
|
DATABASE_URL: postgres://spree:YOUR_PASSWORD@your-db.abc123.eu-west-1.rds.amazonaws.com:5432/spree_production
|
|
51
51
|
SECRET_KEY_BASE: generate-with-openssl-rand-hex-64
|
|
52
|
+
# Active Record encryption — generate with `spree encryption init --print`
|
|
53
|
+
# or `bin/rails db:encryption:init`; never change them once data is encrypted
|
|
54
|
+
ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY: ...
|
|
55
|
+
ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY: ...
|
|
56
|
+
ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT: ...
|
|
52
57
|
RAILS_HOST: store.example.com
|
|
53
58
|
# Uploads to S3 (recommended) — see /developer/deployment/assets
|
|
54
59
|
# AWS_REGION: eu-west-1
|
|
@@ -222,6 +222,9 @@ Create the following secrets in AWS Secrets Manager:
|
|
|
222
222
|
|---|---|---|
|
|
223
223
|
| `spree/database-url` | `DATABASE_URL` | PostgreSQL connection URL |
|
|
224
224
|
| `spree/secret-key-base` | `SECRET_KEY_BASE` | Generate with `bin/rails secret` |
|
|
225
|
+
| `spree/ar-encryption-primary-key` | `ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY` | [Active Record encryption](environment_variables.md#active-record-encryption) keys — generate all three with `bin/rails db:encryption:init` (or `spree encryption init --print`). Never change them once data is encrypted |
|
|
226
|
+
| `spree/ar-encryption-deterministic-key` | `ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY` | Generated together with the primary key |
|
|
227
|
+
| `spree/ar-encryption-key-derivation-salt` | `ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT` | Generated together with the primary key |
|
|
225
228
|
|
|
226
229
|
Optional secrets for email delivery, file storage, and error tracking:
|
|
227
230
|
|
|
@@ -292,6 +295,18 @@ One task definition runs the whole app — the web server also runs background j
|
|
|
292
295
|
{
|
|
293
296
|
"name": "SECRET_KEY_BASE",
|
|
294
297
|
"valueFrom": "arn:aws:secretsmanager:${AWS_REGION}:${AWS_ACCOUNT_ID}:secret:spree/secret-key-base"
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
"name": "ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY",
|
|
301
|
+
"valueFrom": "arn:aws:secretsmanager:${AWS_REGION}:${AWS_ACCOUNT_ID}:secret:spree/ar-encryption-primary-key"
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
"name": "ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY",
|
|
305
|
+
"valueFrom": "arn:aws:secretsmanager:${AWS_REGION}:${AWS_ACCOUNT_ID}:secret:spree/ar-encryption-deterministic-key"
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
"name": "ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT",
|
|
309
|
+
"valueFrom": "arn:aws:secretsmanager:${AWS_REGION}:${AWS_ACCOUNT_ID}:secret:spree/ar-encryption-key-derivation-salt"
|
|
295
310
|
}
|
|
296
311
|
],
|
|
297
312
|
"logConfiguration": {
|
|
@@ -351,6 +366,18 @@ Switches to [split mode](quickstart.md#web-and-worker): background jobs move int
|
|
|
351
366
|
{
|
|
352
367
|
"name": "SECRET_KEY_BASE",
|
|
353
368
|
"valueFrom": "arn:aws:secretsmanager:${AWS_REGION}:${AWS_ACCOUNT_ID}:secret:spree/secret-key-base"
|
|
369
|
+
},
|
|
370
|
+
{
|
|
371
|
+
"name": "ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY",
|
|
372
|
+
"valueFrom": "arn:aws:secretsmanager:${AWS_REGION}:${AWS_ACCOUNT_ID}:secret:spree/ar-encryption-primary-key"
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
"name": "ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY",
|
|
376
|
+
"valueFrom": "arn:aws:secretsmanager:${AWS_REGION}:${AWS_ACCOUNT_ID}:secret:spree/ar-encryption-deterministic-key"
|
|
377
|
+
},
|
|
378
|
+
{
|
|
379
|
+
"name": "ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT",
|
|
380
|
+
"valueFrom": "arn:aws:secretsmanager:${AWS_REGION}:${AWS_ACCOUNT_ID}:secret:spree/ar-encryption-key-derivation-salt"
|
|
354
381
|
}
|
|
355
382
|
],
|
|
356
383
|
"logConfiguration": {
|
|
@@ -54,6 +54,11 @@ services:
|
|
|
54
54
|
environment:
|
|
55
55
|
DATABASE_URL: postgres://postgres@postgres:5432/spree_production
|
|
56
56
|
SECRET_KEY_BASE: change-me-to-a-real-secret
|
|
57
|
+
# Active Record encryption — generate with `spree encryption init --print`
|
|
58
|
+
# or `bin/rails db:encryption:init`; never change them once data is encrypted
|
|
59
|
+
ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY: change-me
|
|
60
|
+
ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY: change-me
|
|
61
|
+
ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT: change-me
|
|
57
62
|
RAILS_FORCE_SSL: "false"
|
|
58
63
|
RAILS_ASSUME_SSL: "false"
|
|
59
64
|
# Public host used in generated URLs (images/attachments in API
|
|
@@ -93,6 +98,10 @@ Background jobs run inside the web container by default. When job load deserves
|
|
|
93
98
|
environment:
|
|
94
99
|
DATABASE_URL: postgres://postgres@postgres:5432/spree_production
|
|
95
100
|
SECRET_KEY_BASE: change-me-to-a-real-secret
|
|
101
|
+
# the same encryption keys as web
|
|
102
|
+
ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY: change-me
|
|
103
|
+
ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY: change-me
|
|
104
|
+
ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT: change-me
|
|
96
105
|
RAILS_HOST: localhost:3000
|
|
97
106
|
command: bin/jobs
|
|
98
107
|
```
|
|
@@ -103,6 +112,7 @@ Background jobs run inside the web container by default. When job load deserves
|
|
|
103
112
|
| --- | --- | --- |
|
|
104
113
|
| `DATABASE_URL` | PostgreSQL connection URL | `postgres://user:pass@host:5432/spree` |
|
|
105
114
|
| `SECRET_KEY_BASE` | Secret key for session encryption | Generate with `bin/rails secret` |
|
|
115
|
+
| `ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY`, `ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY`, `ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT` | Keys Spree encrypts secrets at rest with — see [Active Record encryption](environment_variables.md#active-record-encryption). Never change them once data is encrypted | Generate with `spree encryption init --print` or `bin/rails db:encryption:init` |
|
|
106
116
|
| `RAILS_HOST` | Public host used in generated URLs — image/attachment URLs in API responses, email links | `store.example.com` |
|
|
107
117
|
| `SOLID_QUEUE_IN_PUMA` | Run background jobs inside the web container (default `true`); set `false` when running a dedicated worker | `true` |
|
|
108
118
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Environment Variables
|
|
3
|
-
description: Reference for Spree deployment environment variables — database, web server, background jobs, SMTP, file storage, and application settings.
|
|
3
|
+
description: Reference for Spree deployment environment variables — database, secrets and encryption keys, web server, background jobs, SMTP, file storage, and application settings.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
Spree uses environment variables for all deployment configuration. No secrets or credentials are stored in the codebase.
|
|
@@ -14,7 +14,58 @@ These two variables are all a production deployment strictly needs:
|
|
|
14
14
|
| `DATABASE_URL` | Database connection URL — see [Database Configuration](database.md) | `postgres://user:pass@localhost:5432/spree` |
|
|
15
15
|
| `SECRET_KEY_BASE` | Secret used to encrypt sessions and cookies. Generate with `openssl rand -hex 64` | `2fad5c0b79d25e4765d3018d8c740f8c3a665f0e5c...` |
|
|
16
16
|
|
|
17
|
-
You'll almost always want to set [`RAILS_HOST`](#urls-and-hosts) too — without it, generated URLs point at `localhost
|
|
17
|
+
You'll almost always want to set [`RAILS_HOST`](#urls-and-hosts) too — without it, generated URLs point at `localhost`, and the three [Active Record encryption](#active-record-encryption) keys — without them, secrets Spree stores are kept in plain text.
|
|
18
|
+
|
|
19
|
+
## Active Record encryption
|
|
20
|
+
|
|
21
|
+
Spree encrypts sensitive values at rest with [Active Record encryption](https://guides.rubyonrails.org/active_record_encryption.html): webhook endpoint signing secrets, payment gateway customer IDs, and the OAuth tokens stored on user identities. It does so only when encryption keys are configured — without them, these values are stored in plain text and a production app logs a warning at boot.
|
|
22
|
+
|
|
23
|
+
| Variable | Description |
|
|
24
|
+
| --- | --- |
|
|
25
|
+
| `ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY` | Key for (non-deterministic) encrypted attributes |
|
|
26
|
+
| `ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY` | Key for deterministic encrypted attributes — the ones Spree looks records up by, such as webhook signing secrets and gateway customer IDs |
|
|
27
|
+
| `ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT` | Salt for deriving the encryption keys |
|
|
28
|
+
|
|
29
|
+
Set all three. Each is a random string — generate a set with any of:
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
```bash Spree CLI
|
|
33
|
+
spree encryption init # writes a set to your project's .env (never overwrites existing keys)
|
|
34
|
+
spree encryption init --print # prints a fresh set, e.g. for your hosting provider
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
```bash Without Spree CLI
|
|
38
|
+
bin/rails db:encryption:init
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
- **New projects** — `create-spree-app` generates the keys into `.env`, and the [Render Blueprint](render.md) generates them for production.
|
|
43
|
+
- **Production** — use a separate set of keys from development and store it in your secret manager as a backup.
|
|
44
|
+
- **Rails credentials** — instead of env vars, you can put the values printed by `bin/rails db:encryption:init` under `active_record_encryption` in your encrypted credentials. When both are present, the env vars win.
|
|
45
|
+
|
|
46
|
+
> **WARNING:** Never change or lose the keys once data is encrypted — records encrypted with them become unreadable. Rails supports [rotating the primary key](https://guides.rubyonrails.org/active_record_encryption.html#rotating-keys) by adding the new key and keeping the old one, but it doesn't support rotating the deterministic key — and webhook endpoint secrets and gateway customer IDs are encrypted deterministically. Keep `ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY` and `ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT` unchanged unless you plan a migration that re-encrypts those records.
|
|
47
|
+
|
|
48
|
+
### Enabling encryption on an existing installation
|
|
49
|
+
|
|
50
|
+
Records written before the keys were set are stored in plain text. OAuth tokens on user identities stay readable and are encrypted on their next write. Webhook endpoint secrets and gateway customer IDs are not readable in plain text once encryption is on, so enable encryption with plaintext support first, then encrypt the existing rows:
|
|
51
|
+
|
|
52
|
+
1. Allow reading and looking up plaintext rows in `config/application.rb`:
|
|
53
|
+
|
|
54
|
+
```ruby
|
|
55
|
+
config.active_record.encryption.support_unencrypted_data = true
|
|
56
|
+
config.active_record.encryption.extend_queries = true
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
2. Set the three keys ([see above](#active-record-encryption)) and deploy.
|
|
60
|
+
3. Encrypt the existing rows from a Rails console (`spree console` or `bin/rails console`):
|
|
61
|
+
|
|
62
|
+
```ruby
|
|
63
|
+
[Spree::WebhookEndpoint, Spree::GatewayCustomer, Spree::UserIdentity].each { |model| model.find_each(&:encrypt) }
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
4. Remove the two settings from step 1 and deploy again.
|
|
67
|
+
|
|
68
|
+
Apps created from an older `spree-starter` also need `config/application.rb` to read the env vars — see the [5.6 to 6.0 upgrade guide](../upgrades/5.6-to-6.0.md#enable-active-record-encryption).
|
|
18
69
|
|
|
19
70
|
## URLs and Hosts
|
|
20
71
|
|
|
@@ -37,7 +37,7 @@ The `/jobs` dashboard uses HTTP Basic auth: user `jobs`, with a password the Blu
|
|
|
37
37
|
|
|
38
38
|
### Environment Variables
|
|
39
39
|
|
|
40
|
-
Render sets `DATABASE_URL
|
|
40
|
+
Render sets `DATABASE_URL`, `SECRET_KEY_BASE` and the three [Active Record encryption](environment_variables.md#active-record-encryption) keys automatically from the Blueprint. Copy the encryption keys from the **Environment** tab into your secret manager as a backup — never change them once data is encrypted. For additional configuration (SMTP, file storage, Sentry, etc.), see [Environment Variables](environment_variables.md).
|
|
41
41
|
|
|
42
42
|
Generated URLs (images and attachments in API responses, email links) automatically use Render's `RENDER_EXTERNAL_HOSTNAME` (`<your-app-name>.onrender.com`). When you attach a custom domain, set [`RAILS_HOST`](environment_variables.md#urls-and-hosts) to it — it takes precedence.
|
|
43
43
|
|
|
@@ -63,6 +63,7 @@ Spree API is built on **Ruby on Rails** which provides strong security defaults
|
|
|
63
63
|
We recommend:
|
|
64
64
|
|
|
65
65
|
- Keeping Spree and all dependencies up to date
|
|
66
|
+
- Configuring [Active Record encryption](../deployment/environment_variables.md#active-record-encryption) keys in production — without them, webhook signing secrets, payment gateway customer IDs and OAuth tokens are stored in plain text
|
|
66
67
|
- Following the [Rails Security Guide](https://guides.rubyonrails.org/security.html)
|
|
67
68
|
- Using [bundler-audit](https://github.com/rubysec/bundler-audit) to scan for known vulnerabilities in dependencies
|
|
68
69
|
- Running [brakeman](https://github.com/presidentbeef/brakeman) for static security analysis
|
|
@@ -178,6 +178,41 @@ bundle exec rake spree:upgrade:migrate_country_state_codes
|
|
|
178
178
|
|
|
179
179
|
Countries and states are no longer database records in 6.0. Addresses, delivery zone members, market countries, stock locations and stores now name them by ISO code (`country_code`, `state_code`), and this task fills those columns from the old `country_id` / `state_id` references. The old `country_iso` / `state_abbr` names still work on addresses for one release.
|
|
180
180
|
|
|
181
|
+
## Enable Active Record encryption
|
|
182
|
+
|
|
183
|
+
Spree encrypts webhook endpoint signing secrets, payment gateway customer IDs and the OAuth tokens on user identities with [Active Record encryption](https://guides.rubyonrails.org/active_record_encryption.html) — but only when encryption keys are configured. Without keys these values are stored in plain text. New 6.0 projects get keys at setup; upgraded applications need to add them.
|
|
184
|
+
|
|
185
|
+
**1. Make the app read the keys.** Projects created from `spree-starter` read them from the `ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY`, `ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY` and `ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT` env vars, falling back to the `active_record_encryption` entry in Rails credentials. If your `config/application.rb` predates this, add inside the `Application` class:
|
|
186
|
+
|
|
187
|
+
```ruby config/application.rb
|
|
188
|
+
%i[primary_key deterministic_key key_derivation_salt].each do |key|
|
|
189
|
+
value = ENV["ACTIVE_RECORD_ENCRYPTION_#{key.upcase}"].presence ||
|
|
190
|
+
credentials.dig(:active_record_encryption, key).presence
|
|
191
|
+
config.active_record.encryption[key] = value if value
|
|
192
|
+
end
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Setting the keys in `config.active_record.encryption` (rather than only in credentials) matters: Spree checks that configuration when it decides whether to encrypt webhook secrets and gateway customer IDs.
|
|
196
|
+
|
|
197
|
+
**2. Generate keys for development and production** — a separate set for each environment:
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
```bash Spree CLI (Docker)
|
|
201
|
+
spree encryption init # adds a set to your project's .env (never overwrites existing keys)
|
|
202
|
+
spree encryption init --print # prints a set for your production host
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
```bash Without Spree CLI
|
|
206
|
+
bin/rails db:encryption:init # prints a set; put it in env vars or encrypted credentials
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
Recreate the containers so they pick up the new `.env` (`spree update`, or `spree dev` for an ejected project — `spree restart` keeps the old environment). Set the keys on your production host **before** deploying, and store them in your secret manager.
|
|
211
|
+
|
|
212
|
+
> **WARNING:** Never change or lose the keys once data is encrypted — the encrypted records become unreadable.
|
|
213
|
+
|
|
214
|
+
**3. Encrypt existing rows.** Rows written before the keys were set are plain text. OAuth tokens on user identities stay readable and are encrypted on their next write. Webhook endpoint secrets and gateway customer IDs can't be read in plain text once encryption is on — follow [Enabling encryption on an existing installation](../deployment/environment_variables.md#enabling-encryption-on-an-existing-installation): turn on `support_unencrypted_data` and `extend_queries`, deploy with the keys, run `find_each(&:encrypt)` over `Spree::WebhookEndpoint`, `Spree::GatewayCustomer` and `Spree::UserIdentity`, then turn the two settings off again.
|
|
215
|
+
|
|
181
216
|
## The Cart/Order split
|
|
182
217
|
|
|
183
218
|
The single biggest change. What used to be one `Spree::Order` living through checkout and beyond is now two models:
|