diff --git a/morph/grid/local/grid.nix b/morph/grid/local/grid.nix
index c686cdd2582a659c0feef7440f815a752174cdaf..96a61edf5e4286556a0dd6a15f614fe62a30ee02 100644
--- a/morph/grid/local/grid.nix
+++ b/morph/grid/local/grid.nix
@@ -71,12 +71,14 @@ let
   payments = {
     imports = [
       gridlib.issuer
-      (gridlib.customize-issuer grid-config)
       grid-module
     ];
     config = {
       grid.monitoringvpnIPv4 = "172.23.23.11";
       grid.publicIPv4 = "192.168.67.21";
+      grid.issuer = {
+        inherit (grid-config) letsEncryptAdminEmail issuerDomains allowedChargeOrigins;
+      };
     };
   };
 
diff --git a/morph/grid/production/grid.nix b/morph/grid/production/grid.nix
index 131978dc437d52dd3dedb93b8c7a8888e7fe72e6..eaeba677f44ff3a6373950c0b615caff64fa0911 100644
--- a/morph/grid/production/grid.nix
+++ b/morph/grid/production/grid.nix
@@ -34,11 +34,13 @@ let
     imports = [
       gridlib.issuer
       gridlib.hardware-aws
-      (gridlib.customize-issuer grid-config)
       grid-module
     ];
     config = {
       grid.monitoringvpnIPv4 = "172.23.23.11";
+      grid.issuer = {
+        inherit (grid-config) letsEncryptAdminEmail issuerDomains allowedChargeOrigins;
+      };
     };
   };
 
diff --git a/morph/grid/testing/grid.nix b/morph/grid/testing/grid.nix
index a2d844a26f9bd0acc3b279d8d630b0108bc1f39b..a940b6716a710c692b8027dafa64bcd0fbc2bc97 100644
--- a/morph/grid/testing/grid.nix
+++ b/morph/grid/testing/grid.nix
@@ -34,11 +34,13 @@ let
     imports = [
       gridlib.issuer
       gridlib.hardware-aws
-      (gridlib.customize-issuer grid-config)
       grid-module
     ];
     config = {
       grid.monitoringvpnIPv4 = "172.23.23.11";
+      grid.issuer = {
+        inherit (grid-config) letsEncryptAdminEmail issuerDomains allowedChargeOrigins;
+      };
     };
   };
 
diff --git a/morph/lib/customize-issuer.nix b/morph/lib/customize-issuer.nix
deleted file mode 100644
index 5a34db1ac4aa1950275404fd45154e255bcc0c42..0000000000000000000000000000000000000000
--- a/morph/lib/customize-issuer.nix
+++ /dev/null
@@ -1,25 +0,0 @@
-# Define a function which returns a value which fills in all the holes left by
-# ``issuer.nix``.
-{
-  # A string giving an email address to use for Let's Encrypt registration and
-  # certificate issuance.
-  letsEncryptAdminEmail
-
-  # A list of strings giving the domain names that point at this issuer
-  # system.  These will all be included in Let's Encrypt certificate.
-, issuerDomains
-
-  # A list of strings giving CORS Origins will the issuer will be configured
-  # to allow.
-, allowedChargeOrigins
-, ...
-}:
-{ config, ... }:
-{
-  services.private-storage-issuer = {
-    inherit letsEncryptAdminEmail allowedChargeOrigins;
-    domains = issuerDomains;
-  };
-
-  system.stateVersion = "19.03";
-}
diff --git a/morph/lib/customize-monitoring.nix b/morph/lib/customize-monitoring.nix
index a8f96f2d7e11473c707b44dba1b923ad92e11799..67544de5bab466fab0927b71b493ff81935192e9 100644
--- a/morph/lib/customize-monitoring.nix
+++ b/morph/lib/customize-monitoring.nix
@@ -8,8 +8,12 @@
   # allows Grafana to show us hostnames instead of VPN IP addresses.
   hostsMap
 
-  # See ``customize-issuer.nix``.
+  # A string giving an email address to use for Let's Encrypt registration and
+  # certificate issuance.
 , letsEncryptAdminEmail
+
+  # A list of strings giving the domain names that point at this monitoring
+  # system.  These will all be included in Let's Encrypt certificate.
 , monitoringDomains
 
   # A list of VPN IP addresses as strings indicating which clients will be
diff --git a/morph/lib/default.nix b/morph/lib/default.nix
index a820cc559b6b2da78c06bcb84282e392c3a1ebc7..ca1ac9631a1eeb4cc98ac3660c837de5876f2524 100644
--- a/morph/lib/default.nix
+++ b/morph/lib/default.nix
@@ -8,7 +8,6 @@
   hardware-vagrant = import ./hardware-vagrant.nix;
 
   issuer = import ./issuer.nix;
-  customize-issuer = import ./customize-issuer.nix;
 
   storage = import ./storage.nix;
   customize-storage = import ./customize-storage.nix;
diff --git a/morph/lib/issuer.nix b/morph/lib/issuer.nix
index 5390f9e12ba978d20869cc735f9c5b0a217afdd0..b2d48c2cee8cb914d7c3c9acedfcaf9ad2997178 100644
--- a/morph/lib/issuer.nix
+++ b/morph/lib/issuer.nix
@@ -1,70 +1,98 @@
-# This, along with `customize-issuer.nix, contains all of the NixOS system
-# configuration necessary to specify an "issuer"-type system.  Originally, this
-# file has all the static configuration, and `customize-issuer.nix` was a function
-# that filled in the holes. We are in the process of merging the modules, using settings
-# instead of function arguments.
-# See https://whetstone.privatestorage.io/privatestorage/PrivateStorageio/-/issues/80
-{ config, ...}:
+# This contains all of the NixOS system configuration necessary to specify an
+# "issuer"-type system.
+{ lib, config, ...}:
 let
   inherit (config.grid) publicKeyPath privateKeyPath monitoringvpnEndpoint monitoringvpnIPv4;
+  inherit (config.grid.issuer) letsEncryptAdminEmail issuerDomains allowedChargeOrigins;
 in {
-  deployment = {
-    secrets = {
-      "ristretto-signing-key" = {
-        destination = "/run/keys/ristretto.signing-key";
-        source = "${privateKeyPath}/ristretto.signing-key";
-        owner.user = "zkapissuer";
-        owner.group = "zkapissuer";
-        permissions = "0400";
-        action = ["sudo" "systemctl" "restart" "zkapissuer.service"];
-      };
-      "stripe-secret-key" = {
-        destination = "/run/keys/stripe.secret-key";
-        source = "${privateKeyPath}/stripe.secret";
-        owner.user = "zkapissuer";
-        owner.group = "zkapissuer";
-        permissions = "0400";
-        action = ["sudo" "systemctl" "restart" "zkapissuer.service"];
-      };
-
-      "monitoringvpn-secret-key" = {
-        destination = "/run/keys/monitoringvpn/client.key";
-        source = "${privateKeyPath}/monitoringvpn/${monitoringvpnIPv4}.key";
-        owner.user = "root";
-        owner.group = "root";
-        permissions = "0400";
-        action = ["sudo" "systemctl" "restart" "wireguard-monitoringvpn.service"];
-      };
-      "monitoringvpn-preshared-key" = {
-        destination = "/run/keys/monitoringvpn/preshared.key";
-        source = "${privateKeyPath}/monitoringvpn/preshared.key";
-        owner.user = "root";
-        owner.group = "root";
-        permissions = "0400";
-        action = ["sudo" "systemctl" "restart" "wireguard-monitoringvpn.service"];
-      };
-    };
-  };
-
   imports = [
     ../../nixos/modules/monitoring/vpn/client.nix
     ../../nixos/modules/monitoring/exporters/node.nix
   ];
 
-  services.private-storage-issuer = {
-    enable = true;
-    tls = true;
-    ristrettoSigningKeyPath = config.deployment.secrets.ristretto-signing-key.destination;
-    stripeSecretKeyPath = config.deployment.secrets.stripe-secret-key.destination;
-    database = "SQLite3";
-    databasePath = "${config.fileSystems."zkapissuer-data".mountPoint}/vouchers.sqlite3";
-  };
+  options.grid.issuer = {
+    letsEncryptAdminEmail = lib.mkOption {
+      type = lib.types.str;
+      description = ''
+        A string giving an email address to use for Let's Encrypt registration and
+        certificate issuance.
+      '';
+    };
+
+    issuerDomains = lib.mkOption {
+      type = lib.types.listOf lib.types.str;
+      description = ''
+        A list of strings giving the domain names that point at this issuer
+        system.  These will all be included in Let's Encrypt certificate.
+      '';
+    };
 
-  services.private-storage.monitoring.vpn.client = {
-    enable = true;
-    ip = monitoringvpnIPv4;
-    endpoint = monitoringvpnEndpoint;
-    endpointPublicKeyFile = "${publicKeyPath}/monitoringvpn/server.pub";
+    allowedChargeOrigins = lib.mkOption {
+      type = lib.types.listOf lib.types.str;
+      description = ''
+        A list of strings giving CORS Origins will the issuer will be configured
+        to allow.
+      '';
+    };
   };
 
+  config = {
+    deployment = {
+      secrets = {
+        "ristretto-signing-key" = {
+          destination = "/run/keys/ristretto.signing-key";
+          source = "${privateKeyPath}/ristretto.signing-key";
+          owner.user = "zkapissuer";
+          owner.group = "zkapissuer";
+          permissions = "0400";
+          action = ["sudo" "systemctl" "restart" "zkapissuer.service"];
+        };
+        "stripe-secret-key" = {
+          destination = "/run/keys/stripe.secret-key";
+          source = "${privateKeyPath}/stripe.secret";
+          owner.user = "zkapissuer";
+          owner.group = "zkapissuer";
+          permissions = "0400";
+          action = ["sudo" "systemctl" "restart" "zkapissuer.service"];
+        };
+
+        "monitoringvpn-secret-key" = {
+          destination = "/run/keys/monitoringvpn/client.key";
+          source = "${privateKeyPath}/monitoringvpn/${monitoringvpnIPv4}.key";
+          owner.user = "root";
+          owner.group = "root";
+          permissions = "0400";
+          action = ["sudo" "systemctl" "restart" "wireguard-monitoringvpn.service"];
+        };
+        "monitoringvpn-preshared-key" = {
+          destination = "/run/keys/monitoringvpn/preshared.key";
+          source = "${privateKeyPath}/monitoringvpn/preshared.key";
+          owner.user = "root";
+          owner.group = "root";
+          permissions = "0400";
+          action = ["sudo" "systemctl" "restart" "wireguard-monitoringvpn.service"];
+        };
+      };
+    };
+
+    services.private-storage-issuer = {
+      enable = true;
+      tls = true;
+      ristrettoSigningKeyPath = config.deployment.secrets.ristretto-signing-key.destination;
+      stripeSecretKeyPath = config.deployment.secrets.stripe-secret-key.destination;
+      database = "SQLite3";
+      databasePath = "${config.fileSystems."zkapissuer-data".mountPoint}/vouchers.sqlite3";
+      inherit letsEncryptAdminEmail allowedChargeOrigins;
+      domains = issuerDomains;
+    };
+
+    services.private-storage.monitoring.vpn.client = {
+      enable = true;
+      ip = monitoringvpnIPv4;
+      endpoint = monitoringvpnEndpoint;
+      endpointPublicKeyFile = "${publicKeyPath}/monitoringvpn/server.pub";
+    };
+
+    system.stateVersion = "19.03";
+  };
 }