Use nix to generate a static site and host it on github pages.
tldr;
-
Goto the settings of your repo, select the pages tab and set Source to GitHub Actions.
-
Copy default.nix, flake.nix and .github/workflows/pages.yml to your repo.
-
Adjust the
buildPhase
andinstallPhase
in default.nix to build your site. -
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:
{ 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.
{
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.

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:
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. |