Hi,
For a little while now I have been thinking about moving my personal blog to a self-hosted service. One of the options I have been considering is Linode.
As part of this idea. I wanted to see how I might be able to automate some of the processes. This is just a write up on one of my ideas so far.
Idea
The basic idea is pretty simple. After I have created and edited a post. I will push the updates to the remote hosting server. It will then rebuild the site on the hosting server and update the site. At the moment I use Hugo as my static site generator. As part of that I am looking at using a docker image with let’s Encrypt and Nginx. I may cover that in a future post.
requirements
- Actions must be done by unprivileged users.
- rsync is installed
- git is installed
- hugo is installed (This would change if you were using a different site generator)
Remote Server Environment
I am going to assume you have an existing unprivileged user. So I will not cover that here. If you need help. Google can be your friend.
The remote server will have two main directories.
- Bare git Repo to accept the push from my local development environment.
- Normal directly from which the site will be served by the chosen web server.
In my case I chose to create /var/www/
and var/repos
. These directories are owned by root. Below these I created the actual folders that git and the web server will use.
WWW
Here I created a folder using the name of my domain.
sudo mkdir -p /var/www/[domain-name]
sudo chown [myuser]:[myuser] /var/www/[domain-name]
chmod 755 /var/www/[domain-name]
The last two commands change the owner of domain-name
so that my unprivileged user will have access to this directory. Only the owner will have write access. But anyone can read. This is important as the web server will probably be a different user.
Repos
Here we create the directory for storing git repos. And specifically the repo directory for the site. We also make the directory a special git directory.
sudo mkdir -p /var/repos/[domain-name].git
sudo chown [myuser]:[myuser] /var/repos/[domain-name].git
cd /var/repos/[domain-name].git
git --bare init
post-receive hook
We need to create a post-receive
hook that will be triggered when we receive a push from our development server.
#!/bin/bash
DOMAIN=[domain-name]
GIT_REPO=/var/repos/[domain-name].git
WORKING_DIRECTORY=/tmp/$DOMAIN
PUBLIC_WWW=/var/www/$DOMAIN
BACKUP_WWW=/tmp/$DOMAIN-backup
set -e
rm -rf $WORKING_DIRECTORY
rsync -aqz $PUBLIC_WWW/ $BACKUP_WWW
trap "echo 'A problem occurred. Reverting to backup.'; rsync -aqz --del $BACKUP_WWW/ $PUBLIC_WWW; rm -rf $WORKING_DIRECTORY" EXIT
git clone $GIT_REPO $WORKING_DIRECTORY
# Add any git submodules here so that they are included during the build.
git clone https://github.com/[my sites theme] $WORKING_DIRECTORY/themes/[my theme name]
rm -rf $PUBLIC_WWW/*
hugo -s $WORKING_DIRECTORY -d $PUBLIC_WWW -b "http://${DOMAIN}"
rm -rf $WORKING_DIRECTORY
trap - EXIT
This script and idea was taken from Digital Ocean
This script basically clones the default branch into a /tmp/
directory. Collects the required theme module and then has hugo build the site directly into the live site folder. There is an issue that if you remove any content from your git repo. It will not be removed from the live site with this approach.
Note
This script could be improved by building the site in another temp directory, and then using rsync to copy this into the live site directory whist deleting any missing files and or folders. Though I did not create this script myself.
Local Development Environment
This part is pretty straight forward. We are simply going to add a new remote repo.
Inside our development git repo we can simply issue the command:
git remote add prod [myuser]@[host]:/var/repos/[domain-name].git
This will allow us to push our update directly to the live web server just by using the command
git push prod
But before we can do this we need to setup our ssh key access.
SSH Access
Regarding SSH. There are many great guides online for this. So I will just suggest that you take a look around.