Deploy a NixOps Network
This guide will show you how you can roll out a NixOps configuration when a branch is updated.
| When an agent deploys itself, it interrupts its deployment. This is might cause issues with NixOps' state file, so using NixOps to deploy your agents is not recommended for now. This will be improved. |
| Usage of secrets inside a NixOps deployment has not been documented yet, because a standard solution is under development. |
Prerequisites:
-
You have set up an agent for the account that owns the repository
-
You have deployed a NixOps network before
-
You have added a repository to your Hercules CI installation
-
You have added the
hcicommand
Import state file (optional)
If you want to deploy an existing network, you need to import the state file in order to give access to the existing machines and resources.
First, find the network you want to automate.
$ nixops list
+--------------------------------------+----------------------------------+-----------------------------+------------+---------+
| UUID | Name | Description | # Machines | Type |
+--------------------------------------+----------------------------------+-----------------------------+------------+---------+
| e8c96407-026f-11eb-8821-024213d29dcb | foo | Unnamed NixOps network | 0 | |
+--------------------------------------+----------------------------------+-----------------------------+------------+---------+
Then, upload the state. State files identified by the project and file name.
$ nixops export -d e8c96407-026f-11eb-8821-024213d29dcb \ (1)
| hci state put --project github/neat-org/neat-repo \ (2)
--name nixops-foo.json \ (3)
--file -
| 1 | replace by the UUID of your deployment |
| 2 | replace by the project path that matches your repository |
| 3 | replace foo by the name of the deployment |
Add runNixOps to ci.nix
This guide helps you write the ci.nix file in steps.
Let’s start with a basic invocation of runNixOps:
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) runNixOps runIf;
inherit (pkgs) lib;
in
{
neat-network = runIf true (
runNixOps {
name = "foo";
src = lib.cleanSource ./.; (1)
networkFiles = ["network.nix" "network-aws.nix"]; (2)
}
);
}nix
| 1 | Unlike some other deployment methods, NixOps needs access to the actual expression files. |
| 2 | For the same reason, we specify the expression files as path strings relative to src. |
Add secrets to your agents
For example, with writeAWSSecret
runNixOps {
# ...
userSetupScript = ''
writeAWSSecret aws default
'';
secretsMap."aws" = "neat-aws";
}nix
and add to secrets.json on your agents:
"neat-aws": {
"kind": "Secret",
"data": {
"aws_access_key_id": "AKIA.....",
"aws_secret_access_key": "....."
}
}json
Prebuild the network
To make sure all packages are cached, create a network file to replace any values that are unknown when the network configuration can’t access secrets or cloud resources.
Create an empty network file network-stub.nix:
{ }nix
and add it to prebuildOnlyNetworkFiles:
runNixOps {
# ...
networkFiles = ["network.nix" "network-aws.nix"];
prebuildOnlyNetworkFiles = ["network-stub.nix"];
}nix
Then iterate on network-stub.nix until nix-instantiate ci.nix -A neat-network.prebuilt succeeds.
See deployOnlyNetworkFiles if you have overrides that you only want to use during continuous deployment.
Push
Commit any remaining changes and push your branch. Your agents will build and deploy your network.
Meanwhile, you can configure which branch causes your deployment to run. For example, if you only want to deploy when you’ve merged into the production branch, use:
# Make ci.nix a function with default argument
{ src ? { ref = null; }}:
# ...
neat-network = runIf (src.ref == "refs/heads/production") (
runNixOps {
# ...
}
);
}nix
After push/PR/merge, your continuous deployment is ready for use.
Further reading
-
runNixOpsfunction