Skip to content
Snippets Groups Projects
deployment.nix 3.08 KiB
Newer Older
  • Learn to ignore specific revisions
  • # A NixOS module which enables remotely-triggered deployment updates.
    
      # A handy alias for our part of the configuration.
      cfg = config.services.private-storage.deployment;
    
    
      # Compute an authorized_keys line that allows the holder of a certain key to
      # execute a certain command *only*.
    
      restrictedKey =
        { authorizedKey, command, gridName }:
    
        # `restrict` means "disable all the things" then `command` means "but
        # enable running this one command" (the client does not have to supply the
        # command; if they authenticate, this is the command that will run).
    
    Tom Prince's avatar
    Tom Prince committed
        "restrict,command=\"sudo ${command}\" ${authorizedKey}";
    
      update-script = pkgs.writeShellScript "update-deployment"
        ''
        set -euxo pipefail
    
        nix-env --profile /nix/var/nix/profiles/system --set -f ${lib.escapeShellArg ../top-level.nix} --argstr gridname ${lib.escapeShellArg cfg.gridName} --argstr hostname ${lib.escapeShellArg config.networking.hostName}
    
        /nix/var/nix/profiles/system/bin/switch-to-configuration switch
        '';
    
        services.private-storage.deployment.authorizedKey = lib.mkOption {
    
          type = lib.types.str;
          example = lib.literalExample ''
            ssh-ed25519 AAAAC3N...
          '';
          description = ''
            The SSH public key to authorize to trigger a deployment update.
          '';
        };
    
        services.private-storage.deployment.gridName = lib.mkOption {
    
          type = lib.types.str;
          example = lib.literalExample "staging";
          description = ''
            The name of the grid configuration to use to update this deployment.
          '';
        };
    
        # Configure the system to use our binary cache so that deployment updates
        # only require downloading pre-built software, not building it ourselves.
        nix = {
          binaryCachePublicKeys = [
            "saxtons.private.storage:MplOcEH8G/6mRlhlKkbA8GdeFR3dhCFsSszrspE/ZwY="
          ];
          binaryCaches = [
            "http://saxtons.private.storage"
          ];
        };
    
    
    Tom Prince's avatar
    Tom Prince committed
        # This package is used by top-level.nix above.
        system.extraDependencies = [ pkgs.morph.lib ];
    
        security.sudo.extraRules = [
          {
            users = ["deployment"];
            commands = [ "${update-script}" ];
            runAs = "root";
          }
        ];
    
        # 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.
        services.logind.extraConfig = ''
          RuntimeDirectorySize=50%
        '';
    
    
          # A user must be either normal or system.  A normal user uses the
          # default shell, has a home directory created for it at the usual
          # location, and is in the "users" group.  That's pretty much what we
          # want for the deployment user.
          isNormalUser = true;
    
          # Authorize the supplied key to run the deployment update command.
    
            (restrictedKey {
              inherit (cfg) authorizedKey gridName;
    
    Tom Prince's avatar
    Tom Prince committed
              command = update-script;