Custom GitHub pages redirect with nginx

I migrated my personal website from GitHub Pages to my own web server a while ago. VPS' are cheap and I enjoy managing my own web server.

However, there is one feature GitHub pages provides that I wanted to preserve: When you have a user page with a custom domain (might also work without a custom domain, not sure), every project page is available under http://example.net/<project>/ (where example.net is the custom user page domain).

I wanted to preserve this behavior, primarily because I didn't want to break existing links, but I also wanted to do this in an automated way.

The GitHub API

The first step was to get information about which of my repositories have GitHub pages enabled.

GitHub provides an API to access information about repositories. Some information is publicly accessible without authentication. That makes getting the information much easier. Unauthenticated access is subject to stricter rate
limits, but that is not an issue in my case.

The endpoint to use is https://api.github.com/users/<user>/repos which
returns a (JSON) array of repo objects. You can curl the URL for your own
user account to see all the data available.

The properties we are most interested in are name and has_pages: name is the
value to be used in URL to redirect to, has_pages tells us whether the repo
has GitHub pages enabled.

jq to the rescue

jq is a powerful little utility for processing JSON data. To filter the array for repos that have a GitHub page and get there name's, I use the following command:

curl <url> | jq -r '.[] | select(.has_pages) | .name'  

Creating nginx directives

I use nginx as my webserver. In order to redirect requests to GitHub I have to create location directives that look like

location /the-repo/ {  
  proxy-pass https://<user>.github.io/the-repo/;  
}  

This is pretty easy to do with awk or sed:

awk '{ printf "location /%s/ {\n proxy_pass https://<user>.github.io/%s/;\n}\n", $0, $0}' > github-pages-redirect  

The created file just needs to be included in the main nginx configuration file for the site and the server needs to be reloaded:

# /etc/nginx/sites-enabled/<site>  

server {  
 ...  

 include path/to/github-pages-redirect;  
}  

Complete script

Here is the complete script with placeholders. It also checks whether the
generated file not empty because I got invalid responses from the GitHub API
from time to time.

#!/bin/sh  

GH_ACCOUNT=account  
FILE=$HOME/github-pages-redirect  

curl --silent https://api.github.com/users/${GH_ACCOUNT}/repos |  
    jq -r '.[] | select (.has_pages==true) | .name' |  
        sort |  
            awk '{ printf "location /%s/ {\n proxy_pass https://${GH_ACCOUNT}.github.io/%s/;\n}\n", $0, $0}' > $FILE.new  

if diff --new-file $FILE $FILE.new; then  
    exit 0  
fi  

mv $FILE.new $FILE  
sudo systemctl reload nginx