View me on GitHub

Use nix to generate a static site and host it on github pages.

tldr;

  1. Goto the settings of your repo, select the pages tab and set Source to GitHub Actions.

  2. Copy default.nix, flake.nix and .github/workflows/pages.yml to your repo.

  3. Adjust the buildPhase and installPhase in default.nix to build your site.

  4. Commit and push to github.

Your site is available at https://your-github-username.github.io/your-repo-name/ after the Deploy to Pages action is done (~1 min).

Detailed instructions

Building with nix

First you need a nix derivation that builds the root of your page. In this example we will look at the derivation for building this page:

default.nix
{ pkgs ? import <nixpkgs> { } }:
with pkgs; stdenv.mkDerivation {
  name = "pages";
  src = ./.;

  nativeBuildInputs = [
    asciidoctor
  ];

  buildPhase = ''
    asciidoctor --attribute reproducible="true" README.adoc -o index.html
  '';

  installPhase = ''
    mkdir -p $out
    cp index.html $out
    cp screenshot.webp $out
  '';
}

In it the dependencies required to build the page are defined, in this case only asciidoctor. In the buildPhase we execute some commands to generate our html files. In the installPhase we copy the files we need to the output at $out. $out will be the root of our page.

We also have a nix flake to serve as an entrypoint to the derivation. It also contains a script to build and preview your website locally.

flake.nix
{
  inputs = {
    nixpkgs.url = "nixpkgs/nixos-22.11";
    flake-utils.url = "github:numtide/flake-utils";
  };

  outputs = { self, nixpkgs, flake-utils }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = nixpkgs.legacyPackages.${system};
      in
      rec {
        name = "pages";
        packages.pages = import ./default.nix { pkgs = pkgs; };
        packages.default = packages.pages;
        apps.default = flake-utils.lib.mkApp
          {
            drv = pkgs.writeShellScriptBin "pages" "${pkgs.python3}/bin/python3 -m http.server 8000 -d ${packages.pages}";
          };

      }
    );
}

You can copy these files to your repository and adjust the build process in default.nix for your project. You don’t need to modify flake.nix.

By executing nix run . you can start a local preview of your page on localhost:8000.

Deploying to github pages

To setup deployment to github pages you need to go to your repository settings, then to the pages tab, and set Source to GitHub Actions.

screenshot
Figure 1. It should look similar to this

That should be all the configuration you need to do in github. The last step is to add a github action to deploy your website on every push to master or main.

To do that you just need to copy the following file to your repo:

.github/workflows/pages.yml
name: Deploy to Pages

# Runs on pushes targeting things that look like the default branch
on:
  push:
    branches: ["main", "master"]
  workflow_dispatch:

# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
  contents: read
  pages: write
  id-token: write

concurrency:
  group: "pages"
  cancel-in-progress: true

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Install Nix
        uses: nixbuild/nix-quick-install-action@v21
        with:
          nix_conf: experimental-features = nix-command flakes
      - name: Build site
        run: nix build .#pages --print-build-logs
      - name: Adjust permissions
        run: |
          chown -R `id -u`:`id -g` ./result
          chmod -R a+rwx ./result
      - name: Upload artifact
        uses: actions/upload-pages-artifact@v1
        with:
          path: ./result
  deploy:
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    needs: build
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v1

When you commit and push your files the action should be triggered and deploy to github pages. You can now view your page at https://your-github-username.github.io/your-repo-name/

EXTRA: Use your own domain

You can use a custom domain instead of username.github.io. In this example we will configure github pages to work with the base of your naked domain and the www subdomain. To prepare your domain you need to add the following DNS records to your domain:

Note

You need to replace your-github-username in the CNAME record with your actual username.

Note

The TXT record is required to verify your domain ownership with github. You can get the values you need to set here in your github settings.

Type Host Value

A

@

185.199.108.153

A

@

185.199.109.153

A

@

185.199.110.153

A

@

185.199.111.153

AAAA

@

2606:50c0:8000::153

AAAA

@

2606:50c0:8001::153

AAAA

@

2606:50c0:8002::153

AAAA

@

2606:50c0:8003::153

CNAME

www

your-github-username.github.io

TXT

You can get the host and value you need to set here in your github settings.

After you set the DNS entries you should first make sure, that your domain is verified with github now. You can go to the page where you got the values for the TXT record and check the verification status. If it is not verified yet click on the three dots, select Continue verifying and then click Verify again.

After your domain is verified you can configure it for your repository. Go to the settings of your repo, select the pages tab and set Custom domain to your naked domain (like example.com). Hit Save and wait for the DNS check to succeed. If it fails wait a few minutes and try again, the DNS entries may have not been updated yet. After the check succeeded you need to set the Custom domain to the www subdomain (like www.example.com). Hit save again and wait for the check to succeed. Now you can set the Custom domain back to the naked domain hit save one more time and you are done.

Note

We set Custom domain multiple times, because github redirects all domains that have been set at some point in the past to the current one.