Middleware Configuration for Strapi Cloud
Page summary:
On Strapi Cloud, middleware customizations must go in
config/env/production/middlewares.ts(or.js) — changes to the global config file are overwritten on deploy.
- A local Strapi project running on
v4.8.2+. - A Strapi Cloud project (see Getting Started).
On Strapi Cloud, NODE_ENV is always set to production. The platform injects its own middleware configuration at the production environment level, which means any customizations placed in the global config/middlewares.ts (or .js) file will be overwritten after deploy and will not take effect.
To apply custom middleware configuration on Strapi Cloud, place your changes in:
config/env/production/middlewares.ts
or .js if your project uses JavaScript.
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.
Common use cases
Custom Content Security Policy (CSP)
If you use an external upload provider (such as Cloudflare R2, AWS S3, or any custom domain), you need to allow those domains in the CSP directives. Without this, the Strapi Admin panel will block images and media from those sources.
Create or update config/env/production/middlewares.ts:
- JavaScript
- TypeScript
module.exports = [
'strapi::errors',
{
name: 'strapi::security',
config: {
contentSecurityPolicy: {
useDefaults: true,
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
],
upgradeInsecureRequests: null,
},
},
},
},
'strapi::cors',
'strapi::poweredBy',
'strapi::logger',
'strapi::query',
'strapi::body',
'strapi::session',
'strapi::favicon',
'strapi::public',
];
export default [
'strapi::errors',
{
name: 'strapi::security',
config: {
contentSecurityPolicy: {
useDefaults: true,
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
],
upgradeInsecureRequests: null,
},
},
},
},
'strapi::cors',
'strapi::poweredBy',
'strapi::logger',
'strapi::query',
'strapi::body',
'strapi::session',
'strapi::favicon',
'strapi::public',
];
For a full list of upload providers and their required domains, see the Strapi Market.
Custom CORS headers
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.ts will not work on Strapi Cloud — it must be in config/env/production/middlewares.ts.
- JavaScript
- TypeScript
module.exports = ({ env }) => [
'strapi::errors',
'strapi::security',
{
name: 'strapi::cors',
config: {
enabled: true,
origin: [env('CLIENT_URL')],
headers: [
'Content-Type',
'Authorization',
'Origin',
'Accept',
'X-Requested-With',
'your-custom-header', // add any custom headers your frontend sends
],
},
},
'strapi::poweredBy',
'strapi::logger',
'strapi::query',
'strapi::body',
'strapi::session',
'strapi::favicon',
'strapi::public',
];
export default ({ env }) => [
'strapi::errors',
'strapi::security',
{
name: 'strapi::cors',
config: {
enabled: true,
origin: [env('CLIENT_URL')],
headers: [
'Content-Type',
'Authorization',
'Origin',
'Accept',
'X-Requested-With',
'your-custom-header', // add any custom headers your frontend sends
],
},
},
'strapi::poweredBy',
'strapi::logger',
'strapi::query',
'strapi::body',
'strapi::session',
'strapi::favicon',
'strapi::public',
];
Important notes
The config/env/production/middlewares.ts (or .js) file fully replaces the global middleware array — it is not merged. Your file must always include the complete middleware list: strapi::errors, strapi::security, strapi::cors, strapi::poweredBy, strapi::logger, strapi::query, strapi::body, strapi::session, strapi::favicon, and strapi::public. Both CSP and CORS customizations can be combined in the same file.
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 for guidance on using external providers to handle larger file sizes.
This behavior applies to all Strapi Cloud plans.
See also
- Middlewares configuration — full reference for all available middleware options, including
strapi::securityandstrapi::corsparameters. - Upload Provider Configuration for Strapi Cloud — configure an external upload provider and the associated CSP settings.