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

UPDATE: CORS (Cross-origin resource sharing) added to the “fake” CDN. Based on:

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:

server {
    listen   80; ## listen for ipv4
    listen   [::]:80; ## listen for ipv6
    access_log /var/log/nginx/;
    error_log  /var/log/nginx/;

    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:×300.jpg ->×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.

Go to the Homepage → ← Go back



  1. Ary Wibowo says:

    hi, i’ve tried to make my own cdn similar like this tutorial. but i wanna ask you, why if i set `location ~* .(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf|html|txt|htm)$ {
    expires max;
    log_not_found off;
    access_log off;
    add_header Cache-Control public;
    fastcgi_hide_header Set-Cookie;
    }`. all files become unaccesible. it returns 404. but if i turn off, it can be accesible again. perhaps you can help give me some explanation. thanks 🙂

    • admin says:

      Hi Ary.

      That’s strange… It should work fine… Have you changed any other configuration?

      Try also to remove the options line by line to see if it works.

  2. Pixelaar LLC says:


    I have been followed your instruction and all working nice except GT Matrix still showing notice for Cookie Free domain. I checked and all my static content loading from my subdomain so why it still saying not Cookie Free to my subdomain link ? Is there I missed something ?


  3. Gamal says:

    i have read every tutorial, tried every method, your tutorial is the only one worked for me to define the CDN correctly and removed the (CORS policy) error which was hiding all the font icons from my themes.
    Millions of thx 🙂

Leave a Comment

Your email address will not be published.