Newer
Older
# A NixOS module which enables remotely-triggered deployment updates.
{ config, lib, ... }:
# 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).
"restrict,command=\"${command} ${gridName}\" ${authorizedKey}";
in {
options = {
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.
'';
};
};
config = {
# 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"
];
};
# 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%
'';
# Configure the deployment user.
users.users.deployment = {
# Without some shell no login is possible at all, even to execute our
# single non-restricted command.
useDefaultShell = true;
# Without a home directory, lots of tools break.
createHome = true;
home = "/home/deployment";
# Authorize the supplied key to run the deployment update command.
openssh.authorizedKeys.keys = [
(restrictedKey {
inherit (cfg) authorizedKey gridName;
command = ./update-deployment;
})
];
};
};
}