Selectors and tags
The --on flag chooses which nodes a command acts on. It is the same selector
across apply, build, install, provision, and ssh, so a slice that
means something to you means the same thing to every command. With no --on,
Navi acts on every node in the Hive.
What --on accepts
The selector is a comma-separated list. Each entry is a node name, a glob, or a
tag prefixed with @:
navi apply --on web-01 # one node
navi apply --on web-01,web-02 # several nodes
navi apply --on 'web-*' # a glob over names
navi apply --on @web # a tag
navi apply --on @web,@db # several tags
Quote globs so the shell does not expand them before Navi sees them.
Tags
Tags are declared per node with deployment.tags, a list of strings. A node can
carry as many as you like, and a tag can span tenants, environments, and roles:
web-01 = { ... }: {
deployment.tags = [ "web" "staging" "edge" ];
};
With those tags in place, --on @web selects every web node, --on @staging
selects the staging environment, and --on @edge selects the edge tier,
regardless of how the nodes are named.
A naming convention
In a large fleet it pays to make the tags fall out of one convention rather than setting them by hand. A small function that stamps the environment, tenant, and tier into each node's name and tags keeps selection predictable:
mkNode = { env, tenant, tier, n }: {
name = "${env}-${tenant}-${tier}-${toString n}";
value = {
imports = [ ./tiers/${tier}.nix ];
deployment.tags = [ tier env tenant ];
};
};
Feed a list of those through builtins.listToAttrs to produce the nodes. Every
tag then derives from the convention, so --on @ingress, --on @staging, and
--on 'acme-*' each address exactly the slice you expect.
Listing what a selector matches
Several commands take --list to show the selected nodes without acting on
them. Use it to check a selector before running a destructive operation:
navi install --on 'web-*' --list
navi provision --list