Configure subdomain as “CDN” in NGINX (+ WordPress & W3 Total Cache configuration)

UPDATE: CORS (Cross-origin resource sharing) added to the “fake” CDN. Based on: https://gist.github.com/alexjs/4165271

In a typical scenario, you serve your webpage from single domain, that includes all yours “server generated” pages and also the images and assets (javascript, css and other files) of your site.

This can slow down your page speed. Most of the browsers create maximum two/four simultaneous connections when downloading a page from the web server, so others connections have to wait. There is also another problem, your domain could serve some cookies with your assets, which can decrease also the page performance.

The best solution for this problem is to invest in a real CDN (Content Delivery Network). CDNs are optimized to serve images and assets (without cookies), they have his own domains, release the load of your server and they are distributed in multiple data centers (so your users are going to download the assets faster because they are near them).

The problem: CDNs cost you money.

If you can afford it, go and take one (your page will load faster). If not, you can have some of the benefits of having a CDN, configuring a subdomain to serve this content. This is not a real CDN because it’s not a “Network” (Data is not distributed in multiple data centers) and your server have to load and serve the assets, but you can benefit of more simultaneous connections and get rid of the cookies. You can see an example in this page 🙂

As I’m using NGINX as web server, I’m going to show you how to configure in it a “fake cdn” subdomain.

First you have to create a new subdomain/server configuration in “/etc/nginx/sites-available” with this content:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
server {
    listen   80; ## listen for ipv4
    listen   [::]:80; ## listen for ipv6
    server_name cdn.yourdomain.com;
    access_log /var/log/nginx/cdn.yourdomain.com.access.log;
    error_log  /var/log/nginx/cdn.yourdomain.com.error.log;

    root /var/www/your/web/folder/;
    
    include sites-available/cdn.conf;
}

You have two options:

– use the same content folder of your actual installation/web page (I recommend this if you are doing this with WordPress or if you don’t want to move or copy your files from one folder to another). In this case the line “root /var/www/your/web/folder/;” has to point to your actual web folder or wordpress installation.

– configure a new empty folder (change the line according the “root /var/www/your/web/folder/;”) and move there your assets.

As you can see there is an include (“include sites-available/cdn.conf;”) I’m going to show you the content of the cdn.conf file (it have some additions for wordpress installations):

Change the line 7 to redirect your users to an error page or create the 404.html page in your web folder.

The file is commented, if you want to know more. The configuration includes some advantages as:

– No php execution in the subdomain.

– Set maximun browser cache for images, CSS and other static files.

– Don’t send cookies in the subdomain.

Now, you have to make a symbolic link of the first file that you have created into “/etc/nginx/sites-enabled” and restart nginx.

Your subdomain must be working now. If you have chosen the first option (use the same content folder of your actual installation/web page) you can access at the same files through your new subdomain. For example, in my server:

http://jesus.perezpaz.es/wp-content/uploads/2013/03/mc-1-280×300.jpg -> http://cdn-jesus.perezpaz.es/wp-content/uploads/2013/03/mc-1-280×300.jpg

It’s the same image but one is served with the default server configuration and the other one with all the improvements of the new subdomain.

If you have chosen the second option you can upload your assets to the new folder and see the subdomain working.

More generic optimizations could be done in your NGINX configuration. You can look for internet for those, there are plenty of sites with this information 🙂

WordPress & W3 Total Cache configuration

So, you have now your new “CDN” running and you want to use it in wordpress… easy 🙂

I’m going to use the plugin W3 total cache, because I use it for others performance improvements.

In the section “General Settings”(Performance>General Settings), enable “CDN” and use “Generic Mirror” as “CDN Type”. “Save all Settings”.

Go to the “CDN” section (Performance>CDN). Find the “Configuration” section and insert your new subdomain in “Replace site’s hostname with”.

“Test Mirror” and (if “Test passed”) “Save all Settings” again.

You can take a look at the different configurations on this page (default configurations must work well).

We have configured the new “CDN” and it will be used for the new uploads and for the assets, but we can change also the images and uploads in the ancient post.

To do that in the top of the same page (Performance>CDN), you can find a button “modify attachment URLs”. Click on it, insert your blog/page domain (not the new “CDN” subdomain) in “Domains to rename” and click “Start”. In a moment all your ancient images will be served through your new CDN.