Nix and updated templates

Cara Salter 7 months ago
parent a610350e7e
commit d6126294bf
  1. 1
  2. 57
  3. 18
  4. 16
  5. 10
  6. 50
  7. 174
  8. 16
  9. 3
  10. 4
  11. 43
  12. 14

@ -0,0 +1 @@
eval "$(lorri direnv)"

@ -0,0 +1,57 @@
title: NixOS Part 1
date: 2022-02-22
Recently, I switched both of my primary laptops from Arch (cesium/vulcan) and
Windows (carbon) to NixOS, mostly on a whim. Some friends of mine have been
encouraging me to try it out for a while, and I did so over the winter break on
Carbon, but I couldn't get flakes to work properly, so I abandoned it and put
Windows on it. What I needed from carbon was for it to work as a notetaking
tablet, and Windows came with OneNote so it was easy to get set up.
Ever since, NixOS has been in the back of my mind. The idea of a system
configuration tracked in Git that I can use on clients and servers intrigued me
and I wanted to see how I could use that in my systems administration.
# First Steps
The first thing I did was talk with my friends who were trying to get me to use
NixOS in the first place. They recommended that I go with setting up my flake
immediately, instead of trying to merge my existing `configuration.nix` into a
flake later. This turned out to be the right move, and I'm now tracking my
system configuration at [muirrum/nix]( This
has led to me being able to share a baseline configuration across both carbon
and cesium, including my user configuration and the packages I expect to have
(including neovim, zsh, firefox, and my custom fork of dwm).
# Encapsulate and Unif~~i~~y
Everything else I'm planning to split into modules, for both my user
configuration and my system configuration. I've already started this with
`nixos/modules/*.nix` and `home/modules/mail.nix` which set up system modules
like Steam, Darktable, and virtualization, as well as my mail sync systemd
service. That way, I can enable the things I need per-system, while still
maintaining the ability to centrally manage it. Now I can add
`./nixos/modules/steam.nix` to my system configuration and I get *my* Steam
setup on every system, every time. It's the same with Darktable, libvirtd, or
`mbsync`. Getting a unified system configuration is as simple as
`nixos-rebuild switch` in my flake directory. I'm planning on rolling this out
to my servers slowly, starting with my physical server during the next break.
# Packaging
NixOS is based on the Nix package manager, which allows developers to describe
exactly which versions of which packages should be built to make their app work
every time. I've been using this to package my bots and configure their
development environments so I don't have those tools polluting my `$PATH`
outside of the directories where I intend to work on them. I have one of my bots
set up to automatically build a small Docker image for me, so that I can quickly
push it up to my private registry.
# Conclusion
I plan to keep using NixOS for all my devices. I've found it fun to tinker with,
especially since it keeps a backup of previous versions of your system, so that
if you mess something up you can just reboot and choose a different one. I
haven't needed that *yet* but I'm sure it's coming soon, knowing how much I like
to mess with things that shouldn't be messed with.
I'll probably write about my experience getting NixOS set up on my home server
in another post.

@ -0,0 +1,18 @@
title: Wireguard Site-to-Site VPN
date: 2022-02-15
draft: true
Hi all! Recently, I was inspired by [this post][xepost] to make my own Wireguard
VPN between my laptop and servers. That post is super old though, so I wanted to
write up what I changed and added.
# Initial Setup
I chose my dedicated Debian host as the Wireguard server. So far in its
lifetime, it's been gathering all the miscellaneous infrastructure services like
Prometheus, so there's not much happening on it

@ -0,0 +1,16 @@
{ sources ? import ./nix/sources.nix, pkgs ? import sources.nixpkgs { } }:
rust = import ./nix/rust.nix { inherit sources; };
naersk = pkgs.callPackage sources.naersk {
rustc = rust;
cargo = rust;
src = builtins.filterSource (path: type: type != "directory" ||
builtins.baseNameOf path != "target") ./.;
in naersk.buildPackage {
inherit src;
remapPathPrefix = true;

@ -0,0 +1,10 @@
{ sources ? import ./sources.nix }:
pkgs =
import sources.nixpkgs { overlays = [ (import sources.nixpkgs-mozilla) ]; };
channel = "nightly";
date = "2022-02-16";
targets = [ ];
chan = pkgs.rustChannelOfTargets channel date targets;
in chan

@ -0,0 +1,50 @@
"naersk": {
"branch": "master",
"description": "Build rust crates in Nix. No configuration, no code generation, no IFD. Sandbox friendly. [maintainer: ???]",
"homepage": "",
"owner": "nmattia",
"repo": "naersk",
"rev": "2fc8ce9d3c025d59fee349c1f80be9785049d653",
"sha256": "1jhagazh69w7jfbrchhdss54salxc66ap1a1yd7xasc92vr0qsx4",
"type": "tarball",
"url": "",
"url_template": "<owner>/<repo>/archive/<rev>.tar.gz"
"niv": {
"branch": "master",
"description": "Easy dependency management for Nix projects",
"homepage": "",
"owner": "nmattia",
"repo": "niv",
"rev": "9cb7ef336bb71fd1ca84fc7f2dff15ef4b033f2a",
"sha256": "1ajyqr8zka1zlb25jx1v4xys3zqmdy3prbm1vxlid6ah27a8qnzh",
"type": "tarball",
"url": "",
"url_template": "<owner>/<repo>/archive/<rev>.tar.gz"
"nixpkgs": {
"branch": "release-20.03",
"description": "Nix Packages collection",
"homepage": "",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "eb73405ecceb1dc505b7cbbd234f8f94165e2696",
"sha256": "06k21wbyhhvq2f1xczszh3c2934p0m02by3l2ixvd6nkwrqklax7",
"type": "tarball",
"url": "",
"url_template": "<owner>/<repo>/archive/<rev>.tar.gz"
"nixpkgs-mozilla": {
"branch": "master",
"description": "Mozilla overlay for Nixpkgs.",
"homepage": "",
"owner": "mozilla",
"repo": "nixpkgs-mozilla",
"rev": "f233fdc4ff6ba2ffeb1e3e3cd6d63bb1297d6996",
"sha256": "1rzz03h0b38l5sg61rmfvzpbmbd5fn2jsi1ccvq22rb76s1nbh8i",
"type": "tarball",
"url": "",
"url_template": "<owner>/<repo>/archive/<rev>.tar.gz"

@ -0,0 +1,174 @@
# This file has been generated by Niv.
# The fetchers. fetch_<type> fetches specs of type <type>.
fetch_file = pkgs: name: spec:
name' = sanitizeName name + "-src";
if spec.builtin or true then
builtins_fetchurl { inherit (spec) url sha256; name = name'; }
pkgs.fetchurl { inherit (spec) url sha256; name = name'; };
fetch_tarball = pkgs: name: spec:
name' = sanitizeName name + "-src";
if spec.builtin or true then
builtins_fetchTarball { name = name'; inherit (spec) url sha256; }
pkgs.fetchzip { name = name'; inherit (spec) url sha256; };
fetch_git = name: spec:
ref =
if spec ? ref then spec.ref else
if spec ? branch then "refs/heads/${spec.branch}" else
if spec ? tag then "refs/tags/${spec.tag}" else
abort "In git source '${name}': Please specify `ref`, `tag` or `branch`!";
builtins.fetchGit { url = spec.repo; inherit (spec) rev; inherit ref; };
fetch_local = spec: spec.path;
fetch_builtin-tarball = name: throw
''[${name}] The niv type "builtin-tarball" is deprecated. You should instead use `builtin = true`.
$ niv modify ${name} -a type=tarball -a builtin=true'';
fetch_builtin-url = name: throw
''[${name}] The niv type "builtin-url" will soon be deprecated. You should instead use `builtin = true`.
$ niv modify ${name} -a type=file -a builtin=true'';
# Various helpers
sanitizeName = name:
concatMapStrings (s: if builtins.isList s then "-" else s)
builtins.split "[^[:alnum:]+._?=-]+"
((x: builtins.elemAt (builtins.match "\\.*(.*)" x) 0) name)
# The set of packages used when specs are fetched using non-builtins.
mkPkgs = sources: system:
sourcesNixpkgs =
import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) { inherit system; };
hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath;
hasThisAsNixpkgsPath = <nixpkgs> == ./.;
if builtins.hasAttr "nixpkgs" sources
then sourcesNixpkgs
else if hasNixpkgsPath && ! hasThisAsNixpkgsPath then
import <nixpkgs> {}
Please specify either <nixpkgs> (through -I or NIX_PATH=nixpkgs=...) or
add a package called "nixpkgs" to your sources.json.
# The actual fetching function.
fetch = pkgs: name: spec:
if ! builtins.hasAttr "type" spec then
abort "ERROR: niv spec ${name} does not have a 'type' attribute"
else if spec.type == "file" then fetch_file pkgs name spec
else if spec.type == "tarball" then fetch_tarball pkgs name spec
else if spec.type == "git" then fetch_git name spec
else if spec.type == "local" then fetch_local spec
else if spec.type == "builtin-tarball" then fetch_builtin-tarball name
else if spec.type == "builtin-url" then fetch_builtin-url name
abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}";
# If the environment variable NIV_OVERRIDE_${name} is set, then use
# the path directly as opposed to the fetched source.
replace = name: drv:
saneName = stringAsChars (c: if isNull (builtins.match "[a-zA-Z0-9]" c) then "_" else c) name;
ersatz = builtins.getEnv "NIV_OVERRIDE_${saneName}";
if ersatz == "" then drv else
# this turns the string into an actual Nix path (for both absolute and
# relative paths)
if builtins.substring 0 1 ersatz == "/" then /. + ersatz else /. + builtins.getEnv "PWD" + "/${ersatz}";
# Ports of functions for older nix versions
# a Nix version of mapAttrs if the built-in doesn't exist
mapAttrs = builtins.mapAttrs or (
f: set: with builtins;
listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set))
range = first: last: if first > last then [] else builtins.genList (n: first + n) (last - first + 1);
stringToCharacters = s: map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1));
stringAsChars = f: s: concatStrings (map f (stringToCharacters s));
concatMapStrings = f: list: concatStrings (map f list);
concatStrings = builtins.concatStringsSep "";
optionalAttrs = cond: as: if cond then as else {};
# fetchTarball version that is compatible between all the versions of Nix
builtins_fetchTarball = { url, name ? null, sha256 }@attrs:
inherit (builtins) lessThan nixVersion fetchTarball;
if lessThan nixVersion "1.12" then
fetchTarball ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
fetchTarball attrs;
# fetchurl version that is compatible between all the versions of Nix
builtins_fetchurl = { url, name ? null, sha256 }@attrs:
inherit (builtins) lessThan nixVersion fetchurl;
if lessThan nixVersion "1.12" then
fetchurl ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
fetchurl attrs;
# Create the final "sources" from the config
mkSources = config:
mapAttrs (
name: spec:
if builtins.hasAttr "outPath" spec
then abort
"The values in sources.json should not have an 'outPath' attribute"
spec // { outPath = replace name (fetch config.pkgs name spec); }
) config.sources;
# The "config" used by the fetchers
mkConfig =
{ sourcesFile ? if builtins.pathExists ./sources.json then ./sources.json else null
, sources ? if isNull sourcesFile then {} else builtins.fromJSON (builtins.readFile sourcesFile)
, system ? builtins.currentSystem
, pkgs ? mkPkgs sources system
}: rec {
# The sources, i.e. the attribute set of spec name to spec
inherit sources;
# The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers
inherit pkgs;
mkSources (mkConfig {}) // { __functor = _: settings: mkSources (mkConfig settings); }

@ -0,0 +1,16 @@
{ pkgs ? import <nixpkgs> {} }:
sources = import ./nix/sources.nix;
pkgs = import sources.nixpkgs {};
rust = import ./nix/rust.nix { inherit sources; };
pkgs.mkShell {
buildInputs = [
# keep this line if you use bash

@ -25,6 +25,7 @@ async fn main() -> Result<()> {
let state = Arc::new(internal::init().await?);
let index = warp::get().and(path::end().and_then(misc::handlers::index));
let about = warp::path!("about").and_then(misc::handlers::about);
let blog_index = warp::path!("blog")
@ -35,7 +36,7 @@ async fn main() -> Result<()> {
let static_files = warp::path("static").and(warp::fs::dir("./statics"));
let site = index
let site = index.or(about)

@ -6,4 +6,8 @@ pub mod handlers {
pub async fn index() -> Result<impl Reply, Rejection> {
Response::builder().html(|o| templates::index_html(o))
pub async fn about() -> Result<impl Reply, Rejection> {
Response::builder().html(|o| templates::about_html(o))

@ -0,0 +1,43 @@
@use super::{header_html, footer_html};
@:header_html(None, None)
<div class="two-column">
<div class="inner-column">
<p>The best way to reach me is via email: [my name] [at] [this site]. I
try to respond as soon as I can but please understand that I am a
college student who is also busy with maintaining her own systems that
other people depend on.</p>
<div class="inner-column">
<h3>Social Media</h3>
<li>Mastodon: <a
<li>GitHub: <a href="">Muirrum</a></li>
<li>SourceHut: <a href="">~muirrum</a></li>
<li>Personal Gitea: <a
<h1>Selected Projects</h1>
<div class="two-column">
<div class="inner-column">
<h3>Campmaster-Constantine (Discontinued)</h3>
<p>Discord bot written in Rust, then Python. Discontinued after was retired.</p>
<div class="inner-column">
<p>Enables automatic provisioning of new peers across a Wireguard
network based on a management server.</p>

@ -28,7 +28,19 @@
Among other things. <br/><br/>
I am currently pursuing a Bachelors degree in Computer Science at
Worcester Polytechnic Institute.
Worcester Polytechnic Institute.<br/><br/>
My past projects are, in no particular order:
<li><a href="">WG-manager</li>
<li><a href="">LNL DB</a></li>
<div class="inner-column">