# Motivation
My blog was originally running on hugo with nginx on a digitalocean server. But, it’s a static site! I shouldn’t need to pay to host it on a server when I could just be deploying to github pages for free.
I recently tried to pick up haskell, and wanted to configure my blog in haskell. This can be done through hakyll. I get the same benefits that hugo provides (e.g. static site generation from markdown files, except with pandoc) ; the configuration part is a bit easier and more powerful since it’s in haskell instead of a yaml file.
My vision was to have hakyll be able to convert my markdown, css/html templates, and haskell config file into a static website. I also didn’t want to do this every time I had a modification. The workflow I envisioned went like:
- push modified markdown, css/html template, haskell config to github
- github would grab
nix
on a build server and use nix flakes to convert to a static website. - that static website would be pushed to a separate branch of the repo that is deployed to github pages and link with my CNAME (justin.restivo.me)
# Building as a flake
The first thing to do was figure out how to generate the blog using nixFlake
.
Luckily, this guy
had already done this in a readable manner. However, he was hosting on a nginx
instance, which I didn’t want, so I cut some of what he did. The barebones
is just in my flake.nix
file.
This flake builds hakyll, then the static site (builder
) then copies the
generated site (plus CNAME
) to $out
. I was then able to get nix
to deploy
using the process described here and here. Note that I didn’t realize
this template existed until after I had put together this tooling. The template’s
nix tooling is quite nice.
The CI steps are:
- Use the checkout action to clone the repo
- Use the
cachix/install-nix-action
to install nix flakes. - Run the
nix build . -o site
to build the flake and put the result in thesite
subdirectory. - Use crazy-max
deploy to github pages action. This requires a
GITHUB_TOKEN
which is already autogenerated by github. It looks at thebuild_dir
field to figure out what to deploy, then pushes that folder to thetarget_branch
field (gh-pages
). This is then read in by github pages and deployed to the website insite/CNAME
(which was generated with theflake.nix
).
# Configuration
Generating the blog content is done by first nix develop
-ing, then running
hakyll-init
in the root directory; this generates the template to modify.
Then building is as easy as:
nix build .
The website workflow is easy to control from the Main.hs
file, and the
template’s css and html is easy enough to modify as well.
As with all static website generators, live refresh upon modification of css is a must for rapid prototyping. Hakyll allows this via:
nix develop
site --watch
# Google Analytics
I’m also interested in data, and one way to get data is to hook
the site into google analytics. Google gives your site a script to put in the
HEAD
of each page, and it will provide you with analytics based on the
requests to the page. I’ve done this and it’s pretty nifty
(though I’m the only user). Hakyll makes this easy, since all I need do is
modify the template used to include the analytics script and boom it’s
on all webpages.
# Adding style
To make the site look a little less outdated, I’m using nerdfonts
. This was
as easy as including a line in the HEAD
section and a little bit of css
per nerdfont README.
# Adding the Resume
So, my resume is built with latex. I would open source (and perhaps will) the repo I’m using for it. However, there’s personally identifying information like my mail address and phone number in the git history, and I’m too lazy to scrub that.
In any case: my resume is in latex and built with xelatex and latexmk. I recently turned it into a flake by modifying the default template to look like:
{
= "Justin Restivo Resume";
description
.nixpkgs.url = "github:NixOS/nixpkgs/nixos-20.09";
inputs
= { self, nixpkgs }: {
outputs
.x86_64-linux =
defaultPackageimport nixpkgs { system = "x86_64-linux"; };
with .mkDerivation {
stdenv= "justinrestivo_resume";
name = self;
src = "latexmk -pdf";
buildPhase = with nixpkgs;
buildInputs [
(texlive.combine {
(texlive) scheme-medium lipsum fmtcount datetime;
inherit })
];
= "mkdir -p $out/; mv *.pdf $out/";
installPhase };
};
}
This is a very simple flake that basically defines the latex dependencies and latexmk build command.
Now, if I want to build this into my website flake, I can list the resume repo as an input to the flake:
.justinrestivo_resume = {
inputs= "git+ssh://git@github.com/DieracDelta/resume";
url = true;
flake };
Then, in the build phase of justinrestivo-me
,
I can just copy the pdf output of my blog’s flake into the output site
directory and have it be accessible (and linked to by the blog):
cp ${justinrestivo_resume}/justin_restivo_resume.pdf $out
In theory this is great, but I still needed it to play nicely with CI. This all built fine locally, but did not with github actions. It couldn’t grab the flake since github CI didn’t have permissions to clone the private repo that contained my resume flake. To get around this, I had to add in another github action that started ssh-agent with a custom private ssh key. The relevant piece of the yaml is:
- uses: webfactory/ssh-agent@v0.4.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
So first I had to generate a private ssh key, add it to my githubs, and
then as a repo secret with the label secrets.SSH_PRIVATE_KEY
.
Still, after I had ssh-agent start like that, everything worked smoothly. Now, nix builds my resume as a dependency, then builds my website with the resulting resume pdf included.