Set up a Jekyll site on a vps with Ubuntu, Nginx and Letsencrypt
Recently, I decided to update my personal site/blog using Jekyll. As a developer, I like to have some control over what happens on the server, setting up a vps therefore seemed like a good option, despite other hosting options such as Github pages.
Another reason for this approach is that it allows you to use Letsencrypt, a free certificate authority for SSL. Setting up a vps and configuration does require basic knowledge of the command line and text editors like vim / nano. However, if you don’t have that experience, this is a perfect opportunity to learn. This guide also assumes you’re using Mac/Linux. Let’s get started!
1. Install Jekyll
First, install Jekyll, a simple, blog-aware, static site generator. Check out the Jekyll docs for the installation requirements(Ruby).
2. Create a new droplet with Ubuntu 16.04 on Digitalocean
We’ll use DigitalOcean to create our Ubuntu VPS. Create an account and head over to your dashboard to create a new droplet.
- create a droplet
- select ubuntu 16.04 (latest)
- Choose a size. Because this is a simple static site, the cheapest option ($5) will do.
- Choose a region
- Add your ssh key (we will use this to log in to our server with ssh)
- Name your droplet to something recognizable (yourblog)
- create droplet!
3. Setting up server access
Your droplet is now ready, the next step is to setup ssh access and create a new user for deploying our site. Because we added ssh keys to our droplet, we can login as a root user.
ssh root@YOUR_SERVER_IP
The next step is to create a new (deploy) user with the appropriate permissons
sudo adduser deploy
*this will prompt a password change
Use enter to skip the user information for deploy. Next, add the deploy user to sudo group permissions
sudo adduser deploy sudo
to switch to the deploy user run
su deploy
Close the connection to the server
Now we will add ssh keys for the deploy user as well.
An easy way to do this is using a tool called ssh-copy-id
.
Run the following on your local machine to copy your ssh keys to the server.
ssh-copy-id deploy@YOUR_SERVER_IP
This will prompt for the password you set earlier.
Test your ssh login with ssh deploy@YOUR_SERVER_IP
4. Install Nginx
On our droplet, we will use Nginx to serve our pages. On your server, run the following to install Nginx.
To check if Nginx is running, enter your ip address in the browser. This should display the “Welcome to Nginx” page. Alternatively, run
sudo service nginx status
5. Getting your static site on the server
- If you would rather use Capistrano, you can skip this and read 8. Deploying with Capistrano instead.
Now we want to get our static site files to the server.
The default directory where nginx finds the html you’re seeing right now is the default index.html in /var/www/html
.
We’re going to change that by adjusting the default nginx configuration (using vim or nano).
sudo vim /etc/nginx/sites-enabled/default
find the line with root /var/www/html;
and change it to
/home/deploy/your_blog_name/_site
There are several ways to transfer static site files to a server. One of the simpler methods is using rsync. On your local machine, in your blog directory, run the following command to generate the _site build folder that we will transfer to the server.
bundle exec jekll build
To transfer the _site directory to our server, run
rsync -a _site deploy@YOUR_SERVER_IP:/home/deploy/your_site_name
If we go back to the server we should find our files in /home/deploy/your_site_name/_site
Run sudo nginx -s reload
to see if your site is up and running!
This is a (very) basic method of getting files to the server. Later I explain how you can setup Capistrano to deploy your site.
6. Add a custom domain name
Go to your dns provider and add an A record with your server ip to your domain name.
Next, ssh into the server and open the Nginx configuration file;
sudo vim /etc/nginx/sites-enables/default
update the server_name with your domain name;
server_name your_domain.com;
Reload nginx configuration with sudo nginx -s reload
, your site should now be accessible via your custom domain.
7. Free SSL with Letsencrypt
Let’s Encrypt is a free, automated, and open certificate authority. To install letsencrypt run the following commands on your server
Run the following to create the certificates, make sure you replace the path, email and domain with yours.
- Also make sure you set the correct webroot path, when deploying with Capistrano for example the
_site
folder should be replaced withcurrent
.
To get an A+ rating for our SSL security, run the following command to generate a Diffie-Hellman group. This is an extra measure to protect our site from the Logjam Attack.
The next step is to set up our Nginx configuration for SSL
sudo vim /etc/nginx/sites-enabled/default
We divide the configuration in two blocks, one for HTTP traffic (which we redirect to HTTPS) and the other for our ssl configuration, including several best practices such as including the protocols, ciphers and the path to the dhparams.
After adjusting the Nginx configuration, reload with sudo nginx -s reload
Letsencrypt certificates are short-lived, and need to be renewed regularly. We’ll add a Cron job to automatically run the renewal script.
Open the crontab with
sudo crontab -e
add the following line to the bottom.
30 2 * * 1 /home/deploy/.local/share/letsencrypt/bin/letsencrypt renew
8. Deploying with Capistrano
Our previous deploy method (rsync) is ofcourse very limited. For some more control over our deployment process we will set up Capistrano in our project. Capistrano uses Github to deploy, so start with submitting your project to Github.
IMPORTANT: Jekyll adds the ‘_site’ directory to the .gitignore file by default. We do need this in our repository, so remove this from your gitignore file.
First, make sure that Capistrano is installed by adding it to your gemfile
gem capistrano
In your site directory run the following to generate the Capistrano configuration files.
cap install
Update/add the following to config/deploy.rb
Change the contents of the file deploy/production.rb to the following
When you deploy, Capistrano will create a /current
directory with your files. The last thing we will have to do is to update Nginx to serve files from this directory.
So on your server, open the Nginx configuration
sudo vim /etc/nginx/sites-enabled/default
change the site root to the following
root /home/deploy/your_site_name/current;
We’ve setup Capistrano to use ssh forwarding, so we can deploy using our ssh key.
For this to work, our ssh key has to be loaded into memory by ssh-agent
.
To check if your key is available, run ssh-add -L
(locally).
You can manually add your key with ssh-add ~/.ssh/id_rsa
. To permanently add the key, update your system’s ssh_config to allow agent forwarding. Check out the Github developer guides for more info about using ssh agent forwarding.
Now to deploy your site
Because the Nginx configuration was changed an extra sudo nginx -s reload
on your server is necessary to reload changes.
That’s it!