Public | Automated Build

Last pushed: 4 months ago
Short Description
Automated build for the Fedora-based container I use to deploy my personal site.
Full Description

alexhaydock.co.uk

This is one of the source repositories for https://alexhaydock.co.uk/ (also hosted at http://alex5q3xhu7wi642.onion/)

This site is built using Jekyll and a modified version of the Pithy theme. Pages and posts are written in Markdown and compiled to HTML by the Jekyll build process.

The main root of this repository holds the Jekyll source, and the compiled static HTML of the site is held in the _site/ directory.


Deployment (Docker)

I deploy this site using Docker for maximum speed and flexibility. The images I use are hosted on Docker Hub (linked to the Dockerfile in this GitHub repo). I deploy this as a systemd service. SSL termination is handled by an nginx instance acting as a reverse proxy that redirects port 80 on the host to the HTTP port that the Docker container is listening on (currently 8080).

This Docker container is built on top of my Nginx+PageSpeed+OpenSSLBeta container.

The Docker Hub images allow for easy prototyping and instant deployment. So if for some strange reason you want to deploy a local version of my website to look at, you can do so with:

docker run --cap-drop=all --name nginx -p 80:8080 -d ajhaydock/alexhaydock.co.uk

Alternatively, you can clone this repo and build the Docker container directly. Enter the directory containing the Dockerfile you want to build an image for, and build it with something like:

docker build -t alexhaydock.co.uk .

Running a manually-built container is similar to the above:

docker run --cap-drop=all --name nginx -p 80:8080 -d alexhaydock.co.uk
Tor Hidden Service

I also deploy a seperate container to host the Tor process which serves this site as an Onion Service. It is deployed using this container.

You can find the torrc and the systemd .service file to go with this container here.


Development Process

Install Ruby and Dev Tools (Debian-based):

sudo apt install build-essential git ruby ruby-dev

Install Ruby and Dev Tools (Red Hat-based):

sudo dnf install git ruby ruby-devel

To install Jekyll as a Ruby gem (ensure you have Ruby installed first), use:

sudo gem install jekyll

And then, within the alexhaydock.co.uk-staging directory, run the following command:

jekyll build

This will build a copy of the site as static HTML inside the _site/ directory, which can be served via a webserver.

Or, to preview changes to the site, with live updates:

jekyll serve

This will start a local webserver entirely within Jekyll (no external server needed) that updates as soon as changes are made to the source files. You can generally access it from http://localhost:4000/


Grsecurity Kernels

If you are cool enough to be running a kernel compiled with the Grsecurity/PaX patchset, you probably need to ensure that MPROTECT is disabled for both the Jekyll and Ruby binaries. You can do this a number of ways, but the easiest is probably with setfattr (you will need the attr package if you don't already have it):

sudo setfattr -n user.pax.flags -v m /usr/bin/ruby
sudo setfattr -n user.pax.flags -v m /usr/local/bin/jekyll

After this, Jekyll should build or serve the site without error.


LetsEncrypt ECDSA Certificate Generation Process

First Run

Create a directory to hold our keys:

sudo mkdir -p /usr/share/nginx/keys/

Clone LetsEncrypt client ready to request our certificate:

cd ~ && git clone https://github.com/certbot/certbot && cd certbot

Generate the ECC private key we will use for our cert:

openssl ecparam -genkey -name secp384r1 | sudo tee /usr/share/nginx/keys/privkey-p384.pem

Generate the CSR (Certificate Signing Request) using the private key. It is important to ensure you also include the www. subdomain in this line, as otherwise Google will not incorporate your domain into their HSTS preload list:

openssl req -new -sha256 -key /usr/share/nginx/keys/privkey-p384.pem -subj "/CN=alexhaydock.co.uk" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:alexhaydock.co.uk,DNS:www.alexhaydock.co.uk,DNS:test.alexhaydock.co.uk")) -outform der -out csr-p384.der && sudo cp -f -v csr-p384.der /usr/share/nginx/keys/csr-p384.der

Feed the CSR into LetsEncrypt client so it spits out a full (public) ECDSA leaf certificate for us:

sudo ./certbot-auto certonly --webroot --webroot-path /usr/share/nginx/html/alexhaydock.co.uk --email alex@alexhaydock.co.uk --csr /usr/share/nginx/keys/csr-p384.der --renew-by-default --agree-tos

If you are running a Grsec kernel, the above step will probably have failed. Please see the bottom of this document for some extra instructions to complete at this point, and then try the above command again.

Move the public leaf cert to our keys directory (Note that your generated certificate might be under a different number if you have generated certificates in the past):

sudo mv -f -v $HOME/certbot/0001_chain.pem /usr/share/nginx/keys/ecdsa-chain.pem

Now, we need to add the following lines to our nginx.conf, within our SSL server block, so that Nginx knows where to find our public certificate and corresponding private key:

ssl_certificate        /usr/share/nginx/keys/ecdsa-chain.pem;
ssl_certificate_key    /usr/share/nginx/keys/privkey-p384.pem;

Make sure to restart Nginx so it uses the new certificate:

sudo systemctl restart nginx

Re-Running

Generally we can reuse the same CSR from our first run each time you need to generate a new certificate (which is every 90 days with LetsEncrypt)

First update your Certbot installation

cd ~/certbot && git pull

And repeat the same command from the above section that feeds our CSR to LetsEncrypt:

sudo ./certbot-auto certonly --webroot --webroot-path /usr/share/nginx/html/alexhaydock.co.uk --email alex@alexhaydock.co.uk --csr /usr/share/nginx/keys/csr-p384.der --renew-by-default --agree-tos

And install our generated cert:

sudo mv -f -v $HOME/certbot/0001_chain.pem /usr/share/nginx/keys/ecdsa-chain.pem

Make sure to restart Nginx so it uses the new certificate:

sudo systemctl restart nginx

Notes for LetsEncrypt under Grsec/Pax kernels

MPROTECT will need to be disabled on some of the binaries pulled in by the LetsEncrypt client:

sudo setfattr -n user.pax.flags -v m $HOME/.local/share/letsencrypt/bin/letsencrypt
sudo setfattr -n user.pax.flags -v m $HOME/.local/share/letsencrypt/bin/pip
sudo setfattr -n user.pax.flags -v m $HOME/.local/share/letsencrypt/bin/pip2
sudo setfattr -n user.pax.flags -v m $HOME/.local/share/letsencrypt/bin/pip2.7
sudo setfattr -n user.pax.flags -v m $HOME/.local/share/letsencrypt/bin/python2.7
sudo setfattr -n user.pax.flags -v m /root/.local/share/letsencrypt/bin/letsencrypt
sudo setfattr -n user.pax.flags -v m /root/.local/share/letsencrypt/bin/pip
sudo setfattr -n user.pax.flags -v m /root/.local/share/letsencrypt/bin/pip2
sudo setfattr -n user.pax.flags -v m /root/.local/share/letsencrypt/bin/pip2.7
sudo setfattr -n user.pax.flags -v m /root/.local/share/letsencrypt/bin/python2.7
Docker Pull Command
Owner
ajhaydock
Source Repository

Comments (0)