Skip to content

Add middleware customization guide for Strapi Cloud production environment#3148

Draft
raulbalestra wants to merge 4 commits into
strapi:mainfrom
raulbalestra:cloud/add-middleware-customization-guide
Draft

Add middleware customization guide for Strapi Cloud production environment#3148
raulbalestra wants to merge 4 commits into
strapi:mainfrom
raulbalestra:cloud/add-middleware-customization-guide

Conversation

@raulbalestra
Copy link
Copy Markdown

@raulbalestra raulbalestra commented May 9, 2026

Description

Adds a new page cloud/advanced/middlewares documenting how to correctly configure custom middlewares on Strapi Cloud.

Why it's needed: On Strapi Cloud, NODE_ENV is always production and the platform injects its own middleware configuration at the production env level. This means changes made to the global config/middlewares.ts are silently overwritten on each deploy. Users must place their customizations in config/env/production/middlewares.ts instead, but this behavior is not currently documented anywhere.

What the page covers:

  • Explanation of why config/middlewares.ts changes don't apply on Cloud
  • How to use config/env/production/middlewares.ts as the correct override path
  • Common use case: custom CSP directives for external upload providers (Cloudflare R2, S3, etc.)
  • Common use case: custom CORS headers for frontend authorization flows
  • JavaScript and TypeScript examples for both cases
  • Notes on combining CSP + CORS in a single file, upload size limits, and Strapi v4/v5 compatibility

Also adds the new page to the Cloud sidebar under "Advanced configuration".

Related issue(s)/PR(s)

  • Closes #8943
  • Closes #8944

@strapi-cla
Copy link
Copy Markdown

strapi-cla commented May 9, 2026

CLA assistant check
All committers have signed the CLA.

@vercel
Copy link
Copy Markdown

vercel Bot commented May 9, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
documentation Ready Ready Preview, Comment May 11, 2026 9:47pm

Request Review

@derrickmehaffy derrickmehaffy added pr: new content PRs for new product features or new documentation sections size: medium If the PR includes 1+ file(s) with a total of 10 to 50 lines of text or <100 lines of code source: Strapi Cloud PRs/issues targeting the Strapi Cloud documentation v5 Documentation PR that targets Strapi v5 AI-assisted labels May 11, 2026
…nment

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.
Copy link
Copy Markdown
Member

@derrickmehaffy derrickmehaffy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Page is solid and the core explanation (NODE_ENV=production + injected prod config) is exactly right. A few changes before merge:

Not tied to a specific line:

  1. cloud/advanced/upload.md still instructs users to edit the global ./config/middlewares.js for the strapi::security block (see its "Configure the Security Middleware" section, lines ~236–399). Per this new page, that won't take effect on Cloud. Either update upload.md to use config/env/production/middlewares.ts, or at minimum add a cross-link from upload.md → this page. Without it the two docs contradict each other.
  2. No link to the standard middlewares reference (/cms/configurations/middlewares). Users will need the full options table for security, cors, etc. — add a pointer in the intro or a See also section.
  3. Sibling pages (upload.md, email.md) open with a :::prerequisites block. Consider adding one (e.g. Cloud project, local Strapi v4.8.2+) for consistency.

# Middleware Configuration for Strapi Cloud

<Tldr>
On Strapi Cloud, middleware customizations must go in `config/env/production/middlewares.ts` — changes to the global config file are overwritten on deploy.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tldr says .ts only, but the page documents both .js and .ts. Suggest: config/env/production/middlewares.{ts,js} (or .ts / .js).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
On Strapi Cloud, middleware customizations must go in `config/env/production/middlewares.ts` — changes to the global config file are overwritten on deploy.
On Strapi Cloud, middleware customizations must go in `config/env/production/middlewares`. Changes to the global config file are overwritten on deploy.

To apply custom middleware configuration on Strapi Cloud, place your changes in:

```
config/env/production/middlewares.ts
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same — show both extensions, otherwise JS users will assume the override only works for TS.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed @raulbalestra , we actually need the full Tabs system here.
Please see agents/templates/components/tabs.md on how to apply them.

Comment on lines +55 to +71
directives: {
'connect-src': ["'self'", 'https:'],
'img-src': [
"'self'",
'data:',
'blob:',
'market-assets.strapi.io',
'your-custom-domain.com', // replace with your provider domain
],
'media-src': [
"'self'",
'data:',
'blob:',
'market-assets.strapi.io',
'your-custom-domain.com', // replace with your provider domain
],
},
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing upgradeInsecureRequests: null inside directives. Both the canonical reference (cms/configurations/middlewares.md, AWS-S3 example) and the existing cloud/advanced/upload.md include it — omitting it breaks mixed-content loads for several providers. Apply to the TS block below as well.

Comment on lines +97 to +113
directives: {
'connect-src': ["'self'", 'https:'],
'img-src': [
"'self'",
'data:',
'blob:',
'market-assets.strapi.io',
'your-custom-domain.com', // replace with your provider domain
],
'media-src': [
"'self'",
'data:',
'blob:',
'market-assets.strapi.io',
'your-custom-domain.com', // replace with your provider domain
],
},
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as the JS block above — add upgradeInsecureRequests: null to the directives object.

name: 'strapi::cors',
config: {
enabled: true,
origin: [process.env.CLIENT_URL],
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rest of the docs use Strapi's env() helper rather than process.env directly. The middleware array doesn't take ({ env }) natively, so this works — but for consistency with every other example in the docs, prefer env('CLIENT_URL') via a factory function, or at minimum note that CLIENT_URL must be set in Cloud → Settings → Variables. Same applies to the TS block (line 182).

## Important notes

:::caution
Both CSP and CORS can be combined in a single `config/env/production/middlewares.ts` file. Make sure to include the full middleware array — partial configs may cause other middlewares to be dropped.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wording is vague — "partial configs may cause other middlewares to be dropped" undersells it. The production-env array fully replaces the global one, so the file must contain the complete middleware list (errors, security, cors, poweredBy, logger, query, body, session, favicon, public). Suggest stating that directly.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

^ What Derrick said
Plus, another instance of .ts suffix to remove. Please simply replace it with config/env/production/middleware

Upload size limits on Strapi Cloud are enforced at the infrastructure level (Cloudflare gateway) and cannot be overridden via the `strapi::body` config. See [Upload Provider Configuration](/cloud/advanced/upload) for guidance on using external providers to handle larger file sizes.
:::

This behavior applies to all Strapi Cloud plans and to both Strapi v4 and v5.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

v4 is EOL — referencing it here is unnecessary and may mislead users into thinking v4-specific guidance lives on this page. Drop the v4 mention.

- 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
- 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
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.
@raulbalestra
Copy link
Copy Markdown
Author

Hi @derrickmehaffy, all your feedback has been addressed:

Review comments:

Updated upload.md, added a :::caution block with a cross-link to this page, updated step 1, and fixed all 4 code block titles to point to config/env/production/middlewares.js|ts.
Added a ## See also section linking to /cms/configurations/middlewares.
Added a :::prerequisites block consistent with the sibling pages.
Inline comments:

Tldr and path block now show both .ts and .js.
Added upgradeInsecureRequests: null to the CSP directives in both JS and TS examples.
CORS examples now use a factory function with env('CLIENT_URL') instead of process.env.
Rewrote the caution block to state explicitly that the production file fully replaces the global array and listed all 10 required middlewares.
Removed the v4 mention.

```

:::note
You can keep your existing `config/middlewares.ts` file as-is — it will not cause conflicts. The production-specific file takes precedence on Strapi Cloud.
Copy link
Copy Markdown
Collaborator

@pwizla pwizla May 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
You can keep your existing `config/middlewares.ts` file as-is it will not cause conflicts. The production-specific file takes precedence on Strapi Cloud.
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.

Also @raulbalestra please ensure there are no em-dashes in content. AIs definitely overuse them. Feel free to pass your content through the Style Checker, or point your AI system to it; it should automatically flag them.

@pwizla
Copy link
Copy Markdown
Collaborator

pwizla commented May 13, 2026

I've just done a complete review, technical writing wise, @raulbalestra
Thank you very much, the page will be super valuable to users 🙏

What needs to be changed before I can merge it: Drastically simplify the page structure. As it is, it doesn't quite fit with the rest of the docs pages. Here are my recommendations:

  • Completely get rid of the See also section: We don't have such sections in any other docs pages. Upload provider configuration link is already mentioned in the note above. Middlewares configuration link can be given in the intro. paragraph, after the prerequisites block
  • "Important notes" shouldn't be a section. Just remove the h2, keep the caution and note content exactly as they are, but move them:
    • caution should be after the "To apply custom middleware configuration… " sentence in the intro
    • merge the note about upload size limits with the note in the intro: You'll get a unique :::note Notes admonition block, with 2 bullet points
  • Delete the "Common use cases" h2 and upgrade the 2 h3s it contains to h2s. That will reduce the page structure/"on this page" navigation to the following simple structure: ## Custom Content Security Policy (CSP), ## Custom CORS headers

Hope everything is clear. I can make the changes for you if it's easier.

Copy link
Copy Markdown
Collaborator

@pwizla pwizla left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please apply all the structural changes I mentioned and your PR will be ready to merge 🚀 Thank you, Raul!

@pwizla pwizla self-assigned this May 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI-assisted pr: new content PRs for new product features or new documentation sections size: medium If the PR includes 1+ file(s) with a total of 10 to 50 lines of text or <100 lines of code source: Strapi Cloud PRs/issues targeting the Strapi Cloud documentation v5 Documentation PR that targets Strapi v5

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants