diff --git a/default.nix b/default.nix
index 18dba97f1f4b09fa44b7432035b43d7402f99274..48bdab384f036dc2a0d06a880d3ed9e6cc92506c 100644
--- a/default.nix
+++ b/default.nix
@@ -1,21 +1,9 @@
 let
   sources = import nix/sources.nix;
-
-  # nixpkgs 21.11 packages a version of pkgconfig that is broken on Python 2.7
-  # so supply our own.  mach-nix depends on this to set up its own build
-  # environment and cannot discover a working version from pypi the way it
-  # works for other dependencies.
-  fixPkgconfig = self: super: {
-    python27 = super.python27.override {
-      packageOverrides = python-self: python-super: {
-        pkgconfig = python-super.pythonPackages.callPackage ./pkgconfig.nix {};
-      };
-    };
-  };
 in
-{ pkgs ? import sources.release2111 { overlays = [ fixPkgconfig ]; }
+{ pkgs ? import sources.release2111 { }
 , pypiData ? sources.pypi-deps-db
-, python ? "python27"
+, python ? "python39"
 , mach-nix ? import sources.mach-nix { inherit pkgs pypiData python; }
 , tahoe-lafs-source ? "tahoe-lafs"
 , tahoe-lafs-repo ? sources.${tahoe-lafs-source}
@@ -83,18 +71,12 @@ in
         version = "1.17.0.post999";
         # See https://github.com/DavHau/mach-nix/issues/190
         requirementsExtra =
-          let
-            foolscap-version =
-              if python <= "python30"
-              then "foolscap == 0.13.1"
-              else "foolscap >= 21.7.0";
-          in
-            ''
+          ''
           # See https://github.com/DavHau/mach-nix/issues/190
           pyrsistent < 0.17
           configparser
           eliot
-          ${foolscap-version}
+          foolscap >= 21.7.0
 
           # undetected cryptography build dependency
           # https://github.com/DavHau/mach-nix/issues/305
@@ -102,7 +84,7 @@ in
           # undetected tomli build dependency
           # probably same underlying cause as cryptography issue
           flit_core
-        '';
+          '';
         postPatch = ''
           cat > src/allmydata/_version.py <<EOF
           # This _version.py is generated by nix.
diff --git a/shell.nix b/shell.nix
index 9388b7353038ee1c1311a1a9d40027d7d4419692..c7ed13786f4d7d394237bcf99009423c2b22c639 100644
--- a/shell.nix
+++ b/shell.nix
@@ -2,14 +2,12 @@
 # work on Nix 2.3.  It works with Nix 2.5.  I'm not sure about 2.4.
 { ... }@args:
 let
-  privatestorage = import ./. args;
+  tests = import ./tests.nix args;
+  inherit (tests) privatestorage lint-python;
   inherit (privatestorage) pkgs mach-nix tahoe-lafs zkapauthorizer;
 
-  pythonVersion = zkapauthorizer.meta.mach-nix.python;
-
-  python = mach-nix.mkPython {
-    inherit (zkapauthorizer.meta.mach-nix) providers;
-    python = pythonVersion;
+  python-env = mach-nix.mkPython {
+    inherit (zkapauthorizer.meta.mach-nix) python providers;
     overridesPre = [
       (
         self: super: {
@@ -17,40 +15,22 @@ let
         }
       )
     ];
-
-    requirements = let
-      py3 = pythonVersion > "python3";
-      lint = pkgs.lib.optionalString (builtins.trace py3 py3) ''
-# lint
-black
-isort
-flake8
-'';
-      workarounds = ''
-# Mitigate for undetected cryptography dependency
-setuptools_rust
-# And for tomli
-flit_core
-'';
-      testing = ''
-coverage
-fixtures
-testtools
-hypothesis
-'';
-    in
+    requirements =
       ''
-${lint}
-${workarounds}
-${testing}
-${zkapauthorizer.requirements}
-'';
+      ${builtins.readFile ./requirements/test.in}
+      ${zkapauthorizer.requirements}
+      '';
   };
 in
 pkgs.mkShell {
+  # Avoid leaving .pyc all over the source tree when manually triggering tests
+  # runs.
   PYTHONDONTWRITEBYTECODE = "1";
 
   buildInputs = [
-    python
+    # Provide the linting tools for interactive usage.
+    lint-python
+    # Supply all of the runtime and testing dependencies.
+    python-env
   ];
 }
diff --git a/tests.nix b/tests.nix
index f51d5727f55ec963d344390f54f874b12e98a7f5..0d7f6a7750c73da64c8f4619503394234497d3f9 100644
--- a/tests.nix
+++ b/tests.nix
@@ -70,5 +70,5 @@ let
     '';
 in
 {
-  inherit pkgs python lint-python tests;
+  inherit privatestorage lint-python tests;
 }