From c5bec73274d9ecde65775afdf863428fa59c1266 Mon Sep 17 00:00:00 2001
From: Tom Prince <tom.prince@private.storage>
Date: Thu, 16 Sep 2021 17:20:01 -0600
Subject: [PATCH] Allow building the local grid with a clean checkout.

---
 .gitlab-ci.yml                                |  2 +-
 morph/grid/local/.gitignore                   |  3 +-
 morph/grid/local/README.rst                   |  2 +-
 morph/grid/local/grid.nix                     | 39 ++++++++++++++++++-
 .../{users.nix => users.nix.example}          |  0
 nixos/modules/update-deployment               |  6 +--
 6 files changed, 45 insertions(+), 7 deletions(-)
 rename morph/grid/local/public-keys/{users.nix => users.nix.example} (100%)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 76dce30e..481c2961 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -39,7 +39,7 @@ morph-build-localdev:
     - |
       # The local grid configuration is *almost* complete enough to build.  It
       # just needs this tweak.
-      sed -i 's/undefined/\"unundefined\"/' morph/grid/${GRID}/public-keys/users.nix
+      echo '{}' > morph/grid/${GRID}/public-keys/users.nix
 
 morph-build-testing:
   <<: *MORPH_BUILD
diff --git a/morph/grid/local/.gitignore b/morph/grid/local/.gitignore
index 8000dd9d..00e940f3 100644
--- a/morph/grid/local/.gitignore
+++ b/morph/grid/local/.gitignore
@@ -1 +1,2 @@
-.vagrant
+/.vagrant
+/public-keys/users.nix
diff --git a/morph/grid/local/README.rst b/morph/grid/local/README.rst
index d30d8766..48f395cb 100644
--- a/morph/grid/local/README.rst
+++ b/morph/grid/local/README.rst
@@ -35,7 +35,7 @@ Use the local development environment
 
   Latest Morph honors the ``SSH_CONFIG_FILE`` environment variable (`since 3f90aa88 (March 2020, v 1.5.0) <https://github.com/DBCDK/morph/commit/3f90aa885fac1c29fce9242452fa7c0c505744ef#diff-d155ad793bd62e6ea4c44ba985049ecb13a4f4f32f799791b2bce695a16c0101>`_), so in the future this should get a bit more convenient.
 
-6. Add your SSH key to ``users.nix`` so you'll be able to log in after deploying the new configuration::
+6. Create a ``public-keys/users.nix`` file with your SSH key (see ``public-keys/users.nix.example`` for the format) so you'll be able to log in after deploying the new configuration::
 
     $EDITOR public-keys/users.nix
 
diff --git a/morph/grid/local/grid.nix b/morph/grid/local/grid.nix
index e3c5752c..46cb9c8e 100644
--- a/morph/grid/local/grid.nix
+++ b/morph/grid/local/grid.nix
@@ -4,6 +4,21 @@ let
   gridlib = import ../../lib;
   grid-config = pkgs.lib.trivial.importJSON ./config.json;
 
+  ssh-users = let
+    ssh-users-file = ./public-keys/users.nix;
+  in
+    if builtins.pathExists ssh-users-file then
+      import ssh-users-file
+    else
+      # Use builtins.toString so that nix does not add the file
+      # to the nix store before including it in the string.
+      throw ''
+        ssh-keys for local grid are not configured.
+        Refusing to build a possibly inaccessible configuration.
+        Please create ${builtins.toString ssh-users-file} before building.
+        See ${builtins.toString ./README.rst} for more information.
+      '';
+
   # Module with per-grid configuration
   grid-module = {config, ...}: {
     imports = [
@@ -13,7 +28,29 @@ let
       # Give it a good SSH configuration.
       ../../../nixos/modules/ssh.nix
     ];
-    services.private-storage.sshUsers = import ./public-keys/users.nix;
+    services.private-storage.sshUsers = ssh-users;
+
+    # Include the ssh-users config in a form that can be read by nix,
+    # so the self-update deployment system can access it.
+    # nixos/modules/update-deployment imports the nix file into
+    # the checkout of this repository it creates.
+    environment.etc."nixos/ssh-users.json" = {
+      # Output the loaded value, rather than just copying the file, in case the
+      # file has external references.
+      mode = "0666";
+      text = builtins.toJSON ssh-users;
+    };
+    environment.etc."nixos/ssh-users.nix" = {
+      # This is the file that is imported by update-deployment.
+      # We don't directly read the JSON so that the script doesn't
+      # depend on the format we use.
+      mode = "0666";
+      text = ''
+        # Include the ssh-users config 
+        builtins.fromJSON (builtins.readFile ./ssh-users.json)
+      '';
+    };
+
     networking.domain = grid-config.domain;
     # Convert relative paths to absolute so library code can resolve names
     # correctly.
diff --git a/morph/grid/local/public-keys/users.nix b/morph/grid/local/public-keys/users.nix.example
similarity index 100%
rename from morph/grid/local/public-keys/users.nix
rename to morph/grid/local/public-keys/users.nix.example
diff --git a/nixos/modules/update-deployment b/nixos/modules/update-deployment
index d8d32ff6..889324f9 100755
--- a/nixos/modules/update-deployment
+++ b/nixos/modules/update-deployment
@@ -50,10 +50,10 @@ fi
 # Get us to a pristine checkout of the right branch.
 git -C "${CHECKOUT}" reset --hard "origin/${BRANCH}"
 
-# If we happen to be on the local grid then fix the undefined key.
+# If we happen to be on the local grid then add the required user.nix file
+# containing ssh-keys.
 if [ "${GRIDNAME}" = "local" ]; then
-    KEY="$(cat /etc/ssh/authorized_keys.d/vagrant)"
-    sed -i "s_undefined_\"${KEY}\"_" "${CHECKOUT}"/morph/grid/${GRIDNAME}/public-keys/users.nix
+    echo "import /etc/nixos/ssh-users.nix" > "${CHECKOUT}"/morph/grid/"${GRIDNAME}"/public-keys/users.nix
 fi
 
 # Compute a log message explaining what we're doing.
-- 
GitLab