Skip to content

Commit 16d3441

Browse files
authored
Add middleware customization guide for Strapi Cloud production environment (#3148)
* Add middleware customization guide for Strapi Cloud production environment Closes #8943 and #8944: document that config/middlewares.ts is overwritten on Cloud deploys and that customizations must go in config/env/production/middlewares.ts. Covers CSP and CORS use cases with JS/TS examples following the docs style guide. * Address review feedback on middleware guide - Add :::prerequisites block to middlewares.md for consistency with sibling pages - Add See also section linking to /cms/configurations/middlewares reference - Update upload.md Security Middleware section with :::caution pointing to config/env/production/middlewares.ts and cross-linking the new guide * Apply inline review feedback from derrickmehaffy - Tldr and path block now show both .ts and .js extensions - Add upgradeInsecureRequests: null to CSP directives (JS and TS) - CORS examples use factory function with env() helper instead of process.env - Rewrite caution block to explicitly state the production array fully replaces the global one and list all required middlewares - Remove v4 EOL mention * Fix code block titles in upload.md Security Middleware section Update file path titles from ./config/middleware.js to ./config/env/production/middlewares.js (and .ts) to match the correct Cloud override path documented in the new middlewares guide. * Apply structural simplification per reviewer feedback - Remove ## Common use cases: upgrade CSP and CORS sections to H2 - Remove ## Important notes H2: move caution after file path block - Merge two :::note blocks into one with 2 bullet points - Remove ## Related resources: add Middlewares config link to intro paragraph - Fix Tabs: add default to all JS TabItems, quote code block titles - Remove v4 version requirement from prerequisites
1 parent 1cf92ec commit 16d3441

3 files changed

Lines changed: 259 additions & 5 deletions

File tree

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
---
2+
title: Middleware Configuration for Strapi Cloud
3+
displayed_sidebar: cloudSidebar
4+
description: Configure custom middlewares for your Strapi Cloud production environment.
5+
canonicalUrl: https://docs.strapi.io/cloud/advanced/middlewares.html
6+
tags:
7+
- configuration
8+
- middlewares
9+
- CORS
10+
- Content Security Policy
11+
- CSP
12+
- production
13+
- Strapi Cloud
14+
- Strapi Cloud configuration
15+
- Strapi Cloud project
16+
---
17+
18+
# Middleware Configuration for Strapi Cloud
19+
20+
<Tldr>
21+
On Strapi Cloud, middleware customizations must go in `config/env/production/middlewares`. Changes to the global config file are overwritten on deploy.
22+
</Tldr>
23+
24+
:::prerequisites
25+
26+
- A local Strapi project.
27+
- A Strapi Cloud project (see [Getting Started](/cloud/getting-started/deployment)).
28+
29+
:::
30+
31+
On Strapi Cloud, `NODE_ENV` is always set to `production`. The platform applies its own production-level middleware configuration on deploy. Any changes to the global `config/middlewares` file are overwritten and will not take effect. For available middleware options, see [Middlewares configuration](/cms/configurations/middlewares).
32+
33+
To apply custom middleware configuration on Strapi Cloud, place your changes in:
34+
35+
<Tabs groupId="js-ts">
36+
<TabItem value="js" label="JavaScript" default>
37+
38+
```
39+
config/env/production/middlewares.js
40+
```
41+
42+
</TabItem>
43+
<TabItem value="ts" label="TypeScript">
44+
45+
```
46+
config/env/production/middlewares.ts
47+
```
48+
49+
</TabItem>
50+
</Tabs>
51+
52+
:::caution
53+
The `config/env/production/middlewares` file **fully replaces** the global middleware array. Your file must include the complete list:
54+
55+
- `strapi::errors`
56+
- `strapi::security`
57+
- `strapi::cors`
58+
- `strapi::poweredBy`
59+
- `strapi::logger`
60+
- `strapi::query`
61+
- `strapi::body`
62+
- `strapi::session`
63+
- `strapi::favicon`
64+
- `strapi::public`
65+
66+
Both CSP and CORS customizations can be combined in the same file.
67+
:::
68+
69+
:::note
70+
- You can keep your existing `config/middlewares` file as-is as it will not cause conflicts. The production-specific file takes precedence on Strapi Cloud.
71+
- Upload size limits on Strapi Cloud are enforced at the infrastructure level (Cloudflare gateway) and cannot be overridden via the `strapi::body` config. For external storage options, see [Upload Provider Configuration](/cloud/advanced/upload).
72+
:::
73+
74+
## Custom Content Security Policy (CSP)
75+
76+
If you use an external upload provider, allow its domain in the CSP directives. Without this, the Strapi Admin panel will block images and media from those sources.
77+
78+
Create or update `config/env/production/middlewares`:
79+
80+
<Tabs groupId="js-ts">
81+
<TabItem value="js" label="JavaScript" default>
82+
83+
```js title="config/env/production/middlewares.js"
84+
module.exports = [
85+
'strapi::errors',
86+
{
87+
name: 'strapi::security',
88+
config: {
89+
contentSecurityPolicy: {
90+
useDefaults: true,
91+
directives: {
92+
'connect-src': ["'self'", 'https:'],
93+
'img-src': [
94+
"'self'",
95+
'data:',
96+
'blob:',
97+
'market-assets.strapi.io',
98+
'your-custom-domain.com', // replace with your provider domain
99+
],
100+
'media-src': [
101+
"'self'",
102+
'data:',
103+
'blob:',
104+
'market-assets.strapi.io',
105+
'your-custom-domain.com', // replace with your provider domain
106+
],
107+
upgradeInsecureRequests: null,
108+
},
109+
},
110+
},
111+
},
112+
'strapi::cors',
113+
'strapi::poweredBy',
114+
'strapi::logger',
115+
'strapi::query',
116+
'strapi::body',
117+
'strapi::session',
118+
'strapi::favicon',
119+
'strapi::public',
120+
];
121+
```
122+
123+
</TabItem>
124+
<TabItem value="ts" label="TypeScript">
125+
126+
```ts title="config/env/production/middlewares.ts"
127+
export default [
128+
'strapi::errors',
129+
{
130+
name: 'strapi::security',
131+
config: {
132+
contentSecurityPolicy: {
133+
useDefaults: true,
134+
directives: {
135+
'connect-src': ["'self'", 'https:'],
136+
'img-src': [
137+
"'self'",
138+
'data:',
139+
'blob:',
140+
'market-assets.strapi.io',
141+
'your-custom-domain.com', // replace with your provider domain
142+
],
143+
'media-src': [
144+
"'self'",
145+
'data:',
146+
'blob:',
147+
'market-assets.strapi.io',
148+
'your-custom-domain.com', // replace with your provider domain
149+
],
150+
upgradeInsecureRequests: null,
151+
},
152+
},
153+
},
154+
},
155+
'strapi::cors',
156+
'strapi::poweredBy',
157+
'strapi::logger',
158+
'strapi::query',
159+
'strapi::body',
160+
'strapi::session',
161+
'strapi::favicon',
162+
'strapi::public',
163+
];
164+
```
165+
166+
</TabItem>
167+
</Tabs>
168+
169+
:::tip
170+
For a full list of upload providers and their required domains, see the <ExternalLink to="https://market.strapi.io/providers" text="Strapi Market"/>.
171+
:::
172+
173+
## Custom CORS headers
174+
175+
If your frontend sends custom request headers (e.g. for authorization flows), you need to explicitly allow them in the CORS configuration. Placing this in the global `config/middlewares` file will not work on Strapi Cloud. Place it in `config/env/production/middlewares` instead.
176+
177+
<Tabs groupId="js-ts">
178+
<TabItem value="js" label="JavaScript" default>
179+
180+
```js title="config/env/production/middlewares.js"
181+
module.exports = ({ env }) => [
182+
'strapi::errors',
183+
'strapi::security',
184+
{
185+
name: 'strapi::cors',
186+
config: {
187+
enabled: true,
188+
origin: [env('CLIENT_URL')],
189+
headers: [
190+
'Content-Type',
191+
'Authorization',
192+
'Origin',
193+
'Accept',
194+
'X-Requested-With',
195+
'your-custom-header', // add any custom headers your frontend sends
196+
],
197+
},
198+
},
199+
'strapi::poweredBy',
200+
'strapi::logger',
201+
'strapi::query',
202+
'strapi::body',
203+
'strapi::session',
204+
'strapi::favicon',
205+
'strapi::public',
206+
];
207+
```
208+
209+
</TabItem>
210+
<TabItem value="ts" label="TypeScript">
211+
212+
```ts title="config/env/production/middlewares.ts"
213+
export default ({ env }) => [
214+
'strapi::errors',
215+
'strapi::security',
216+
{
217+
name: 'strapi::cors',
218+
config: {
219+
enabled: true,
220+
origin: [env('CLIENT_URL')],
221+
headers: [
222+
'Content-Type',
223+
'Authorization',
224+
'Origin',
225+
'Accept',
226+
'X-Requested-With',
227+
'your-custom-header', // add any custom headers your frontend sends
228+
],
229+
},
230+
},
231+
'strapi::poweredBy',
232+
'strapi::logger',
233+
'strapi::query',
234+
'strapi::body',
235+
'strapi::session',
236+
'strapi::favicon',
237+
'strapi::public',
238+
];
239+
```
240+
241+
</TabItem>
242+
</Tabs>

docusaurus/docs/cloud/advanced/upload.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -237,9 +237,13 @@ export default ({ env }) => ({
237237

238238
Due to the default settings in the Strapi Security Middleware you will need to modify the `contentSecurityPolicy` settings to properly see thumbnail previews in the Media Library.
239239

240+
:::caution
241+
On Strapi Cloud, `NODE_ENV` is always set to `production`. Changes to the global `config/middlewares.ts` file are overwritten on each deploy and will not take effect. Place your Security Middleware customizations in `config/env/production/middlewares.ts` instead. See [Middleware Configuration for Strapi Cloud](/cloud/advanced/middlewares) for details.
242+
:::
243+
240244
To do this in your Strapi project:
241245

242-
1. Navigate to `./config/middlewares.js` or `./config/middlewares.ts` in your Strapi project.
246+
1. Navigate to `./config/env/production/middlewares.js` or `./config/env/production/middlewares.ts` in your Strapi project.
243247
2. Replace the default `strapi::security` string with the object provided by the upload provider.
244248

245249
**Example:**
@@ -248,7 +252,7 @@ To do this in your Strapi project:
248252
<Tabs groupId="upload-examples" >
249253
<TabItem value="cloudinary" label="Cloudinary">
250254

251-
```js title=./config/middleware.js
255+
```js title=./config/env/production/middlewares.js
252256
module.exports = [
253257
// ...
254258
{
@@ -284,7 +288,7 @@ module.exports = [
284288
</TabItem>
285289
<TabItem value="amazon-s3" label="Amazon S3">
286290

287-
```js title=./config/middleware.js
291+
```js title=./config/env/production/middlewares.js
288292
module.exports = [
289293
// ...
290294
{
@@ -324,7 +328,7 @@ module.exports = [
324328
<Tabs groupId="upload-examples" >
325329
<TabItem value="cloudinary" label="Cloudinary">
326330

327-
```ts title=./config/middleware.ts
331+
```ts title=./config/env/production/middlewares.ts
328332
export default [
329333
// ...
330334
{
@@ -360,7 +364,7 @@ export default [
360364
</TabItem>
361365
<TabItem value="amazon-s3" label="Amazon S3">
362366

363-
```ts title=./config/middleware.ts
367+
```ts title=./config/env/production/middlewares.ts
364368
export default [
365369
// ...
366370
{

docusaurus/sidebars.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,14 @@ const sidebars = {
745745
new: false,
746746
},
747747
},
748+
{
749+
type: 'doc',
750+
id: 'cloud/advanced/middlewares',
751+
label: 'Middleware configuration for Cloud',
752+
customProps: {
753+
new: false,
754+
},
755+
},
748756
],
749757
},
750758
],

0 commit comments

Comments
 (0)