WordPress Rename Image URL For a CDN Usage

by on November 20, 2010 · 24 comments· LAST UPDATED November 21, 2010

in , ,

Recently, we moved all our static assets to a CDN (Content Delivery Network) as described here. However, we have over 8000+ old blog posts and we need to point static images url to our CDN account hosted at http://MyACCOUNT.cloudfront.net/images/ folder. How do I rename all image urls stored in wordpress posts? How do I offload static images to a CDN urls under WordPress?

You need to use php function called preg_replace() to perform a regular expression search and replace. Find 'UNIX' and replace with 'Linux' from the subject as follows:

 
<?php
 echo preg_replace("/UNIX/", "Linux", "Use UNIX or die!" ) . "\n";
?>
 

Sample output:

Use Linux or die!

In this example find url:
www.cyberciti.biz/blog/uploads/2010/11/file.png
And replace as follows:
cdn.cyberciti.biz/blog/uploads/2010/11/file.png
Sample php code that can be used to replace any url in post using regex:

 
<?php
 $pattern="/www.cyberciti.biz\/blog\/uploads\/(.*)\/(.*)\/(.*).png/";
 $replacement="cdn.cyberciti.biz/blog/uploads/$1/$2/$3.png";
 $imagepath="cdn.cyberciti.biz/blog/uploads/2010/11/file.png";
 echo preg_replace($pattern, $replacement, $imagepath ) . "\n";
?>
 

You can now roll out your own php code to find and replace all image urls. However, there is another easy way - WP RegEx Replace plugin. This plugin will replace regular expressions in the final rendered WordPress output. First, download and install WP RegEx Replace plugin. Upload wp-regex-replace.php to the $blog/wp-content/plugins/wp-regex-replace/ directory:
$ ssh user@www45.nixcraft.net.in mkdir -p /var/www/html/blog/wp-content/plugins/wp-regex-replace/
$ scp wp-regex-replace.php user@www45.nixcraft.net.in:/var/www/html/blog/wp-content/plugins/wp-regex-replace/

Activate the plugin through the 'Plugins' menu in WordPress.

Backup Your Data

It cannot be stressed enough how important it is to make a backup of your blog and mysql database before you do this. See how to backup MySQL database here. You can use MySQL command as follows to backup database (you need ssh access):
$ mysqldump --add-drop-table -h mysql02.lan.nixcraft.net.in -u nixcraft -p'MySecretPassword' blogdb-name | bzip2 -c > blog.sql.bz2
You can also backup your files using the following command:
$ tar -zcvf /backup/blogfiles.tar.gz /var/www/html/blog/

How Do I Use This Plugin?

Make sure you upload all your current images to the CDN network using ftp / sftp / rsync client. Another recommends option is to use "Origin Pull CDN" method. Finally, make sure you can view ALL your images from the CDN network.

WARNING! These examples may result into corrupted database if NOT executed with care. It is strongly recommended that you backup your database before using your own php code or the following plugin.

Next, visit example.com/wp-admin/ > 'Settings' menu > 'WP RegEx Replace' plugin option. To replace all png files, enter the following regex in replace box:
http://www.example.com/images/(.*)/(.*)/(.*).png
with:
http://MyACCOUNT.cloudfront.net/images/$1/$2/$3.png
To replace all jpg images, enter:
Replace:
http://www.example.com/images/(.*)/(.*)/(.*).jpg
with:
http://MyACCOUNT.cloudfront.net/images/$1/$2/$3.jpg
To replace all gif images, enter:
Replace:
http://www.example.com/images/(.*)/(.*)/(.*).gif
with:
http://MyACCOUNT.cloudfront.net/images/$1/$2/$3.gif

Fig.01: Changing Image URL's path after wordpress move or CDN offloading

Fig.01: Changing Image URL's path after wordpress move or CDN offloading


Make sure you are using correct path. Finally, hit 'update' button. If you are using any caching plugin (such as wp-cache or supercache) just clean the cache. Visit any post with attached images and all your static images should come from CDN urls.

Redirecting Old Image URLs (HTTP 301 Moved Permanently)

The HTTP response status code 301 Moved Permanently is used for permanent redirection.

nginx HTTP 301 Moved Permanently Configuration

If you are using an Nginx web server, edit nginx.conf and append the following config code:

 
### redirect media / images to CDN url ###
rewrite "^/images/(.*)/(.*)/(.*).png$" http://MyACCOUNT.cloudfront.net/images/$1/$2/$3.png permanent;
rewrite "^/images/(.*)/(.*)/(.*).jpg$" http://MyACCOUNT.cloudfront.net/images/$1/$2/$3.jpg permanent;
rewrite "^/images/(.*)/(.*)/(.*).gif$" http://MyACCOUNT.cloudfront.net/images/$1/$2/$3.gif permanent;
 

Reload your nginx web server, enter:
# /usr/local/nginx/sbin/nginx -s reload

Lighttpd HTTP 301 Moved Permanently Configuration

If you are using a Lighttpd web server, edit lighttpd.conf and append the following config code:

 
### redirect media / images to CDN url ###
"^/images/(.*)/(.*)/(.*).png$" => "http://MyACCOUNT.cloudfront.net/images/$1/$2/$3.png",
"^/images/(.*)/(.*)/(.*).jpg$" => "http://MyACCOUNT.cloudfront.net/images/$1/$2/$3.jpg",
"^/images/(.*)/(.*)/(.*).gif$" => "http://MyACCOUNT.cloudfront.net/images/$1/$2/$3.gif"
 

Reload your lighttpd web server, enter:
# service lighttpd reload

Apache HTTP 301 Moved Permanently Configuration

If you are using an Apache web serer, edit httpd.conf and append the following config code:

 
### redirect media / images to CDN url ###
RewriteEngine on
RewriteRule   ^/images/(.*)/(.*)/(.*).(png|jpg|gif)$  http://MyACCOUNT.cloudfront.net/images/$1/$2/$3.$4 [R=301,L]
 

Reload your Apache web server, enter:
# service httpd restart

Help: I've Made a Mistake. Now What?

You need to restore your database from backup and start again.

TwitterFacebookGoogle+PDF versionFound an error/typo on this page? Help us!

{ 24 comments… read them below or add one }

1 Willie Jackson November 20, 2010 at 9:31 pm

Out of curiosity, why do you handle this manually instead of with a plugin like W3 Total Cache (which supports Cloudfront integration and automatic URL rewriting)?

Reply

2 nixCraft November 20, 2010 at 10:01 pm

Because I can ;)

Why use plugin? There is no need to use plugin at all. A plugin may introduce a new set of security problems and it can slow down wp rendering for sure. Further plugin recommends:

chmod 777 /var/www/vhosts/domain.com/httpdocs/wp-content/

A bad advice, IMHO. Now all you need is one sql injection problem and anyone can upload a .php file in httpdocs/wp-content/ to root your server. Also, what *if* plugin author stopped updating plugin (I’ve been using WP since 2005 and many author stopped updating plugins)? My method is permanent and it does not depends upon plugin overload. I just checked speed using tools.pingdom.com (these urls listed on plugin page) :
+ smashingmagazine.com – 29.6 seconds (1566.5 KB)
+ pearsonified.com – 4.5 seconds (231.5 KB)
+ mashable.com – 2.9 seconds (1123.4 KB)
+ tutsplus.com – 2.5 seconds (316.5 KB)
+ cyberciti.biz – 2 seconds (519.9 KB)

I’m not saying plugin is a bad idea; but it is not for geeks and people who knows how to use the UNIX / Linux *cough* *cough* operating system! Also, this howto is not for everyone; just like W3 Total Cache. YMMV!

HTH

Reply

3 Frederick Townes November 21, 2010 at 12:23 pm

I think the points about W3TC are completely spoken out of turn. The plugin asks for permission changes because of the possible permutations of user:groups that exist and *temporary* permissions change is the easiest way to create the files needed to cache files. The plugin provides a warning if you do not reset the permissions back after installation.

Anyway, even if you don’t like W3TC or plugins in general, this issue is solved elegantly by W3TC which will properly import attachments into the media library where they belong. It will also create the directives you need to create the 301 redirects if you select the option. After this task you could deactivate the plugin if you wanted, but again this problem was solved over a year ago and in a WordPress “native” manner.

Furthermore, some of the techniques in this post show a severe lack of understanding in web performance. Just because something *can* be done, doesn’t mean that it should be:

1. Redirecting user agents to another URL using PHP doesn’t scale and is the poorest performing method to redirect traffic as PHP is one of the slowest components of the stack. W3 Total Cache doesn’t encourage this behavior.

2. Encouraging readers to use cdn.domain.com is also not good advice as inevitably that subdomain will not be cookieless. W3 Total Cache supports all possible permutations of CDN implementation.

3. Most importantly, you’re not showing users how to set any headers on their objects to promote caching on the part of the user agent. W3 Total Cache allows you to control the policies you apply to various media. And soon will support AWS’ new custom origin functionality as well.

Reply

4 nixCraft November 21, 2010 at 7:16 pm

> Furthermore, some of the techniques in this post show a severe lack of understanding in web performance.
Really? Than why this site is a bit faster as compare all sites running W3 cache plugin?

1. I’m not following you on this one. The redirect 301 is only for search engine or people hot-linking images. It is done at web server level.

2. Agreed, you can use examplecdn.net, instead of cdn.example.com and skip the cookies issue.

3. It is covered in our previous article which explains how to setup headers on their object to promote caching and expiry of objects. See here

Look, I’m not saying your W3 cache plugin is a bad thingy; but it is not perfect either. There are always multiple ways to solve any problem. Personally, I do not like installing plugins for simple tasks such as cdn mapping. Again, YMMV.

Reply

5 Frederick Townes November 21, 2010 at 7:35 pm

If you want to test a fully configured W3TC using webpagetest.org or similar, then i think it’s safe to say that YMMV if you actually achieved better results with your manual techniques. The only reason why I posted here is because there are misconceptions about W3TC in your comment.

The fact is that if it were trivial to optimize web performance then google wouldn’t have entered the foray and plugins like mine wouldn’t be sought after, for that reason, I built it since to-date the problem has not been addressed in a way that a user can “easily” deploy.

Reply

6 nixCraft November 21, 2010 at 7:50 pm

Yes, I tested with webpagetest.org too as both domains have 3 or more ads units :
+ mashable.com (Page Speed Score: 76/100) – first time load 23.440s http://www.webpagetest.org/result/101121_DAA3/
+ cyberciti.biz (Page Speed Score: 91/100) – first time load 10.063s http://www.webpagetest.org/result/101121_DAA4/

I get similar results with YSLOW.

So yes manual method can always give you better results without adding overload of plugin. There are limitation with plugin as it can not make certain system changes such as always serving cached html and images from RAM only by mounting cache directory from RAMFS. There are few other tricks too which plugin cannot do as it requires root level access to server. But, I agree plugin is an easy way to speed up stuff without touching shell prompt. If you know how to get around UNIX prompt, go for manual method; otherwise normal users can use W3TC.

BTW, this blog / site is for UNIX sys admins with security in mind and not for new users. So most our posts talk about getting your hands dirty at the shell prompt.

Reply

7 Frederick Townes November 21, 2010 at 8:04 pm

Is there a reason why you ran those test from Sydney? Anyway, I don’t think you understood my point. I was talking about THIS site and a fully configured W3TC to compare apples to apples. Returning objects from memory is not always faster. I’m not sure why you think that’s the case. The fastest I/O is realized when the kernel itself determines what objects are in memory when it handles requests and do that a static file must be written to the disk and returned by the web server, not PHP. Also FYI, returning different files to search engines and end users is not recommended, Google considers that to be cloaking and questionable in general.

Regardless, if W3TC didn’t generate the various Apache/Nginx configurations for you, you still wouldn’t have an optimized application without it. Nor do your suggestions actually help WordPress users use it as it was intended.

Reply

8 Frederick Townes November 21, 2010 at 8:19 pm

Also, for those interested. Properly configured W3TC (no CDN) with a default WP install: http://www.webpagetest.org/result/101121_DAD5/ using nginx on a vps.net server with 3 nodes can do ~2500 req/sec (# ab -t 10 -c 10 -T ‘Accept-Encoding: gzip’ http://vpsnet2.w3-edge.com/) with a primed cache locally YMMV over the WAN.

Reply

9 nixCraft November 21, 2010 at 8:50 pm

Not useful. In real life you need ad tags coming form 2 or more ad vendors, 3rd party widgets (facebook, twitter) and much more. I can create minimum home page like site that loads in 0.2 or 0.3 seconds without any widgets, cdn, or 3rd party apps. So lets be realistic here; you need a fancy website with all javascript and widgets :)

Reply

10 Frederick Townes November 21, 2010 at 8:59 pm

I would say the same thing to you after hearing you compare your site to site’s like mashable or smashing magazine. It seems like you don’t like the way I make my points.

Reply

11 nixCraft November 21, 2010 at 8:45 pm

> FYI, returning different files to search engines and end users is not recommended, Google considers that to be cloaking and questionable in general.
I never said different files for search engine and end users. See, old file was at example.com/images/foo.jpg. Now it is moved examplecdn.com/images/foo.jpg. But when search engine and other visitors come for old image url example.com/images/foo.jpg; you want to notify them that image is moved to a cdn, a faster and better location at examplecdn.com/images/foo.jpg. Both user and Google getting the same thing. This is not cloaking, IMHO. Got it? The config option does the same thing.

I just selected Sydney as it is close to my current location and both domains are hosted in US. But it will give *same* result if I choose any other location.

The slowest part of any server is the hard disk; so yes anything that is come directly from RAMFS going to be faster. Benchmark for yourself and compare the results. I already did the same thing and hence this site is faster :) You will find that RAMFS is way faster than your hard disk. But, I agree comparing this site with any other domain is not fair game; as most other site owners are not expert sys admin to optimize their site at server level with all tricks.

>Nor do your suggestions actually help WordPress users use it as it was intended.
Read the question again. User (all question in /faq/ are submitted by our readers and I write the answers) just wanted to find out how to rename old image urls stored in WP post. This FAQ answers the same thing. This FAQ is not about setting up a CDN for WP. The other commenter brought the W3TC in the comments.

FYI, I benchmarked with both W3TC and manual method (not just for this domain but for my clients domain too). And I found that manual method gives a better result at the end of the day, period.

My argument is simple you don’t need W3TC or 3rd party plugin overload; you can do the same thing to get speed. As I said earlier, there are various ways to solve the same problem; one is W3TC for new users and other is manual method (which gives me better speed and security but it requires UNIX expertise).

Reply

12 Frederick Townes November 21, 2010 at 9:07 pm

I don’t think you understand how W3TC works, nor the kernel (nor my points). Do a test comparing returning a favicon from ramdisk vs from kernel and see which is faster. Do you realize that W3TC reduces execution time of WP then creates the cache files that allow the web server to scale? It doesn’t seem like you do. It’s not possible to do both without installing more software on the server, so I’d expect to hear about varnish or nginx as reverse proxies rather than these “tips”.

In reality, there is only one complete solution, everything else is either circumstantial or deliberately complete. If you give one-off tips, you should share the caveats. And what elements you’re deliberately compromising or addressing. I get hundreds of questions every week based on posts like this, so I was trying to reduce my workload. :)

As you saw from my webpagetest.org link for nginx config’ – stock WP with W3TC is “perfect” add a CDN to get all A’s. If you want to work forward from there and change the theme that’s up to the user, but the point was to show you that what you’re talking about is just more steps and compromises to a plugin that indeed does completely optimize WP and help move incomplete installations into native ones. I tried some of your techniques while researching over the years and building W3TC and in the lab they just aren’t the answer.

I’m not here because I don’t think that hand-made tips win. I’m here because applications should be optimized from the inside out, not outside in.

Reply

13 nixCraft November 21, 2010 at 9:24 pm

Frederick,

Yes, I know how wp, kernel, caching, swapping and W3TC works. Both method try to cache as much as possible without hitting DB and WP engine itself. Nor I started with W3TC in first place here.

How long have you been reading our site (i guess you just came here when somebody mentioned your pet project)? We have covered nginx/keepalived installation, reverse proxy, memcahced for WP, security and almost all other optimization / security issues here.

I get it, W3TC can automate lots of these stuff and so manual method too. My point is simple you don’t need any plugin overload for CDN or WP optimization (may be a few like memcache drop in and others required).

This discussion is not going anywhere, so I will not respond it further. If you’ve any other comments / suggestion please e-mail me directly at vivek@nixcraft.com and we will continue our discussion…

Reply

14 Frederick Townes November 21, 2010 at 9:59 pm

I found your site useful in the past actually as it turns up in google results. But I don’t read everything you post. Anyway, I’d encourage you to link you your other posts when you provide tips it will actually make your site more useful and grow your traffic.

Reply

15 Phoenix January 17, 2012 at 1:37 am

Frederick. After having tried many caching plugins, I think W3TC is the best fall back, as I can use it in a real world scenario with a site that has sessions etc. HyperCache, WPSuper etc just cache the entire page which is horrible.

BUT, the w3tc plugin does not work with wp-regex-replace. I need this functionality. My CDN is just a CNAME with origin pull, so I don’t need to manually upload any files anywhere. Just need to replace:

http://mysite.com/wp/wp-content/w3tc/min/ ==> http://static.mysite.com

But the regexp replacement has to be done just BEFORE w3tc takes over the generated output and caches it. Any way how to do it?

Thanks!

Reply

16 Frederick Townes January 31, 2012 at 10:11 am

In this particular case, it’s best to use your CDN in origin pull mode because W3TC must be the last plugin run in order to support that functionality as you explain it there.

Reply

17 Tom Jocky August 16, 2013 at 6:09 pm

I completely agree with Frederick, the method you posted above uses php for rewriting url or replacing them. This won’t be as efficient as method used by W3TC . Sure this website owner is better Sysadmin, but you can’t optimize everything on server.

Reply

18 Vamsi November 27, 2010 at 12:17 pm

Awesome post Vivek .

+ for “Use UNIX or die! ”

I am using the W3 Total Cache plugin + maxcdn .. its pretty good..but I also believe that doing things manually is better than relying on a plugin . so I will try this method and see the difference ..

Reply

19 AServ December 6, 2010 at 7:06 am

The SQL Replace way could be better, and only one time shot.
UPDATE wp_posts SET post_content = REPLACE('post_content', '%www.nixcraft.com/uploads/%', '%cdn.nixcraft.com/uploads/%');
NB: Not exactly sure about this syntax but should work.

Reply

20 Kumar December 8, 2010 at 3:29 pm

use plugins and die .
stop promoting your plugin here !

Reply

21 Dario March 10, 2011 at 6:55 pm

If you have many urls to replace you might also export wp-posts table and do a replace with something like notepad++, save and import back.

Reply

22 √únsal Korkmaz December 6, 2011 at 11:26 pm

why dont you guys use this:

define( ‘WP_CONTENT_URL’, ‘http://cdn.domain.com/wp-content’);
define( ‘WPMU_PLUGIN_URL’, ‘http://cdn.domain.com/wp-content/plugins’);

Reply

23 Phoenix January 17, 2012 at 5:38 am

Unsal, this is a good recommendation.

But is that URL just what plugins will use? So my actual physical URL does not have to be like that? (In reality, I can have the usual domain.com/wp/wp-content/…) ?

Thanks!

Reply

24 Sandra February 10, 2012 at 5:15 am

there are some bug with Gengo + Post ataavr both last version. Can you help me ?

Reply

Leave a Comment

Tagged as: , , , , , , , , , , , , , , , , , , , , , , ,

Previous Faq:

Next Faq: