Roxy on Cup O' Go Podcast
I was on the Cup O’ Go podcast this last week! I talked about my SQLite package and the history behind it. Go check it out!
I was on the Cup O’ Go podcast this last week! I talked about my SQLite package and the history behind it. Go check it out!
I write a lot of shell scripts.
Many are one-offs or specific to a project,
but every so often,
I’ll have a script that transcends to become a part of my toolbelt.
For example, nix-op-key is a script I wrote to generate new Nix signing keys
and place them in 1Password.
It’s not a task that requires a dedicated program,
it just needs to glue two existing programs together:
nix key generate-secret and op (the 1Password CLI).
These sorts of scripts are great,
but if you want to share them with someone else
(or even just use it on a different computer),
how do you do it?
Scripts like these depend on specific programs (or maybe even specific versions) being installed
and Bash does not have a package manager like pip or the go tool.
As it turns out, Nix is such a package manager.
And with flakes, there’s built-in support for installing and running scripts
with well-specified dependencies
in a single command.
For example, you can run my nix-op-key script I mentioned earlier
(pinned to a specific version)
with:
COMMIT=25e9bd52e977cca415df84ea91028efd92d3da92
nix run "github:zombiezen/dotfiles?dir=nix&rev=$COMMIT#nix-op-key" -- --help
Furthermore, you can install the script using the nix profile install command:
nix profile install "github:zombiezen/dotfiles?dir=nix&rev=$COMMIT#nix-op-key"
(If you try this out yourself, you can uninstall the script with
nix profile remove '.*.nix-op-key').
In this blog post, I’ll show you how you can package your own shell scripts with Nix to make them more reliable and easier to share. This article assumes familiarity with Unix command line and Bash shell scripting. I’m using Nix 2.17.1. All of the source code in this post is released under the Unlicense and is available on GitHub.
I’m proud to announce that my CGo-less SQLite Go package,
zombiezen.com/go/sqlite,
has finally reached version 1.0.
This has been the culmination of almost three years of work:
I started on this project in March of 2021 as a fork of
David Crawshaw’s crawshaw.io/sqlite
to build on top of Jan Mercl’s amazing modernc.org/sqlite.
I’ve built a number of features on top of this package such as:
go fix-like tool for migrating existing code using crawshaw.io/sqliteOver this time, the project has been used in about a dozen open source projects and has over 350 stars on GitHub. I’ve successfully used it in a number of personal projects, including a personal accounting program and my Nix caching layer.
With the 1.0 release, I’m proud to call the API stable so that Go applications
can continue to build on it for their storage needs.
If you’re using zombiezen.com/go/sqlite for something interesting,
let me know about it,
and consider supporting me on GitHub.
Similar to the Jupyter kernel for Ivy I hacked up a few months ago, I’ve created a SQLite kernel for Jupyter Notebook.

Screenshot of a SQLite Visual Studio Code notebook.
Check out the demo on GitHub! (Installation is a little DIY if you’re not using Nix, but there are instructions in the README on how to build.) Read on if you’re interested in how it works.
I’ve been writing about Nix for a few years now, and it has become a staple for all my personal projects. It solves the thorny problem of setting up reproducible development environments in a flexible and general way, while still allowing me to use my tooling the way I want to. I no longer have to worry about my GitHub Actions having different versions of tools from my local dev environment, which is a huge relief.
I’ve started making my CI jobs use nix flake check,
which lets me write and run my CI checks using Nix syntax,
further removing any differences between local development and CI.
However, I sometimes have tests that want to use the network,
which usually isn’t allowed.
I recently discovered that you can use __impure = true; to remove the networking sandbox:1
# flake.nix
{
inputs = {
nixpkgs.url = "nixpkgs";
};
outputs = { nixpkgs, ... }: {
checks.x86_64-linux.foo =
let
pkgs = import nixpkgs { system = "x86_64-linux"; };
in pkgs.stdenvNoCC.mkDerivation {
name = "foo-check";
src = ./.;
__impure = true;
nativeBuildInputs = [
pkgs.cacert
pkgs.curl
];
buildPhase = ''
runHook preBuild
curl -fsSL https://example.com/ > /dev/null
runHook postBuild
'';
installPhase = ''
runHook preInstall
touch "$out"
runHook postInstall
'';
};
};
}
For this to work, you must also set extra-experimental-features = impure-derivations ca-derivations in /etc/nix/nix.conf.2
Just passing a command-line argument doesn’t seem to work in my usage
with Nix 2.13.3 in a multi-user installation.
Since this feature is still experimental, it’s not widely advertised or documented. Hopefully this helps you use it for your own tests.