Fixing Broken Image Uploads on CloudPanel (Nginx)

Broken image uploads on a CloudPanel subfolder staging site (for example domain.com/staging/) almost always come down to one thing: CloudPanel’s default Nginx configuration ships with WordPress Multisite rewrite rules that strip the /staging/ prefix from requests and look for your new images in the live site’s folder instead. The fix is a quick edit to two rewrite rules in your site’s Vhost, and it takes about two minutes.

Why are newly uploaded images broken on a CloudPanel staging site?

When you create a staging site in a subfolder, its URLs look like domain.com/staging/. CloudPanel ships a default Nginx configuration with rewrite rules meant for WordPress Multisite. Those rules intercept requests to the /staging/ folder, strip the prefix, and resolve the path against your live site’s directory. Newly uploaded images exist only in the staging folder, so Nginx can’t find them and returns a broken link or 404 — even though the upload itself succeeded.

The cause is purely in the Nginx rewrite rules. Nothing is wrong with WordPress, your media library, or the uploaded files.

How do I fix broken images on CloudPanel and Nginx?

Add an exclusion to your site’s Nginx configuration so the Multisite rewrite rules skip your staging folder. The whole change happens in the CloudPanel Vhost editor and takes about two minutes.

Step 1: Open your site’s Vhost editor

  1. Log into your CloudPanel dashboard.
  2. Click the website where uploads are breaking.
  3. Open the Vhost tab in the top menu.

Step 2: Replace the Multisite rewrite rules

Scroll to the static-files section. It begins with a line like:

location ~* ^.+.(css|js|jpg|jpeg|gif|png...)$

Inside that block, delete these two default rewrite lines:

  # WordPress Multisite Subdirectory
  rewrite ^/[_0-9a-zA-Z-]+(/wp-.*) $1 break;
  rewrite ^/[_0-9a-zA-Z-]+(/.*.php)$ $1 break;

Paste these updated lines in their place:

  # WordPress Multisite Subdirectory (Excluding WP Staging)
  rewrite ^/(?!staging)[_0-9a-zA-Z-]+(/wp-.*) $1 break;
  rewrite ^/(?!staging)[_0-9a-zA-Z-]+(/.*.php)$ $1 break;

The (?!staging) negative lookahead tells Nginx to apply the Multisite rewrite to every folder except staging, so requests for your staging images resolve correctly.

Step 3: Save and reload Nginx

Click the Save button at the bottom right. CloudPanel reloads Nginx automatically, and your newly uploaded staging images start working immediately.

What if my staging folder isn’t named "staging"?

If your staging site lives in a folder with a different name — dev, test, or anything else — change the word staging in both rewrite lines to match your actual folder name. The rest of the rule stays the same.

Will this fix get overwritten?

Yes, if you click the Reset to Default button in the Vhost tab. That button restores CloudPanel’s stock configuration and removes the exclusion, so you would need to re-apply these two lines afterward. Normal CloudPanel and WordPress updates do not touch your saved Vhost.

Frequently asked questions

Does this change affect my live site?

No. The (?!staging) exclusion only changes how Nginx routes requests under the staging subfolder. Requests to your live site still match the original Multisite rule, unchanged.

Why do only newly uploaded images break, not older ones?

The default rules send staging requests to your live folder. Images you upload after creating the staging site exist only in the staging uploads folder, so Nginx can’t find them there and returns a 404.

I use Apache, not Nginx. Does this apply?

No. CloudPanel serves sites with Nginx, so this fix is Nginx-specific. The rewrite syntax shown here does not work in an Apache .htaccess file.

Do I need to restart anything after saving?

No. CloudPanel reloads Nginx for you when you click Save. The fix is live as soon as the reload finishes.

Related articles

Updated on June 8, 2026

Alaa Salama

Author: Alaa Salama

I have spent more than a decade in the support field because I truly enjoy the human side of technology. Whether I’m solving a complex WordPress issue or developing custom plugins and code snippets to streamline workflows, my goal is always to reduce friction and help people work smarter. For me, there is nothing more rewarding than seeing a solution I’ve built make someone else’s day better.

When I’m offline, I’m usually still "under the hood" of something. I’m passionate about server optimization and DIY electronics, often spending my free time on smart home projects and hardware repairs. I especially value the time spent in my home workshop with my children; together, we tackle everything from household fixes to creative projects, fostering a love for building things that last.