Interwebs.life

Add a CDN to your site

host-from-home cloud nginx cdn cloudflare

To reduce the load on your server, you can put a content delivery network (CDN) in front of your site that will cache your static content and serve it without making a request back to the origin server. This post will describe how to setup Cloudflare as your CDN.

Update DNS records #

Create an account at Cloudflare and add your DNS records. For example, this site has two records:

Make sure the status for each of these records is proxied (orange cloud).

Next, update your nameservers at your registrar with the values provided. Once the changes go through, your site should be available and proxied through Cloudflare.

SSL/TLS #

We are going to make sure we have end-to-end encryption to our public facing server. Users will make a secure connection to Cloudflare, and Cloudflare will make a secure connection to our backend server.

On the SSL/TLS tab, we will use the Full (strict) option and install a Cloudflare certificate on our web server in the cloud. On the Origin Server tab, create a certificate for the apex domain and wildcard domain (interwebs.life and *.interwebs.life in my case). Copy the generated certificate and key to your cloud server, for example:

Make these files read-only with

chmod 400 interwebs.life/ssl/site.*

Update your default.conf file to configure nginx to use these certificates:

server {
listen 443 ssl;
ssl_certificate /etc/ssl/site.pem
ssl_certificate_key /etc/ssl/site.key
...

We will need to update our docker command to make sure we’re exposing port 443 and mounting the ssl dir:

docker run \
-v $(pwd)/interwebs.life/default.conf:/etc/nginx/conf.d/default.conf:ro \
-v $(pwd)/interwebs.life/ssl:/etc/ssl:ro \
-p 443:443 \
--name reverse-proxy \
--restart always \
-d \
nginx

Also, make sure the Always Use HTTPS setting is set to On in the SSL/TLS -> Edge Certificates tab.

Only allow traffic from Cloudflare #

All of the legitimate traffic should be coming from Cloudflare at this point, but we do still have port 443 open to the internet. To block traffic that is not coming from Cloudflare, we can turn on Authenticated Origin Pulls on the SSL/TLS tab. This will require a client certificate to be provided when making a request from our web server, and we will configure nginx to only accept Cloudflare’s client certificate.

Download the orgin-pull-ca.pem file to your site’s ssl directory on the cloud server. Then update the server block of your default.conf file to require that cert:

server {
...
ssl_client_certificate /etc/ssl/origin-pull-ca.pem;
ssl_verify_client on;
...

Restart nginx for these changes to take effect. You should still see your site when you navigate to your domain name, but if you try to navigate to your public ip address, you should get a 400 Bad Request: No required SSL certificate was sent error.

Filter out unwanted traffic #

At the time of this writing, this site is purely static. I’m not running php, wordpress, or any other dynamic server side processing. We can set up a firewall rule in Cloudflare to block traffic to things like php files that would just end up as a 404 on our origin server anyway.

On the Firewall tab, add a rule to filter out any traffic you don’t want and set the action to Block:

(http.request.uri.path contains "php") 
  or (http.request.uri.path contains "cgi") 
  or (http.request.uri.path contains "wp-") 
  or (http.request.uri.path contains "/admin") 
  or (not http.request.method in {"GET" "HEAD"})

Use a page rule to control caching #

You can take a look at the cf-cache-status response header to see how Cloudflare handled the request. In my case, the posts on this blog were being treated as dynamic content and not getting cached. This is because Cloudflare caches resources based on extension, and the posts don’t have an extension.

To make sure these requests get cached, we can setup a page rule that tells Cloudflare how to handle these requests. The content on this site is all static, so we can set to cache everything.

← Home