diff --git a/morph/grid/local/config.json b/morph/grid/local/config.json
index 09074b3a6077b471f999f78de4226648b8c7e617..c08955eb24d0c7046dbb4862cf7b81d1ca3e0a0a 100644
--- a/morph/grid/local/config.json
+++ b/morph/grid/local/config.json
@@ -2,6 +2,7 @@
 , "ristrettoSigningKeyPath": "../../PrivateStorageSecrets/ristretto.signing-key"
 , "stripeSecretKeyPath": "../../PrivateStorageSecrets/privatestorageio-testing-stripe.secret"
 , "monitoringvpnKeyDir": "../../PrivateStorageSecrets/monitoringvpn"
+, "monitoringvpnEndpoint": "192.168.67.24:51820"
 , "passValue": 1000000
 , "issuerDomain": "payments.localdev"
 , "letsEncryptAdminEmail": "florian@privatestorage.io"
diff --git a/morph/grid/production/config.json b/morph/grid/production/config.json
index 99c50b3f3e5dc16ad1bde3afabc1df6f85c7cf2f..fefbb16665660a24e7c61a011e76139335e8b9da 100644
--- a/morph/grid/production/config.json
+++ b/morph/grid/production/config.json
@@ -2,6 +2,7 @@
 , "ristrettoSigningKeyPath": "../../PrivateStorageSecrets/ristretto.signing-key"
 , "stripeSecretKeyPath": "../../PrivateStorageSecrets/stripe.secret"
 , "monitoringvpnKeyDir": "../../PrivateStorageSecrets/monitoringvpn"
+, "monitoringvpnEndpoint": "monitoring.private.storage:51820"
 , "passValue": 1000000
 , "issuerDomain": "payments.privatestorage.io"
 , "letsEncryptAdminEmail": "jean-paul@privatestorage.io"
diff --git a/morph/grid/testing/config.json b/morph/grid/testing/config.json
index 0765f915107a60bb373f347f63597c7648ac46ed..d0b1b814601ec076aa3fb77b55e589f8e7c5782d 100644
--- a/morph/grid/testing/config.json
+++ b/morph/grid/testing/config.json
@@ -2,6 +2,7 @@
 , "ristrettoSigningKeyPath": "../../PrivateStorageSecrets/ristretto.signing-key"
 , "stripeSecretKeyPath": "../../PrivateStorageSecrets/privatestorageio-testing-stripe.secret"
 , "monitoringvpnKeyDir": "../../PrivateStorageSecrets/monitoringvpn"
+, "monitoringvpnEndpoint": "monitoring.privatestorage-staging.com:51820"
 , "passValue": 1000000
 , "issuerDomain": "payments.privatestorage-staging.com"
 , "letsEncryptAdminEmail": "jean-paul@privatestorage.io"
diff --git a/morph/lib/make-issuer.nix b/morph/lib/make-issuer.nix
index b4bb55a6d793321e8ecb2ad789d27729e3767dc2..7ca7992c94776af560c667f2c0949cb1bfdaed65 100644
--- a/morph/lib/make-issuer.nix
+++ b/morph/lib/make-issuer.nix
@@ -9,11 +9,13 @@
 , publicIPv4
 , monitoringvpnKeyDir ? null
 , monitoringvpnIPv4 ? null
+, monitoringvpnEndpoint ? null
 , ...
 }: let
 
   enableVpn = monitoringvpnKeyDir != null &&
-              monitoringvpnIPv4 != null;
+              monitoringvpnIPv4 != null &&
+              monitoringvpnEndpoint != null;
 
   vpnSecrets = if !enableVpn then {} else {
     "monitoringvpn-secret-key" = {
@@ -83,5 +85,6 @@ in rec {
   services.private-storage.monitoring.vpn.client = if !enableVpn then {} else {
     enable = true;
     ip = monitoringvpnIPv4;
+    endpoint = monitoringvpnEndpoint;
   };
 }
diff --git a/morph/lib/make-storage.nix b/morph/lib/make-storage.nix
index 1c000e11173ec200e395ae2305a4ba3ab49a8f62..de34394bf1b9094e27c83819c4234d125c0312dd 100644
--- a/morph/lib/make-storage.nix
+++ b/morph/lib/make-storage.nix
@@ -3,7 +3,6 @@
 , hardware                   # The path to the hardware configuration for this node.
 , publicStoragePort          # The storage port number on which to accept connections.
 , ristrettoSigningKeyPath    # The *local* path to the Ristretto signing key file.
-, monitoringvpnSecretKeyDir  # The directory that holds the VPN keys.
 , passValue                  # Bytes component of size×time value of passes.
 , sshUsers                   # Users for which to configure SSH access to this node.
 , stateVersion               # The value for system.stateVersion on this node.
@@ -12,7 +11,9 @@
                              # to avoid breaking some software such as
                              # database servers. You should change this only
                              # after NixOS release notes say you should.
+, monitoringvpnKeyDir        # The directory that holds the VPN keys.
 , monitoringvpnIPv4          # This node's IP in the monitoring VPN.
+, monitoringvpnEndpoint      # The VPN server and port.
 , ...
 }: rec {
   deployment = {
@@ -77,6 +78,6 @@
   services.private-storage.monitoring.vpn.client = {
     enable = true;
     ip = monitoringvpnIPv4;
-    endpoint = "monitoring.private.storage:51820"; # XXX TBD when the machine is online
+    endpoint = monitoringvpnEndpoint;
   };
 }
diff --git a/morph/lib/make-testing.nix b/morph/lib/make-testing.nix
index cd4128f70e0da92d091b468bbee6fbdeea18f069..974cfcbb69d8160bef682ccaf2bbdeda197b1f41 100644
--- a/morph/lib/make-testing.nix
+++ b/morph/lib/make-testing.nix
@@ -7,10 +7,12 @@
 , stateVersion
 , monitoringvpnKeyDir ? null
 , monitoringvpnIPv4 ? null
+, monitoringvpnEndpoint ? null
 , ... }: let
 
   enableVpn = monitoringvpnKeyDir != null &&
-              monitoringvpnIPv4 != null;
+              monitoringvpnIPv4 != null &&
+              monitoringvpnEndpoint != null;
 
   vpnSecrets = if !enableVpn then {} else {
     "monitoringvpn-secret-key" = {
@@ -72,5 +74,6 @@ in rec {
   services.private-storage.monitoring.vpn.client = if !enableVpn then {} else {
     enable = true;
     ip = monitoringvpnIPv4;
+    endpoint = monitoringvpnEndpoint;
   };
 }
diff --git a/nixos/modules/monitoring/vpn/client.nix b/nixos/modules/monitoring/vpn/client.nix
index 58991d0532106fad4c417ca09c52abb0aafa664e..4c651f612ef7d906a44efd99e68a054b7708c912 100644
--- a/nixos/modules/monitoring/vpn/client.nix
+++ b/nixos/modules/monitoring/vpn/client.nix
@@ -42,7 +42,6 @@ in {
     endpoint = lib.mkOption {
       type = lib.types.str;
       example = lib.literalExample "vpn.monitoring.private.storage:54321";
-      default = "192.168.67.24:51820";
       description = ''
         The address and port number of the server to establish the VPN with.
       '';