···1515the same name together.
16161717::: tip
1818-It should be noted that there are a few downsides. For example, you cannot access `config.deployment` from `nixosConfigurations`. For this reason it would be best practice to limit configuration in `colmena` to simply defining keys and deployment options.
1818+You should include the wire module, which will provide the `deployment` options, even if nixos-rebuild can't directly use them.
1919:::
20202121::: code-group
···24242525Now, if we run `wire show`, you will see that wire only finds
2626the `nixosConfigurations`-es that also match a node in the hive.
2727+`some-other-host` is not included in the hive unless specified in `makeHive`.
27282829```
2930$ wire show
3030-Hive {
3131- nodes: {
3232- Name(
3333- "node-a",
3434- ): Node {
3535- target: Target {
3636- hosts: [
3737- "node-a",
3838- ],
3939- user: "root",
4040- port: 22,
4141- current_host: 0,
4242- },
4343- build_remotely: false,
4444- allow_local_deployment: true,
4545- tags: {},
4646- keys: [],
4747- host_platform: "x86_64-linux",
4848- },
4949- },
5050- schema: 0,
5151-}
3131+Node node-a (x86_64-linux):
3232+3333+ > Connection: {root@node-a:22}
3434+ > Build remotely `deployment.buildOnTarget`: false
3535+ > Local apply allowed `deployment.allowLocalDeployment`: true
3636+3737+Summary: 1 total node(s), totalling 0 keys (0 distinct).
3838+Note: Listed connections are tried from Left to Right
3939+5240```
53415442This way, you can continue using `nixos-rebuild` and wire at the same time.
+10
doc/guides/flakes/overview.md
···2727$ nix flake show
2828git+file:///some/path
2929└───wire: unknown
3030+3131+$ wire show
3232+Node node-a (x86_64-linux):
3333+3434+ > Connection: {root@node-a:22}
3535+ > Build remotely `deployment.buildOnTarget`: false
3636+ > Local apply allowed `deployment.allowLocalDeployment`: true
3737+3838+Summary: 1 total node(s), totalling 0 keys (0 distinct).
3939+Note: Listed connections are tried from Left to Right
3040```
+15-11
doc/guides/installation.md
···15151616:::
17171818+It is recommended you stick to either using a tagged version of wire, or the `stable` branch which tracks the latest stable tag.
1919+1820## Binary Cache
19212020-You should trust the substituter `https://wires.cachix.org` by
2121-either editing `/etc/nix/nix.conf` or updating your NixOS configuration:
2222-2323-::: code-group
2424-2525-<<< @/snippets/getting-started/nix.conf
2626-<<< @/snippets/getting-started/cache.nix [configuration.nix]
2727-2828-:::
2222+You must enable the [garnix binary cache](https://garnix.io/docs/caching) on all
2323+nodes in your wire hive, otherwise they will not accept the wire key agent and
2424+you will be compiling everything from source.
29253026## Installation through flakes
3127···4541you'd like, really.
46424743```sh
4848-$ npins add github mrshmllow wire
4444+$ npins add github mrshmllow wire --branch stable
4945```
50464747+Alternatively, you can use a tag instead:
4848+4949+```sh
5050+$ npins add github mrshmllow wire --at v1.0.0-alpha.0
5151+```
5252+5353+Then, use this pinned version of wire for both your `hive.nix` and `shell.nix`:
5454+5155::: code-group
5256<<< @/snippets/guides/installation/shell.nix{8} [shell.nix]
5353-<<< @/snippets/guides/installation/hive.nix{8} [hive.nix]
5757+<<< @/snippets/guides/installation/hive.nix [hive.nix]
5458:::
+3
doc/guides/non-root-user.md
···2222- "Non-interactive SSH Auth" here most likely meaning an SSH key, anything that
2323 does not require keyboard input in the terminal.
24242525+To put it simply, you cannot have a password on _ssh_, but you can have a
2626+password on _sudo_.
2727+2528## Changing the user
26292730By default, the target is set to root:
+112
doc/guides/writing-a-hive.md
···11+---
22+comment: true
33+title: Write a Hive
44+---
55+66+# {{ $frontmatter.title }}
77+88+## Anatomy of a Hive
99+1010+A "Hive" is the attribute set that you pass to `wire.makeHive`. It has the
1111+following layout:
1212+1313+```nix
1414+# `meta`
1515+# type: attrset
1616+meta = {
1717+ # `meta.nixpkgs` tells wire how to get nixpkgs.
1818+ # type: "A path or an instance of nixpkgs."
1919+ nixpkgs = <nixpkgs>;
2020+2121+ # `meta.specialArgs` are specialArgs to pass to each node & default
2222+ # type: attrset
2323+ specialArgs = { };
2424+};
2525+2626+# `defaults` is a module applied to every node
2727+# type: NixOS Module
2828+defaults = { ... }: { };
2929+3030+# Any other attributes are nodes.
3131+```
3232+3333+### `<node-name>`
3434+3535+Other attributes are NixOs modules that describe a system. They automatically
3636+have `defaults` and the wire NixOS module imported.
3737+3838+They also have the `name` and `nodes` attributes passed to them, `name` being a string of the nodes name, and `nodes` being an attribute set of every node in the hive.
3939+4040+### `meta`
4141+4242+There is more detailed information about `meta` in [the
4343+reference](/reference/meta.html).
4444+4545+### `defaults`
4646+4747+De-duplicate options with default node configuration.
4848+4949+At the top level of a hive wire reserves the `defaults` attribute. It's applied
5050+to every node.
5151+5252+::: warning
5353+5454+`defaults` must not rely on modules that a node imports, but a
5555+node may rely on modules that default imports.
5656+5757+:::
5858+5959+## Example
6060+6161+There is more detailed information the special options for nodes [the
6262+reference](/reference/module.html).
6363+6464+```nix:line-numbers [hive.nix]
6565+{
6666+ meta.nixpkgs = import some-sources-or-inputs.nixpkgs { };
6767+6868+ defaults = {
6969+ # name of the node that defaults is being applied to
7070+ name,
7171+ # attribute set of all nodes
7272+ nodes,
7373+ pkgs,
7474+ ...
7575+ }: {
7676+ import = [
7777+ ./default-module.nix
7878+7979+ # module that is imported for all nodes
8080+ some-flake.nixosModules.default
8181+ ];
8282+8383+ # all nodes should include vim!
8484+ environment.systemPackages [ pkgs.vim ];
8585+ };
8686+8787+ node-a = {
8888+ # name of the node that defaults is being applied to
8989+ name,
9090+ # attribute set of all nodes
9191+ nodes,
9292+ pkgs,
9393+ ...
9494+ }: {
9595+ imports = [
9696+ # import the hardware-config and all your extra stuff
9797+ ./node-a
9898+ ];
9999+100100+ deployment = {
101101+ target.host = "192.0.2.1";
102102+ tags = [ "x86" ];
103103+ };
104104+ };
105105+106106+ # as many nodes as you'd like...
107107+108108+ node-g = {
109109+ # some more config
110110+ };
111111+}
112112+```
···22 inputs = {
33 nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
44 wire.url = "github:mrshmllow/wire/stable";
55+66+ # alternatively, you can use a tag instead:
77+ # wire.url = "github:mrshmllow/wire/v1.0.0-alpha.0";
88+59 systems.url = "github:nix-systems/default";
610 };
711···1418 forAllSystems = nixpkgs.lib.genAttrs (import systems);
1519 in {
1620 wire = wire.makeHive {
1717- # ...
2121+ nixpkgs = import nixpkgs {localSystem = "x86_64-linux";};
2222+2323+ # Continue to next How-To guide to fill this section
1824 };
19252026 devShells = forAllSystems (
+1-1
doc/snippets/guides/installation/hive.nix
···66 # give wire nixpkgs from npins
77 meta.nixpkgs = import sources.nixpkgs {};
8899- # ...
99+ # Continue to next How-To guide to fill this section
1010 }
+3-1
doc/tutorial/overview.md
···18181919In this tutorial we will create and deploy a wire Hive. Along the way we will
2020encounter [npins](https://github.com/andir/npins), simple NixOS
2121-configurations, virutal machines, and deployment keys.
2121+configurations, virtual machines, and deployment keys.
2222+2323+You'll need at least 10~ GB of free disk space to complete this tutorial.
22242325<div class="tip custom-block" style="padding-top: 8px">
2426
+1-1
doc/tutorial/part-one/basic-hive.md
···40404141```
42424343-The line `nodes: {}` means theres no "nodes" in our hive.
4343+The line `nodes: {}` means there is no "nodes" in our hive.
44444545## Adding The First Node
4646
+4-13
doc/tutorial/part-one/nix-setup.md
···2626nix (Nix) 2.11.0
2727```
28282929-## Using `cache.althaea.zone`
2929+## Binary Cache
30303131Because wire can be heavy to compile, it is distributed with a [binary
3232-cache](https://wiki.nixos.org/wiki/Binary_Cache). It's URL is
3333-`https://cache.althaea.zone` and it's public key is
3434-`cache.althaea.zone:BelRpa863X9q3Y+AOnl5SM7QFzre3qb+5I7g2s/mqHI=`.
3232+cache](https://wiki.nixos.org/wiki/Binary_Cache).
35333636-You should trust the substituter `https://wires.cachix.org` by
3737-either editing `/etc/nix/nix.conf` or updating your NixOS configuration:
3838-3939-::: code-group
4040-4141-<<< @/snippets/getting-started/nix.conf
4242-<<< @/snippets/getting-started/cache.nix [configuration.nix]
4343-4444-:::
3434+You must enable the [garnix binary cache](https://garnix.io/docs/caching) or you
3535+will be compiling everything from source.
+6-11
doc/tutorial/part-one/repo-setup.md
···2727[nix-shell]$ git init wire-tutorial
2828Initialized empty Git repository in /home/.../wire-tutorial/.git/
2929[nix-shell]$ cd wire-tutorial/
3030-[nix-shell]$ npins init --bare
3030+[nix-shell]$ npins init
3131[INFO ] Welcome to npins!
3232[INFO ] Creating `npins` directory
3333[INFO ] Writing default.nix
3434[INFO ] Writing initial lock file (empty)
3535[INFO ] Successfully written initial files to 'npins/sources.json'.
3636-[nix-shell]$ npins add github pkpbynum nixpkgs --branch pb/disk-size-bootloader
3736```
38373939-::: details
4040-4141-This tutorial is using a [PR](https://github.com/NixOS/nixpkgs/pull/449945) that
4242-fixes virutal machine bootloader disk sizes.
4343-4444-:::
4545-4638This has created a pinned version of `nixpkgs` for us to use in our wire hive.
47394840## Adding wire as a dependency
···5042We can now need to tell `npins` to use `mrshmllow/wire` as a dependency.
51435244```sh
5353-[nix-shell]$ npins add github mrshmllow wire
4545+[nix-shell]$ npins add github mrshmllow wire --branch stable
5446[INFO ] Adding 'wire' …
5547 repository: https://github.com/mrshmllow/wire.git
5648 pre_releases: false
···10294 pkgs.git
10395 ];
10496105105- NIX_PATH = "nixpkgs=${sources.nixpkgs.outPath}";
9797+ shellHook = ''
9898+ export NIX_PATH="nixpkgs=${sources.nixpkgs.outPath}"
9999+ '';
106100}
107101```
108102···113107```sh
114108[nix-shell]$ exit
115109exit
110110+$ cd wire-tutorial/
116111$ nix-shell
117112[nix-shell]$ wire --version
118113wire 0.5.0
+30-5
doc/tutorial/part-one/vm-setup.md
···10101111## Creating a `vm.nix`
12121313+For this step, you'll need your ssh public key, which you can obtain from
1414+`ssh-add -L`.
1515+1316Open a text editor and edit `vm.nix`. Place in it this basic NixOS
1417virtual machine configuration, which enables openssh and forwards it's 22 port:
1518···22252326 networking.hostName = "wire-tutorial";
24272828+ users.users.root = {
2929+ initialPassword = "root";
3030+ openssh.authorizedKeys.keys = [
3131+ # I made this a nix syntax error so you're forced to deal with it!
3232+ <your ssh public-key as a string>
3333+ ];
3434+ };
3535+2536 boot = {
2637 loader = {
2738 systemd-boot.enable = true;
···2940 };
30413142 kernelParams = [ "console=ttyS0" ];
4343+4444+ boot.growPartition = true;
3245 };
33463447 # enable openssh
···4154 getty.autologinUser = "root";
4255 };
43564444- boot.growPartition = true;
4545-4657 virtualisation = {
4758 graphics = false;
4859 useBootLoader = true;
49606161+ # use a 5gb disk
5062 diskSize = 5 * 1024;
51636464+ # grow the filesystem to fit the 5 gb we reserved
6565+ fileSystems."/".autoResize = true;
6666+5267 # forward `openssh` port 22 to localhost:2222.
5368 forwardPorts = [
5469 {
···5873 }
5974 ];
6075 };
6161-6262- users.users.root.initialPassword = "root";
63766477 system.stateVersion = "23.11";
6578}
···70837184## Building & Running the virtual machine
72857373-Open a seperate Terminal tab/window/instance, ensuring you enter the development
8686+Open a separate Terminal tab/window/instance, ensuring you enter the development
7487shell with `nix-shell`.
7588Then, build the virtual machine with a bootloader,
7689taking our `vm.nix` as the nixos configuration.
···7992$ nix-shell
8093[nix-shell]$ nix-build '<nixpkgs/nixos>' -A vmWithBootLoader -I nixos-config=./vm.nix
8194```
9595+9696+::: tip HELP
9797+9898+If you got an error such as
9999+100100+```
101101+error: The option `...' in `...' is already declared in `...'.
102102+```
103103+104104+make sure you ran the above command in the `nix-shell`!
105105+106106+:::
8210783108Building the virtual machine can take some time, but once it completes, start it
84109by running:
+10-8
doc/tutorial/part-two/encryption.md
···10101111::: tip
1212For this tutorial we will be using [`age`](https://github.com/FiloSottile/age),
1313-but other encryption cli tools work just as well such as GnuPG.
1313+but other encryption CLI tools work just as well such as GnuPG.
1414:::
15151616## Installing age
···3131 pkgs.age # [!code ++]
3232 ];
33333434- NIX_PATH = "nixpkgs=${sources.nixpkgs.outPath}";
3434+ shellHook = ''
3535+ export NIX_PATH="nixpkgs=${sources.nixpkgs.outPath}"
3636+ '';
3537}
3638```
3739···6971use the redirection operator to save the encrypted data to `top-secret.age`.
70727173```sh
7272-[nix-shell]$ echo "!! encrypted string !!" | age --encrypt --recipient $(age-keygen -y key.txt) > top-secret.age
7474+[nix-shell]$ echo "encrypted string!" | age --encrypt --recipient $(age-keygen -y key.txt) > top-secret.age
7375```
74767577## Adding an age-encrypted key
76787779Now, lets combine our previous command-sourced key with `age`. Pass the
7878-arguments `age --decrypt --identity key.txt ./age-secret.age` to wire:
8080+arguments `age --decrypt --identity key.txt ./top-secret.age` to wire:
79818082```nix:line-numbers [secrets.nix]
8183{
8284 deployment.keys = {
8385 # ...
84868585- "age-secret" = { # [!code ++]
8787+ "top-secret" = { # [!code ++]
8688 source = [ # [!code ++]
8789 "age" # [!code ++]
8890 "--decrypt" # [!code ++]
8991 "--identity" # [!code ++]
9092 "key.txt" # [!code ++]
9191- "${./age-secret.age}" # [!code ++]
9393+ "${./top-secret.age}" # [!code ++]
9294 ]; # [!code ++]
9395 }; # [!code ++]
9496 };
···99101key:
100102101103```sh [Virtual Machine]
102102-[root@wire-tutorial:~]# cat /run/keys/age-secret
103103-!! encrypted string !!
104104+[root@wire-tutorial:~]# cat /run/keys/top-secret
105105+encrypted string!
104106105107```
···88use crate::{
99 EvalGoal, SubCommandModifiers,
1010 commands::{CommandArguments, Either, WireCommandChip, run_command, run_command_with_env},
1111- errors::HiveLibError,
1111+ errors::{CommandError, HiveLibError},
1212 hive::{
1313 HiveLocation,
1414 node::{Context, Push},
···5252 Ok(())
5353}
54545555+fn get_common_command_help(error: &CommandError) -> Option<String> {
5656+ if let CommandError::CommandFailed { logs, .. } = error
5757+ // marshmallow: your using this repo as a hive you idiot
5858+ && (logs.contains("attribute 'inspect' missing")
5959+ // using a flake that does not provide `wire`
6060+ || logs.contains("does not provide attribute 'packages.x86_64-linux.wire'")
6161+ // using a file called `hive.nix` that is not actually a hive
6262+ || logs.contains("attribute 'inspect' in selection path"))
6363+ {
6464+ Some("Double check this `--path` or `--flake` is a wire hive. You may be pointing to the wrong directory.".to_string())
6565+ } else {
6666+ None
6767+ }
6868+}
6969+5570/// Evaluates the hive in flakeref with regards to the given goal,
5671/// and returns stdout.
5772#[instrument(ret(level = tracing::Level::TRACE), skip_all)]
···99114 )
100115 .await?;
101116102102- child
103103- .wait_till_success()
104104- .await
105105- .map_err(|source| HiveLibError::NixEvalError { attribute, source })
117117+ let status = child.wait_till_success().await;
118118+119119+ let help = if let Err(ref error) = status {
120120+ get_common_command_help(error).map(Box::new)
121121+ } else {
122122+ None
123123+ };
124124+125125+ status
126126+ .map_err(|source| HiveLibError::NixEvalError {
127127+ attribute,
128128+ source,
129129+ help,
130130+ })
106131 .map(|x| match x {
107132 Either::Left((_, stdout)) | Either::Right((_, stdout)) => stdout,
108133 })
+4-1
wire/lib/src/commands/mod.rs
···109109 envs: HashMap<String, String>,
110110) -> Result<Either<InteractiveChildChip, NonInteractiveChildChip>, HiveLibError> {
111111 // use the non interactive command runner when forced
112112- if arguments.modifiers.non_interactive {
112112+ // ... or when there is no reason for interactivity, local and unprivileged
113113+ if arguments.modifiers.non_interactive
114114+ || (arguments.target.is_none() && !arguments.is_elevated())
115115+ {
113116 return Ok(Either::Right(non_interactive_command_with_env(
114117 arguments, envs,
115118 )?));