For my theme development purposes I have a local WordPress installation that I run from a VM, accessed via, let's say, http://local.app. I also have a remote version of the site on a staging server, http://staging.example.com.

The staging site contains all the content that I design the theme around (i.e posts, pages, WooCommerce products etc).

All of this is in the MySQL database on the server as well as media (images, files etc) in wp-content/uploads.

Now, via the useful guide on the Codex entitled "Two WordPresses, One Database" I have this mostly working, with a local copy of the theme, plugins and wordpress core on my vm, getting all its data from the remote staging server.

The only problem is that all media is getting 404 as for some reason all urls to the media files are linking to my local vm rather than the staging server. E.g. If I visit the media library and go to the "edit media" page, the "file url" reads as follows:

  • On the staging server: http://staging.example.com/wp-content/uploads/2015/04/greigh.jpg
  • On my local vm: http://local.app/wp-content/uploads/2015/04/greigh.jpg

When inspecting the database all attachment post types have guids with full urls, not relative. So how is WordPress building these urls, and is there a way to solve this without having to duplicate the entire media library onto my VM?

4 Answers 4


Somewhere in the core, URLs get absolutely pathed when put into the database.

Why don't you just load all your images from your staging server? Have the staging server hold the files while your local mirrors it. Add the following to your .htaccess to your local uploads folder and the contents are as follows:

# Attempt to load files from production if they're not in our local version
<IfModule mod_rewrite.c>
  RewriteEngine on
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} !-f
  # Replace http://example.com with your production site's domain name
  RewriteRule (.*) http://example.com/wp-content/uploads/$1

For latecomers, if your development environment is LEMP, for your nginx (default) site this would go in your main server declaration to redirect most image 404 errors:

  # Directives to send expires headers and turn off 404 error logging. Try images from production server
  location ~* \.(png|jpe?g|gif|ico)$ {
      expires 24h;
      log_not_found off;
      try_files $uri $uri/ @production;

  location @production {
      proxy_pass http://Production-or-StagingServerURL.com/$uri;

Add other resource extensions ie: svg, to the location 'array' to cover other types of 404 resource errors.

Or see this answer for another option: How to configure nginx to redirect requests to the uploads directory to the production server?


Of course, you’ll need to replace www.example.com with your own site address but putting this above the WordPress rules in your .htaccess file will mean that any file on the production site will be displayed on the dev site, no questions asked, no files downloaded.

RewriteEngine On
RewriteBase /
RewriteRule ^wp-content/uploads(.*)$ http://www.example.com/wp-content/uploads/$1 [L,R]

do a database search and replace where 'local.app' is changed to 'staging.example.com'

  • Can you explain how to do search and replace on DB.
    – bravokeyl
    Commented Nov 2, 2016 at 5:57
  • @bravokeyl easiest way os to export your database to an .sql file, then use a text editor to find and replace. Save and import the file to a database.
    – Steven
    Commented Feb 21, 2017 at 21:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.