diff --git a/nixos/modules/deployment.nix b/nixos/modules/deployment.nix
index f05aa1114cf3a5b2c8c30c1d70212bfd25d23ae3..2f4462ac0bc0b16719be7738bb0d758ef4d009eb 100755
--- a/nixos/modules/deployment.nix
+++ b/nixos/modules/deployment.nix
@@ -1,5 +1,5 @@
 # A NixOS module which enables remotely-triggered deployment updates.
-{ config, lib, ... }:
+{ config, lib, pkgs, ... }:
 let
   # A handy alias for our part of the configuration.
   cfg = config.services.private-storage.deployment;
@@ -44,6 +44,45 @@ in {
       ];
     };
 
+    # Create a one-time service that will set up an ssh key that allows the
+    # deployment user to authorize as root to perform the system update with
+    # `morph deploy`.
+    systemd.services.authorize-morph-as-root = {
+      enable = true;
+      serviceConfig = {
+        # Tell systemd that the service is a process that runs and then exits.
+        # By being "oneshot" instead of "simple" any dependencies are not
+        # started until after the process exits.  We have no dependencies yet
+        # but if we did it would be more correct for them to wait until we are
+        # done.
+        #
+        # It is not clear that "oneshot" means "run once" though (maybe it
+        # does, I can't tell) so the script is robust in the face of repeated
+        # runs even though it should only ever need to be run once.
+        Type = "oneshot";
+      };
+      wantedBy = [
+        # Run this to reach the multi-user target, a good target that is
+        # reached in the typical course of system startup.
+        "multi-user.target"
+      ];
+      # Here's the program to run for this unit.  It's a shell script that
+      # creates an ssh key that authorized root access via ssh and give it to
+      # the deployment user.  If such a key appears to exist already, do
+      # nothing.
+      script = ''
+        KEY=~deployment/.ssh/morph_key
+        TMP="$KEY"_tmp
+        if [ ! -e "$KEY" ]; then
+          mkdir -p ~deployment/.ssh ~root/.ssh
+          ${pkgs.openssh}/bin/ssh-keygen -f "$TMP"
+          cat "$TMP".pub >> ~root/.ssh/authorized_keys
+          mv "$TMP".pub "$KEY".pub
+          mv "$TMP" "$KEY"
+        fi
+      '';
+    };
+
     # Raise the hard-limit on the size of $XDG_RUNTIME_DIR (ie
     # /run/user/<uid>).  The default of 10% is too small on some systems for
     # the temporary state morph creates to do the self-update.