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.