Deploy a NixOS Machine
This guide will show you how you can roll out a NixOS configuration when master
is updated.
When an agent deploys itself, it interrupts its deployment. This is a sub-par experience that will be improved. Nonetheless, this may work well enough to be useful. |
Prerequisites:
-
You have set up an agent for the account that owns the repository
-
You have root access to a NixOS machine
-
You have added a repository to your Hercules CI installation
Add an SSH Key
The agent needs valid credentials to log in, so we configure this before we add the effect.
If your agent doesn’t already have an appropriate keypair, add a secret to your
agent’s secrets.json
file.
Use the \n
escape sequence to enter line breaks.
the ergonomics will be improved |
"default-ssh": {
"kind": "Secret",
"data": {
"privateKey":
"-----BEGIN OPENSSH PRIVATE KEY-----\n.....\n-----END OPENSSH PRIVATE KEY-----\n",
"publicKey":
"ssh-rsa ..... default-ssh@hercules-ci\n"
}
}
Add the public key to your host /etc/nixos/configuration.nix
users.users.root.openssh.authorizedKeys.keys =
["ssh-rsa ..... default-ssh@hercules-ci"];
and switch
neathost# nixos-rebuild switch
If you want to use your binary cache, configure it on the remote machine and nixos-rebuild switch . Although not a requirement, it is advisable when you have
significant custom store paths and multiple machines or a slow connection to them.
|
Gather configuration
Copy the /etc/nixos/configuration.nix
and any dependencies like hardware-configuration.nix
to your repository.
Determine the version of the Nixpkgs channel:
# nixos-version
20.09.1632.a6a3a368dda (Nightingale)
Find the SSH host key, locally in your SSH client state. Use the machine’s IP address or hostname:
$ grep 203.0.113.2 ~/.ssh/known_hosts
203.0.113.2 ssh-ed25519 AA.....
Alternatively, if you haven’t logged in there before, you can use ssh-keyscan
, although you should verify the keys.
Use the commit id, hostname and host key to create a ci.nix
file in your repository:
{ src ? { ref = null; } }:
let
# replace hash or use different pinning solution
nixpkgs = builtins.fetchTarball
"https://github.com/NixOS/nixpkgs/archive/a6a3a368dda.tar.gz";
pkgs = import nixpkgs {
system = "x86_64-linux";
overlays = [
(import (effectsSrc + "/overlay.nix"))
];
};
# update hash if desired or use different pinning solution
effectsSrc = builtins.fetchTarball
"https://github.com/hercules-ci/hercules-ci-effects/archive/b67cfbbb31802389e1fb6a9c75360968d201693b.tar.gz";
inherit (pkgs.effects) runNixOS runIf;
in
{
neathost = runIf (src.ref == "refs/heads/master")
(runNixOS {
configuration = ./configuration.nix;
# this references secrets.json on your agent
secretsMap.ssh = "default-ssh";
# replace this with the appropriate line from ~/.ssh/known_hosts
userSetupScript = ''
writeSSHKey ssh
cat >>~/.ssh/known_hosts <<EOF
203.0.113.2 ssh-ed25519 AA.....
EOF
'';
# replace with hostname or ip address for ssh
ssh.destination = "203.0.113.2";
});
}
Try it
When you commit and push these files to a new branch (not master
), you’ll see
that runIf
has turned nearhost
into an attrset with dependencies
and prebuilt
derivations. These make sure your NixOS deployment effect is likely
to work, but don’t perform the actual deployment.
When you create a pull request from your branch into master
, and Hercules CI
gives it a good status.
When you merge your branch into master
, the job for master
will have a
neathost.run
effect that does perform the deployment.
Branches
Instead of master
in refs/heads/master
, you can make your deployment track
other branches.
Multiple machines can be defined side by side in their own attributes, potentially tracking different branches if that fits your workflow.
For example, you can implement a staging/production setup with continuous deployment to staging and manually triggered deployment to production:
stagingHost = runIf (src.ref == "refs/heads/master")
(/* ... */);
productionHost = runIf (src.ref == "refs/heads/production")
(/* ... */);
More
You have completed this guide! Specifically you have used CI to trigger the deployment of an existing NixOS machine and you’ve configured it to track the right branch.
If you want to know more, you can check out the runNixOS
function reference or read about the other effects in the menu.