Hosting Static Site on Dokku with Free Cloudflare CDN and SSL

 
Dokku static website represented by a brick wall

Dokku is dev ops for dummies and a simple way to deploy websites on a barebones VPS. In this tutorial, I will describe how to use it to host a static site, and setup global assets caching with free Cloudflare CDN and SSL certificate.

I use jekyll for this blog and until recently I was hosting it on GitHub Pages. I’ve decided to move it to self-hosting with Dokku. Later in this post I will explain why in my particular case self-hosting is a better option.

Initial setup

Some of the steps in this tutorial are identical to my previous post about migrating Rails app from Heroku to Dokku.

First, you need to purchase a barebones VPS and add an SSH access to it. I will not elaborate on how to do it in this tutorial.

Let’s assume that your VPS has an IP address 192.192.8.8 and your static website will use my-static-site.com as a domain.

SSH into your VPS:

ssh [email protected]

and run:

wget https://raw.githubusercontent.com/dokku/dokku/v0.18.0/bootstrap.sh;
sudo DOKKU_TAG=v0.18.0 bash bootstrap.sh
Replace v0.18.0 with the newest version of Dokku from releases page

Next, you need to specify your app’s name:

dokku apps:create my-static-site

You can now exit your VPS. All the remaining commands can be executed locally.

To finish the Dokku setup you need to go to your IP 192.192.8.8 in a browser and input your public SSH keys there. To check out your SSH keys you can visit the following URL:

https://github.com/[YOUR GITHUB USERNAME].keys

Set Dokku Git remote target

To enable automatic deployments when doing a git push you need to add following lines to your .git/config file.

[remote "dokku"]
  url = [email protected]:my-static-site
  fetch = +refs/heads/*:refs/remotes/dokku/*

Check if your setup is correct by running:

dokku apps:list

If everything is correct you should see the name of your app: my-static-site

Setup buildpack and static content source

We will use an official Dokku NGINX buildpack for our static website. To enable it you need to run the following commands:

touch .static
dokku config:set BUILDPACK_URL=https://github.com/dokku/buildpack-nginx

Official docs recommend using a NGINX_ROOT variable to set the static content folder, but I prefer to use a custom NGINX config. It gives you more control and flexibility.

To do it add a app-nginx.conf.sigil file to the root of your repo with the following contents:

worker_processes 1; # 1
error_log stderr;
pid nginx.pid;
daemon off;

events {
  worker_connections 1024; # 2
}

http {
  types_hash_max_size 2048;
  include mime.types;

  server {
    listen {{ $.PORT }};
    server_name  _;
    root /app/www/docs; # 3
    index index.html;
    port_in_redirect off;

    error_page 404 /404.html;
    location / {
      try_files $uri $uri.html $uri/ =404; # 4
    }
  }
}

Let’s explain some of the options:

  1. worker_processes should be set to the number of CPU cores on your VPS.

  2. worker_connections stands for the number of client connections which can be served at the same time. Remember that a single browser could open multiple connections to your server.

  3. root /app/www/docs here is where you specify a folder from which static content will be served. In my case, it is docs directory in my Dokku repo.

  4. try_files $uri $uri.html $uri/ =404; specifies what files NGINX will try to serve based on a request path. In case it does not manage to match any it will display 404.html file with 404 HTTP status code.

Be aware that by adding this file you overwrite a custom Dokku NGINX template. You can find a default version here.

Add SSL and global assets CDN using Cloudflare

Setup global CDN

You should use Cloudflare DNS for your domain. If you don’t know how to set it up you can check out my previous tutorial.

Enabling CDN is as simple as ticking a cloud icon next to DNS config for your website:

Correct Cloudflare CDN DNS config

If you have trouble with an old DNS entry cache not refreshing you can use whatsmydns.net to check if it has already propagated in another region of the world.

Setup SSL certificate

Cloudflare offers a free end-to-end SSL certificate. You need to set SSL config to full and download private and public keys from the dashboard. To install certificates on your Dokku NGINX run the following commands:

tar cvf certificates.tar certificate.pem certificate.key
dokku certs:add my-static-site < certificates.tar
dokku domains:add my-static-site.com

Deploy

Now you just need to add some static assets to your docs/ repo folder and deploy the app by typing:

git push dokku master

Your app should be up and running on my-static-site.com.

Advantages over GitHub Pages

Price

Although GitHub Pages are free, you need to use a GitHub repo for them. If you don’t want to open source your site you need to pay for private repos. Using Dokku you can setup multiple NGINX instances on a single VPS. Currently, I am paying $5/month for a Hetzner Cloud VPS with 1GB RAM. RAM usage for this blog is ~2MB so I could host tens of static websites on this single low-end VPS. Together with free global assets CDN caching each of the NGXIN instances is able to handle loads of traffic. I verified it using Siege load testing.

You can check memory usage of your docker containers by accessing your VPS and running:

docker stats

Access to traffic logs

Although you can install Google Analytics on the website hosted by GitHub Pages I’ve noticed that traffic statistics reported by GA are much lower than what I see in unique visitor statistics displayed by Cloudflare. It looks like a lot of people are using tracking blockers.

You can display your NGINX access logs by typing:

dokku nginx:access-logs -t

Alternatively, you can find them on your VPS in /var/log/nginx/ and export for further analysis.

Control over cache settings

GitHub Pages use a global assets CDN however you don’t have a way to customize its settings. I could not increase caching duration for my assets and it negatively affected my Google Page Speed Insights rating. I use digest tags for all my assets so I can cache them for a maximum duration of 8 days offered by Cloudflare CDN. Download my free jekyll SEO template to see how it can be implemented for static websites.

You can also check out my previous post for more info about ways to optimize speed rating of your website.

Summary

With Dokku you can easily host static websites on a simple VPS without much dev ops skills. I really think that it is a viable alternative to commercial services like GitHub Pages giving you more control over your content.



Back to index