Basic Hive & Deployment
Creating a basic hive and deploying changes to the virtual machine.
Editing hive.nix
Open a text editor and edit hive.nix. You should copy this example, which imports the npins sources we added. It also calls makeHive, and gives wire nixpkgs from npins as well.
let
# import npins sources
sources = import ./npins;
# import `wire` from npins sources
wire = import sources.wire;
in
wire.makeHive {
# give wire nixpkgs from npins
meta.nixpkgs = import sources.nixpkgs { };
# we'll edit this part
}Lets check out what wire sees with wire show.
[nix-shell]$ wire show
INFO eval_hive: evaluating hive HiveNix("/home/marsh/scratch/wire-tutorial/hive.nix")
WARN use --json to output something scripting suitable
Summary: 0 total node(s), totalling 0 keys (0 distinct).
Note: Listed connections are tried from Left to RightThe line nodes: {} means there is no "nodes" in our hive.
Adding The First Node
Lets add the virtual machine as a node to the hive with the name virtual-machine. Additionally, we will add deployment.target, recalling we forwarded sshd virtual-machine:22 to the port localhost:2222:
let
sources = import ./npins;
wire = import sources.wire;
in
wire.makeHive {
meta.nixpkgs = import sources.nixpkgs { };
virtual-machine = { pkgs, ... }: {
deployment.target = {
port = 2222;
hosts = [ "localhost" ];
};
nixpkgs.hostPlatform = "x86_64-linux";
};
}A naive wire apply
If we tried to run wire apply on our hive at this stage, it likely won't work. If you've used NixOS before, you'll notice that many important options are missing. But let's try anyway:
[nix-shell]$ wire apply
ERROR apply{goal=Switch on=}:goal{node=virtual-machine}: lib::hive::node: Failed to execute `Evaluate the node`
Error: × 1 node(s) failed to apply.
Error:
× node virtual-machine failed to apply
├─▶ wire::Evaluate
│
│ × failed to evaluate `--file /home/marsh/scratch/wire-tutorial/hive.nix topLevels.virtual-machine` from the context
│ │ of a hive.
│
╰─▶ nix --extra-experimental-features nix-command --extra-experimental-features flakes eval --json --file /home/marsh/scratch/
wire-tutorial/hive.nix topLevels.virtual-machine --log-format internal-json failed (reason: known-status) with code 1 (last 20
lines):
error:
… while evaluating '(evaluateNode node).config.system.build.toplevel' to select 'drvPath' on it
at /nix/store/5pfz0v479gnciac17rcqi2gwyz8pl4s0-source/runtime/evaluate.nix:65:23:
64|
65| getTopLevel = node: (evaluateNode node).config.system.build.toplevel.drvPath;
| ^
66| in
… while calling the 'head' builtin
at /nix/store/n3d1ricw0cb5jd8vvfym6ig0mw7x7sv9-source/lib/attrsets.nix:1701:13:
1700| if length values == 1 || pred here (elemAt values 1) (head values) then
1701| head values
| ^
1702| else
(stack trace truncated; use '--show-trace' to show the full trace)
error:
Failed assertions:
- The ‘fileSystems’ option does not specify your root file system.
- You must set the option ‘boot.loader.grub.devices’ or 'boot.loader.grub.mirroredBoots' to make the system bootable.
trace: evaluation warning: system.stateVersion is not set, defaulting to 25.11. Read why this matters on https://nixos.org/
manual/nixos/stable/options.html#opt-system.stateVersion.The command complained about not defining any fileSystems or a boot loader. The ${sources.nixpkgs}/nixos/modules/virtualisation/qemu-vm.nix imported in vm.nix does extra work to make our virtual machine work, which we are currently missing.
Importing vm.nix
Lets import our vm.nix to this hive to fix our evaluation errors. Additionally, add a new package such as vim to our configuration:
let
sources = import ./npins;
wire = import sources.wire;
in
wire.makeHive {
meta.nixpkgs = import sources.nixpkgs { };
virtual-machine = { pkgs, ... }: {
deployment.target = {
port = 2222;
hosts = [ "localhost" ];
};
imports = [
./vm.nix
];
environment.systemPackages = [ pkgs.vim ];
nixpkgs.hostPlatform = "x86_64-linux";
};
}Our first deploy
Trying our basic wire apply again with these changes:
[nix-shell]$ wire apply
...
INFO lib::nix_log: stopping the following units: boot.mount
INFO lib::nix_log: NOT restarting the following changed units: systemd-fsck@dev-disk-by\x2dlabel-ESP.service
INFO lib::nix_log: activating the configuration...
INFO lib::nix_log: setting up /etc...
INFO lib::nix_log: restarting systemd...
INFO lib::nix_log: reloading user units for root...
INFO lib::nix_log: restarting sysinit-reactivation.target
INFO lib::nix_log: reloading the following units: dbus.service
INFO lib::nix_log: the following new units were started: boot.automount, sysinit-reactivation.target, systemd-tmpfiles-resetup.service
INFO apply{goal=Switch on=}:goal{node=virtual-machines}: lib::hive::node: Executing step `Upload key @ PostActivation`
INFO apply{goal=Switch on=}: wire::apply: Successfully applied goal to 1 node(s): [Name("virtual-machines")]Now, lets confirm these changes were applied to the virtual machine by executing vim in the virtual machine window:
[root@wire-tutorial:~]# vim --version
VIM - Vi IMproved 9.1 (2024 Jan 02, compiled Jan 01 1980 00:00:00)Nice! You successfully deployed a new NixOS configuration to a remote host!
INFO
This followed common steps of adding the node's deployment.target details and importing it's pre-existing NixOS configuration (in this case, vm.nix), a pattern you'll be using a lot if you chose to adopt wire.
In the next section, we'll cover how to deploy secrets / keys to our remote node.