diff --git a/.circleci/config.yml b/.circleci/config.yml
index 735831e3fce2f6b39fb0fa35b7caf8af32e51382..5a7a8f081f5207b8c318ccfcf836150fe934bfe7 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -148,7 +148,7 @@ jobs:
       # one day someone pushed a bad revision to it and our CI broke.  So now
       # we just pin some recent version.  Who would have thought a floating
       # dependency would cause build instability?
-      - image: "nixos/nix:2.3.16"
+      - image: "nixos/nix:2.5.1"
 
     # Tahoe-LAFS requires more memory than we get from the default resource
     # class and sometimes we have to build it.
@@ -158,6 +158,10 @@ jobs:
       # CACHIX_AUTH_TOKEN is manually set in the CircleCI web UI and allows us to push to CACHIX_NAME.
       CACHIX_NAME: "privatestorage-opensource"
 
+      # Let us use features marked "experimental".  For example, most/all of
+      # the `nix <subcommand>` forms.
+      NIX_CONFIG: "experimental-features = nix-command"
+
       # Pin a NixOS 21.11 revision.  Most of the software involved in the
       # build process is pinned by nix/sources.json with niv but a few things
       # need to work before we get that far.  This pin is for those things.
@@ -167,6 +171,19 @@ jobs:
       NIXPKGS: "https://github.com/NixOS/nixpkgs/archive/28abc4e43a24d28729509e2d83f5c4f3b3418189.tar.gz"
 
     steps:
+      - run:
+          # Work around a bug in the 2.5.1 Docker image that prevents it from
+          # having any CA certificates to use to validate any certificates it
+          # encounters (and thus makes it incapable of talking to our binary
+          # caches).
+          #
+          # The work-around is from a comment on the issue
+          # https://github.com/NixOS/nix/issues/5797
+          name: "Fix CA Certificates"
+          command: |
+            mkdir -p /etc/ssl/certs/
+            ln -s $NIX_SSL_CERT_FILE /etc/ssl/certs/
+
       - run:
           name: "Set up Cachix"
           command: |
diff --git a/default.nix b/default.nix
index e2b8e609769c6f559bf77fbbe28beee11ae53d58..85817ddefc528b87e8d90e42d9da04dc6a4b3f4b 100644
--- a/default.nix
+++ b/default.nix
@@ -37,6 +37,8 @@ in
     };
   in
     rec {
+      inherit pkgs mach-nix;
+
       tahoe-lafs = mach-nix.buildPythonPackage rec {
         inherit python providers;
         name = "tahoe-lafs";
diff --git a/shell.nix b/shell.nix
index 0f661ebc3692fbf6bfe199abc0cbd8fbd6feaa8e..023fc1bdb969c66f6b0d8da9d0c3b638396b96f1 100644
--- a/shell.nix
+++ b/shell.nix
@@ -1,17 +1,14 @@
+# Note: Passing arguments through here to customize the environment does not
+# work on Nix 2.3.  It works with Nix 2.5.  I'm not sure about 2.4.
+{ ... }@args:
 let
-  sources = import nix/sources.nix;
+  tests = import ./tests.nix args;
+  inherit (tests) pkgs;
 in
-{ pkgs ? import sources.release2105 {}
-, tahoe-lafs-source ? "tahoe-lafs"
-}:
-  let
-    tests = pkgs.callPackage ./tests.nix {
-      inherit tahoe-lafs-source;
-    };
-  in
-    pkgs.mkShell {
-      packages = [
-        tests.python
-        pkgs.niv
-      ];
-    }
+pkgs.mkShell {
+  buildInputs = [
+    tests.python
+    tests.lint-python
+    pkgs.niv
+  ];
+}
diff --git a/tests.nix b/tests.nix
index c985ce0f41b39c886b67788243835d2ee8605808..40412a752ecaacd918e0aad6bfab37def5f24383 100644
--- a/tests.nix
+++ b/tests.nix
@@ -1,24 +1,25 @@
 let
-  sources = import nix/sources.nix;
+  fixArgs = a: builtins.removeAttrs a [
+    # Make sure all the args tests.nix accepts but default.nix does not are
+    # listed here so we don't try to forward them to default.nix
+    "privatestorage"
+    "hypothesisProfile"
+    "collectCoverage"
+    "testSuite"
+    "trialArgs"
+  ];
 in
-{ pkgs ? import sources.release2105 {}
-, pypiData ? sources.pypi-deps-db
-, mach-nix ? import sources.mach-nix { inherit pkgs pypiData; }
-, tahoe-lafs-source ? "tahoe-lafs"
-, tahoe-lafs-repo ? sources.${tahoe-lafs-source}
-, privatestorage ? import ./. {
-    inherit pkgs pypiData mach-nix;
-    inherit tahoe-lafs-repo;
-  }
+{ privatestorage ? import ./. (fixArgs args)
 , hypothesisProfile ? null
 , collectCoverage ? false
 , testSuite ? null
 , trialArgs ? null
-,
-}:
-  let
+# accept any other arguments to be passed on to default.nix
+, ...
+}@args:
+let
+    inherit (privatestorage) pkgs mach-nix zkapauthorizer;
     inherit (pkgs) lib;
-    inherit (privatestorage) zkapauthorizer;
     hypothesisProfile' = if hypothesisProfile == null then "default" else hypothesisProfile;
     defaultTrialArgs = [ "--rterrors" ] ++ (lib.optional (! collectCoverage) "--jobs=$(($NIX_BUILD_CORES > 8 ? 8 : $NIX_BUILD_CORES))");
     trialArgs' = if trialArgs == null then defaultTrialArgs else trialArgs;
@@ -38,10 +39,11 @@ in
       requirements = ''
         isort
         black
+        flake8
       '';
     };
-  in
-    pkgs.runCommand "zkapauthorizer-tests" {
+
+    tests = pkgs.runCommand "zkapauthorizer-tests" {
       passthru = {
         inherit python;
       };
@@ -65,4 +67,8 @@ in
           cp -v .coverage.* "$out/coverage"
         ''
       }
-    ''
+    '';
+in
+{
+  inherit pkgs python lint-python tests;
+}