diff --git a/morph/grid/production/grid.nix b/morph/grid/production/grid.nix
index 106f6729fd0f5ef072ade454f88826b1fa396e49..b2a4436325cdde21aa1f6e56f3fe8d0f54484081 100644
--- a/morph/grid/production/grid.nix
+++ b/morph/grid/production/grid.nix
@@ -38,20 +38,7 @@ in lib.make-grid {
         "storage005"
       ];
 
-    in {
-    # Here are the hosts that are in this morph network.  This is sort of like
-    # a server manifest.  We try to keep as many of the specific details as
-    # possible out of *this* file so that this file only grows as server count
-    # grows.  If it grows too much, we can load servers by listing contents of
-    # a directory or reading from another JSON file or some such.  For now,
-    # I'm just manually maintaining these entries.
-    #
-    # The name on the left of the `=` is mostly irrelevant but it does provide
-    # a default hostname for the server if the configuration on the right side
-    # doesn't specify one.
-    #
-    # The names must be unique!
-    "payments.privatestorage.io" = rec {
+    "payments.privatestorage.io" = {
       imports = [
         lib.issuer
         lib.hardware-aws
@@ -59,76 +46,49 @@ in lib.make-grid {
       ];
     };
 
-    "storage001" = let nodecfg = import ./storage001-config.nix; in {
-      imports = [
-        ./storage001-hardware.nix
-        # Slightly awkwardly, enable some of our hardware / network / bootloader options.
-        ../../../nixos/modules/100tb.nix
-        lib.storage
-        (lib.customize-storage cfg sshUsers nodecfg.publicIPv4 monitoringvpnKeyDir "172.23.23.21" "19.09")
-      ];
-      # And supply configuration for those hardware / network / bootloader options.
-      "100tb".config = nodecfg;
-    };
+    "monitoring" = lib.make-monitoring (cfg // {
+      publicIPv4 = "monitoring.private.storage";
+      monitoringvpnIPv4 = "172.23.23.1";
+      inherit monitoringvpnKeyDir;
+      inherit vpnClientIPs;
+      inherit hostsMap;
+      inherit nodeExporterTargets;
+      hardware = lib.hardware-aws;
+      stateVersion = "19.09";
+      inherit sshUsers;
+    });
 
-    "storage002" = let nodecfg = import ./storage002-config.nix; in {
+    defineStorageNode = name: { vpnIP, stateVersion }: let nodecfg = import "${./.}/${name}-config.nix"; in {
       imports = [
-        ./storage002-hardware.nix
-        # Slightly awkwardly, enable some of our hardware / network / bootloader options.
-        ../../../nixos/modules/100tb.nix
-        lib.storage
-        (lib.customize-storage cfg sshUsers nodecfg.publicIPv4 monitoringvpnKeyDir "172.23.23.22" "19.09")
-      ];
-      # And supply configuration for those hardware / network / bootloader options.
-      "100tb".config = nodecfg;
-    };
+        # Get some of the very lowest-level system configuration for this
+        # node.  This isn't all *completely* hardware related.  Maybe some
+        # more factoring is in order, someday.
+        "${./.}/${name}-hardware.nix"
 
-    "storage003" = let nodecfg = import ./storage003-config.nix; in {
-      imports = [
-        ./storage003-hardware.nix
         # Slightly awkwardly, enable some of our hardware / network / bootloader options.
         ../../../nixos/modules/100tb.nix
-        lib.storage
-        (lib.customize-storage cfg sshUsers nodecfg.publicIPv4 monitoringvpnKeyDir "172.23.23.23" "19.09")
-      ];
-      # And supply configuration for those hardware / network / bootloader options.
-      "100tb".config = nodecfg;
-    };
 
-    "storage004" = let nodecfg = import ./storage004-config.nix; in {
-      imports = [
-        ./storage004-hardware.nix
-        # Slightly awkwardly, enable some of our hardware / network / bootloader options.
-        ../../../nixos/modules/100tb.nix
+        # Get all of the configuration that is common across all storage nodes.
         lib.storage
-        (lib.customize-storage cfg sshUsers nodecfg.publicIPv4 monitoringvpnKeyDir "172.23.23.24" "19.09")
+
+        # Then customize the storage system a little bit based on this node's particulars.
+        (lib.customize-storage cfg sshUsers nodecfg.publicIPv4 monitoringvpnKeyDir vpnIP stateVersion)
       ];
+
       # And supply configuration for those hardware / network / bootloader options.
       "100tb".config = nodecfg;
     };
 
-    "storage005" = let nodecfg = import ./storage005-config.nix; in {
-      imports = [
-        ./storage005-hardware.nix
-        # Slightly awkwardly, enable some of our hardware / network / bootloader options.
-        ../../../nixos/modules/100tb.nix
-        lib.storage
-        (lib.customize-storage cfg sshUsers nodecfg.publicIPv4 monitoringvpnKeyDir "172.23.23.25" "19.03")
-      ];
-      # And supply configuration for those hardware / network / bootloader options.
-      "100tb".config = nodecfg;
+    # Define all of the storage nodes for this grid.
+    storageNodes = builtins.mapAttrs defineStorageNode {
+      storage001 = { vpnIP = "172.23.23.21"; stateVersion = "19.09"; };
+      storage002 = { vpnIP = "172.23.23.22"; stateVersion = "19.09"; };
+      storage003 = { vpnIP = "172.23.23.23"; stateVersion = "19.09"; };
+      storage004 = { vpnIP = "172.23.23.24"; stateVersion = "19.09"; };
+      storage005 = { vpnIP = "172.23.23.25"; stateVersion = "19.03"; };
     };
 
-    "monitoring" = lib.make-monitoring (cfg // {
-      publicIPv4 = "monitoring.private.storage";
-      monitoringvpnIPv4 = "172.23.23.1";
-      inherit monitoringvpnKeyDir;
-      inherit vpnClientIPs;
-      inherit hostsMap;
-      inherit nodeExporterTargets;
-      hardware = lib.hardware-aws;
-      stateVersion = "19.09";
-      inherit sshUsers;
-    });
-  };
+    in {
+      inherit "payments.privatestorage.io" "monitoring";
+    } // storageNodes;
 }