✨ Strapi MCP is now Generally Available - let your agents manage your Strapi content ✨

EcosystemIntermediate5 min read

Fixing "Blocked request. This host is not allowed" in Strapi 5

September 8, 2026
Fixing "Blocked request. This host is not allowed" in Strapi 5

You start Strapi behind a domain (a staging subdomain, a Cloudflare tunnel, an ngrok URL, a Coolify or Dokploy deployment), open the admin panel, and get a blank page with this:

Blocked request. This host ("cms.example.com") is not allowed.
To allow this host, add "cms.example.com" to server.allowedHosts in vite.config.js.

The error message tells you exactly what to do and almost nothing about where to do it. There is no vite.config.js at the root of a Strapi project, which is where most people look first.

Why this happens

Strapi 5's admin panel is a React single-page application, and Vite is the default bundler that builds it. When you run strapi develop, Vite runs a dev server to serve the admin panel with hot module replacement.

Vite validates the Host header on every request to that dev server. This is a security control, not a bug: it protects developers against DNS-rebinding attacks, where a malicious page in your browser resolves an attacker-controlled domain to 127.0.0.1 and talks to your local dev server. Vite tightened this from Vite 5 onwards, which is why the error started appearing for people who had been running the same setup for months.

By default Vite allows localhost and loopback addresses. Any other hostname, including your own staging domain, gets rejected.

Check your version first. Strapi's own development Vite config now sets allowedHosts: true in the base config it builds before your overrides are applied (resolve-development-config, fixing #23491). On a current Strapi 5 release you should not hit this error at all. If you are seeing it, upgrading Strapi may be the whole fix, and a better one than the config below. The rest of this post applies to versions that predate that change, and to cases where you want an explicit allowlist rather than Strapi's permissive default.

The critical detail: this only affects strapi develop. In production you run strapi build followed by strapi start, which serves a static, pre-built admin bundle with no Vite dev server involved. If you are hitting this error on a public domain, that is a signal worth reading, and we come back to it at the end.

The fix

Create ./src/admin/vite.config.ts if it does not exist. Strapi looks for vite.config.js, .mjs, .ts, or .mts in ./src/admin/, and project templates ship an example file in that folder that merges a custom alias, which is a good starting point to replace:

import { mergeConfig, type UserConfig } from 'vite';

export default (config: UserConfig) => {
  // Important: always return the modified config
  return mergeConfig(config, {
    server: {
      allowedHosts: ['cms.example.com', '.preview.example.com'],
    },
  });
};

JavaScript projects use the same shape:

const { mergeConfig } = require('vite');

module.exports = (config) => {
  return mergeConfig(config, {
    server: {
      allowedHosts: ['cms.example.com', '.preview.example.com'],
    },
  });
};

Then restart strapi develop. Note that Strapi passes you the base config it built and expects you to return a modified copy. If you return a fresh object instead of the result of mergeConfig, you will drop Strapi's own Vite setup and the admin panel will fail to build.

A few rules for the values:

  • A string array is the recommended shape. ['cms.example.com'] allows exactly that host.
  • A leading dot allows all subdomains: .example.com matches cms.example.com and preview.example.com.
  • 'all' disables host checking entirely. Vite also accepts true for this, which is what most forum answers reach for.

About allowedHosts: true

It works, and it is the answer you will find copy-pasted everywhere. Understand what you are turning off: any website your browser visits can now make requests to your dev server, and your dev server has an authenticated admin session.

On a laptop on your own network, that risk is small. On a dev instance reachable from the public internet, it is not, and neither is running strapi develop there at all, which brings us back to the real question.

If you hit this on a deployed environment

Running strapi develop on a server that has a domain name is the underlying problem, not the host check. Development mode:

  • runs the Vite dev server and rebuilds the admin panel on every file change,
  • enables the Content-Type Builder, which writes schema.json files to disk that your deployment will overwrite on the next release,
  • is significantly slower and more memory-hungry than a production build.

If you need a Strapi instance that is always reachable at https://dev.example.com, deploy it the same way you deploy production:

NODE_ENV=production npm run build
NODE_ENV=production npm run start

Content-type changes then happen locally and travel through source control, which is how Strapi is designed to work.

Tunnels and rewritten ports

If you reach the admin panel through a tunnel that terminates TLS and rewrites ports (ngrok, Cloudflare Tunnel, a VS Code port forward), allowing the host may fix the initial load but leave hot reload broken. The HMR websocket still tries to connect to the internal port. The Strapi docs suggest pairing allowedHosts with Vite's hmr.clientPort:

import { mergeConfig, type UserConfig } from 'vite';

export default (config: UserConfig) => {
  return mergeConfig(config, {
    server: {
      allowedHosts: ['.ngrok-free.app'],
      hmr: {
        clientPort: 443,
      },
    },
  });
};

This one is contested, so test it before you commit to it. Recent Strapi versions deliberately bind HMR to Strapi's own http.Server so the websocket reuses the app's port, and the code comments say that adding a separate listener plus clientPort is what breaks setups behind a proxy that only exposes the Strapi port. The Strapi source asserts clientPort is undefined; the docs page still recommends setting it. If HMR works without clientPort on your version, leave it out.

Quick checklist

  1. File goes in ./src/admin/vite.config.ts, not the project root.
  2. Always return mergeConfig(config, { ... }).
  3. Prefer an explicit host list over true.
  4. Restart strapi develop. This file is not hot-reloaded.
  5. If the host is a real deployed domain, build and start in production mode instead.

Further reading

Theodore Kelechukwu OnyejiakuDevRel and Community | Software Developer | Technical Writer

Theodore is a Technical Writer and a full-stack software developer. He loves writing technical articles, building solutions, and sharing his expertise.

Running Strapi in production with PM2
EcosystemIntermediate·6 min read

Running Strapi in production with PM2

Keep Strapi running across crashes and reboots with PM2: server.js, ecosystem files, TypeScript projects, log rotation, and the cluster-mode caveat.

·September 9, 2026
Why your Strapi API returns 403 Forbidden (and how to fix it)
EcosystemBeginner·6 min read

Why your Strapi API returns 403 Forbidden (and how to fix it)

A 403 from the Strapi REST API means authorisation, not authentication. The Public role, API tokens, Draft & Publish, and the cases in between.

·September 9, 2026
Deploying Strapi behind an Nginx reverse proxy
EcosystemAdvanced·6 min read

Deploying Strapi behind an Nginx Reverse Proxy

Strapi does not terminate TLS. A complete Nginx configuration: virtual hosts, upstreams, websockets, upload limits, and the forwarded headers it needs.

·September 9, 2026