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