goodbye github pages, also make header look nicer on mobile
This commit is contained in:
parent
3a2309c264
commit
b2a271128c
6
Makefile
6
Makefile
@ -6,12 +6,10 @@ install: result
|
|||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm result
|
rm result
|
||||||
|
rm -rf _site
|
||||||
|
|
||||||
serve:
|
serve:
|
||||||
nix-shell -A serve
|
nix-shell -A serve
|
||||||
|
|
||||||
update:
|
update:
|
||||||
nix-shell -p bundler --run 'bundler update'
|
nix-shell -p bundler --run 'bundler update; bundler lock; bundix; rm -rf .bundle vendor'
|
||||||
|
|
||||||
lock:
|
|
||||||
nix-shell -p bundler -p bundix --run 'bundler lock; bundler package --no-install --path vendor; bundix; rm -rf .bundle vendor'
|
|
||||||
|
@ -12,18 +12,17 @@
|
|||||||
in
|
in
|
||||||
{
|
{
|
||||||
build = derivation {
|
build = derivation {
|
||||||
system = system;
|
inherit jekyll_env system;
|
||||||
name = "mediocre-blog";
|
name = "mediocre-blog";
|
||||||
builder = "${pkgs.bash}/bin/bash";
|
builder = "${pkgs.bash}/bin/bash";
|
||||||
args = [ ./build.sh ];
|
args = [ ./build.sh ];
|
||||||
|
|
||||||
src = ./src;
|
src = ./src;
|
||||||
stdenv = pkgs.stdenv;
|
stdenv = pkgs.stdenv;
|
||||||
inherit jekyll_env;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
serve = pkgs.stdenv.mkDerivation rec {
|
serve = pkgs.stdenv.mkDerivation {
|
||||||
name = "jekyll_env";
|
name = "mediocre-blog-shell";
|
||||||
|
|
||||||
# glibcLocales is required so to fill in LC_ALL and other locale
|
# glibcLocales is required so to fill in LC_ALL and other locale
|
||||||
# related environment vars. Without those jekyll's scss compiler
|
# related environment vars. Without those jekyll's scss compiler
|
||||||
@ -36,6 +35,8 @@
|
|||||||
exec ${jekyll_env}/bin/jekyll serve -s ./src -d ./_site -w -I -D -H 0.0.0.0
|
exec ${jekyll_env}/bin/jekyll serve -s ./src -d ./_site -w -I -D -H 0.0.0.0
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
env = jekyll_env;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ description: >-
|
|||||||
A mix of tech, art, travel, and who knows what else.
|
A mix of tech, art, travel, and who knows what else.
|
||||||
baseurl: "" # the subpath of your site, e.g. /blog
|
baseurl: "" # the subpath of your site, e.g. /blog
|
||||||
url: https://blog.mediocregopher.com # the base hostname & protocol for your site, e.g. http://example.com
|
url: https://blog.mediocregopher.com # the base hostname & protocol for your site, e.g. http://example.com
|
||||||
repository: mediocregopher/blog.mediocregopher.com
|
repository: https://github.com/mediocregopher/blog.mediocregopher.com
|
||||||
twitter_username: mediocre_gopher
|
twitter_username: mediocre_gopher
|
||||||
github_username: mediocregopher
|
github_username: mediocregopher
|
||||||
rss: rss
|
rss: rss
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<header id="title-header" role="banner">
|
<header id="title-header" role="banner">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="seven columns">
|
<div class="seven columns" style="margin-bottom: 3rem;">
|
||||||
<h1 class="title">
|
<h1 class="title">
|
||||||
<a href="{{ "/" | relative_url }}">{{ site.title | escape }}</a>
|
<a href="{{ "/" | relative_url }}">{{ site.title | escape }}</a>
|
||||||
</h1>
|
</h1>
|
||||||
@ -20,7 +20,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{%- if!page.nofollow != true %}
|
{%- if!page.nofollow != true %}
|
||||||
<div class="five columns light" style="text-align: right">
|
<div class="five columns light">
|
||||||
<span style="display:block; margin-bottom:0.5rem;">Get notified when new posts are published!</span>
|
<span style="display:block; margin-bottom:0.5rem;">Get notified when new posts are published!</span>
|
||||||
<a href="{{ "/follow.html" | relative_url }}"><button class="button-primary">
|
<a href="{{ "/follow.html" | relative_url }}"><button class="button-primary">
|
||||||
<i class="fab fa-twitter"></i>
|
<i class="fab fa-twitter"></i>
|
||||||
|
239
src/_posts/2021-01-23-goodbye-github-pages.md
Normal file
239
src/_posts/2021-01-23-goodbye-github-pages.md
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
---
|
||||||
|
title: >-
|
||||||
|
Goodbye, Github Pages
|
||||||
|
description: >-
|
||||||
|
This blog is no longer sponsored by Microsoft!
|
||||||
|
---
|
||||||
|
|
||||||
|
Slowly but surely I'm working on moving my digital life back to being
|
||||||
|
self-hosted, and this blog was an easy low-hanging fruit to tackle. Previously
|
||||||
|
the blog was hosted on Github Pages, which was easy enough but also in many ways
|
||||||
|
restricting. By self-hosting I'm able to have a lot more control over the
|
||||||
|
generation, delivery, and functionality of the blog.
|
||||||
|
|
||||||
|
For reference you can find the source code for the blog at
|
||||||
|
[{{site.repository}}]({{site.repository}}). Yes, it will one day be hosted
|
||||||
|
elsewhere as well.
|
||||||
|
|
||||||
|
## Nix
|
||||||
|
|
||||||
|
Nix is something I'm slowly picking up, but the more I use it the more it grows
|
||||||
|
on me. Rather than littering my system with ruby versions and packages I'll
|
||||||
|
never otherwise use, nix allows me to create a sandboxed build pipeline for the
|
||||||
|
blog with perfectly reproducible results.
|
||||||
|
|
||||||
|
The first step in this process is to take the blog's existing `Gemfile.lock` and
|
||||||
|
turn it into a `gemset.nix` file, which is essentially a translation of the
|
||||||
|
`Gemfile.lock` into a file nix can understand. There's a tool called
|
||||||
|
[bundix][bundix] which does this, and it can be used from a nix shell without
|
||||||
|
having to actually install anything:
|
||||||
|
|
||||||
|
```
|
||||||
|
nix-shell -p bundix --run 'bundix'
|
||||||
|
```
|
||||||
|
|
||||||
|
The second step of using nix is to set up a nix expression in the file
|
||||||
|
`default.nix`. This will actually build the static files. As a bonus I made my
|
||||||
|
expression to also allow for serving the site locally with dynamic updating
|
||||||
|
everytime I change a source file. My `default.nix` looks like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
# pkgs refers to all "builtin" nix pkgs and utilities. By importing from a
|
||||||
|
# URL I'm able to always pin this default.nix to a specific version of those
|
||||||
|
# packages.
|
||||||
|
pkgs ? import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/cd63096d6d887d689543a0b97743d28995bc9bc3.tar.gz") {},
|
||||||
|
system ? builtins.currentSystem,
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
# bundlerEnv looks for a Gemfile, Gemfile.lock, and gemset.nix inside
|
||||||
|
# gemdir, and derives a package containing ruby and all desired gems.
|
||||||
|
ruby_env = pkgs.bundlerEnv {
|
||||||
|
name = "ruby_env";
|
||||||
|
ruby = pkgs.ruby;
|
||||||
|
gemdir = ./.;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
# build will derive a package which contains the generated static
|
||||||
|
# files of the blog. It uses the build.sh file (provided below) to
|
||||||
|
# do this.
|
||||||
|
build = derivation {
|
||||||
|
name = "mediocre-blog";
|
||||||
|
|
||||||
|
# The build.sh file (source provided below) is executed in order
|
||||||
|
# to actually build the site.
|
||||||
|
builder = "${pkgs.bash}/bin/bash";
|
||||||
|
args = [ ./build.sh ];
|
||||||
|
|
||||||
|
# ruby_env is provided as an input to build.sh so that it can
|
||||||
|
# use jekyll, and the src directory is provided so it can access
|
||||||
|
# the blog's source files. system is required by the derivation
|
||||||
|
# function, and stdenv provides standard utilities to build.sh.
|
||||||
|
inherit ruby_env system;
|
||||||
|
src = ./src;
|
||||||
|
stdenv = pkgs.stdenv;
|
||||||
|
};
|
||||||
|
|
||||||
|
# serve will derive an environment specifically tailored for being
|
||||||
|
# run in a nix-shell. The resulting shell will have ruby_env
|
||||||
|
# provided for it, and will automatically run the `jekyll serve`
|
||||||
|
# command to serve the blog locally.
|
||||||
|
serve = pkgs.stdenv.mkDerivation {
|
||||||
|
name = "mediocre-blog-shell";
|
||||||
|
|
||||||
|
# glibcLocales is required so to fill in LC_ALL and other locale
|
||||||
|
# related environment vars. Without those jekyll's scss compiler
|
||||||
|
# fails.
|
||||||
|
#
|
||||||
|
# TODO probably get rid of the scss compiler.
|
||||||
|
buildInputs = [ ruby_env pkgs.glibcLocales ];
|
||||||
|
|
||||||
|
shellHook = ''
|
||||||
|
exec ${ruby_env}/bin/jekyll serve -s ./src -d ./_site -w -I -D
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
(Nix is a bit tricky to learn, but I highly recommend chapters 14 and 15 of [the
|
||||||
|
nix manual][manual] for an overview of the language itself, if nothing else.)
|
||||||
|
|
||||||
|
The `build.sh` used by the nix expression to actually generate the static files
|
||||||
|
looks like this:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# stdenv was given a dependency to build.sh, and so build.sh can use it to
|
||||||
|
# source in utilities like mkdir, which it needs.
|
||||||
|
source $stdenv/setup
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Set up the output directory. nix provides the $out variable which will be the
|
||||||
|
# root of the derived package's filesystem, but for simplicity later we want to
|
||||||
|
# output the site within /var/www.
|
||||||
|
d="$out/var/www/blog.mediocregopher.com"
|
||||||
|
mkdir -p "$d"
|
||||||
|
|
||||||
|
# Perform the jekyll build command. Like stdenv the ruby_env was given as a
|
||||||
|
# dependency to build.sh, so it has to explicitly use it to have access to
|
||||||
|
# jekyll. src is another explicit dependency which was given to build.sh, and
|
||||||
|
# contains all the actual source files within the src directory of the repo.
|
||||||
|
$ruby_env/bin/jekyll build -s "$src" -d "$d"
|
||||||
|
```
|
||||||
|
|
||||||
|
With these pieces in place I can easily regenerate the site like so:
|
||||||
|
|
||||||
|
```
|
||||||
|
nix-build -A build
|
||||||
|
```
|
||||||
|
|
||||||
|
Once run the static files will exist within a symlink called `result` in the
|
||||||
|
project's root. Within the symlink will be a `var/www/blog.mediocregopher.com`
|
||||||
|
tree of directories, and within that will be the generated static files, all
|
||||||
|
without ever having to have installed ruby.
|
||||||
|
|
||||||
|
The expression also allows me to serve the blog while I'm working on it. Doing
|
||||||
|
so looks like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
nix-shell -A serve
|
||||||
|
```
|
||||||
|
|
||||||
|
When run I get a normal jekyll process running in my `src` directory, serving
|
||||||
|
the site in real-time on port 4000, once again all without ever installing ruby.
|
||||||
|
|
||||||
|
As a final touch I introduced a simple `Makefile` to my repo to wrap these
|
||||||
|
commands, because even these were too much for me to remember:
|
||||||
|
|
||||||
|
```
|
||||||
|
result:
|
||||||
|
nix-build -A build
|
||||||
|
|
||||||
|
install: result
|
||||||
|
nix-env -i "$$(readlink result)"
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm result
|
||||||
|
rm -rf _site
|
||||||
|
|
||||||
|
serve:
|
||||||
|
nix-shell -A serve
|
||||||
|
|
||||||
|
update:
|
||||||
|
nix-shell -p bundler --run 'bundler update; bundler lock; bundix; rm -rf .bundle vendor'
|
||||||
|
```
|
||||||
|
|
||||||
|
We'll look at that `install` target in the next section.
|
||||||
|
|
||||||
|
## nginx
|
||||||
|
|
||||||
|
So now I have the means to build my site quickly, reliably, and without
|
||||||
|
cluttering up the rest of my system. Time to actually serve the files.
|
||||||
|
|
||||||
|
My home server has a docker network which houses most of my services that I run,
|
||||||
|
including nginx. nginx's primary job is to listen on ports 80 and 443, accept
|
||||||
|
HTTP requests, and direct those requests to their appropriate service based on
|
||||||
|
their `Host` header. nginx is also great at serving static content from disk, so
|
||||||
|
I'll take advantage of that for the blog.
|
||||||
|
|
||||||
|
The one hitch is that nginx is currently running within a docker container,
|
||||||
|
as are all my other services. Ideally I would:
|
||||||
|
|
||||||
|
* Get rid of the nginx docker container.
|
||||||
|
* Build a nix package containing nginx, all my nginx config files, and the blog
|
||||||
|
files themselves.
|
||||||
|
* Run that directly.
|
||||||
|
|
||||||
|
Unfortunately extracting nginx from docker is dependent on doing so for all
|
||||||
|
other services as well, or at least on running all services on the host network,
|
||||||
|
which I'm not prepared to do yet. So for now I've done something janky.
|
||||||
|
|
||||||
|
If you look at the `Makefile` above you'll notice the `install` target. What
|
||||||
|
that target does is to install the static blog files to my nix profile, which
|
||||||
|
exists at `~/.nix-profile`. nix allows any package to be installed to a profile
|
||||||
|
in this way. All packages within a profile are independent and can be added,
|
||||||
|
updated, and removed atomically. By installing the built blog package to my
|
||||||
|
profile I make it available at `~/.nix-profile/var/www/blog.mediocregopher.com`.
|
||||||
|
|
||||||
|
So to serve those files via nginx all I need to do is add a read-only volume to
|
||||||
|
the container...
|
||||||
|
|
||||||
|
```
|
||||||
|
-v $HOME/.nix-profile/var/www/blog.mediocregopher.com:/var/www/blog.mediocregopher.com:ro \
|
||||||
|
```
|
||||||
|
|
||||||
|
...add a new virtual host to my nginx config...
|
||||||
|
|
||||||
|
```
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name blog.mediocregopher.com;
|
||||||
|
root /var/www/blog.mediocregopher.com;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
...and finally direct the `blog` A record for `mediocregopher.com` to my home
|
||||||
|
server's IP. Cloudflare will handle TLS on port 443 for me in this case, as well
|
||||||
|
as hide my home IP, which is prudent.
|
||||||
|
|
||||||
|
## Deploying
|
||||||
|
|
||||||
|
So now it's time to publish this new post to the blog, what are the actual
|
||||||
|
steps? It's as easy as:
|
||||||
|
|
||||||
|
```
|
||||||
|
make clean install
|
||||||
|
```
|
||||||
|
|
||||||
|
This will remove any existing `result`, regenerate the site (with the new post)
|
||||||
|
under a new symlink, and install/update that newer package to my nix profile,
|
||||||
|
overwriting the previous package which was there.
|
||||||
|
|
||||||
|
And that's it! Nix is a cool tool that I'm still getting the hang of, but
|
||||||
|
hopefully this post might be useful to anyone else thinking of self-hosting
|
||||||
|
their site.
|
||||||
|
|
||||||
|
[jekyll]: https://jekyllrb.com/
|
||||||
|
[bundix]: https://github.com/nix-community/bundix
|
||||||
|
[manual]: https://nixos.org/manual/nix/stable/#chap-writing-nix-expressions
|
Loading…
Reference in New Issue
Block a user