Just Commands
The commands below are all executed with just 🡕.
just <command> <arguments>Each command is prefixed with an icon indicating its usage context:
- 💠 Common: available in all contexts.
- 🔆 Framework: specific to the upstream DNF framework (
dnf/). - ✳️ Project: specific to the consuming project (my network).
- 🔗 Co-development: consuming project that contains a clone of the framework.
Available commands
Section titled “Available commands”The recipes live in dnf/just/. The project Justfile imports one bootstrap file, which determines the available commands depending on the context.
| Context | Justfile line | Commands |
|---|---|---|
| Framework | import 'just/dnf.just' | 💠 🔆 |
| Consumer project | import? 'dnf/just/project.just' | 💠 ✳️ |
| Co-development | import 'dnf/just/codev.just' | 💠 ✳️ 🔗 |
In a consumer project, dnf/ is the symlink to the Nix store created by nix run .#init. The ? in import? lets just start as long as this symlink does not exist.
Co-development replaces this link with a git clone of the framework. The recipes 🔆 unit-tests, check-recipes, simulate, simulate-debug, fixtures and pkg-update can also be run there from the root. Project templates include the codev.just line, commented out.
Development commands
Section titled “Development commands”Common to all contexts, these commands help maintain the code and generate declarative files.
💠 develop / d
Section titled “💠 develop / d”Runs nix develop -c zsh to get a shell with the project tools.
just develop💠 clean / c ⭐
Section titled “💠 clean / c ⭐”Runs the full chain: statix fix → check-code → generate → format → _fix_fs_permissions.
just clean💠 format
Section titled “💠 format”Runs treefmt on all files using the shared framework config. In
co-development, also formats dnf/.
just format💠 generate
Section titled “💠 generate”Regenerates the default.nix files of module folders and, in a project, the
var/generated/*.nix files from etc/config.yaml. It also seeds
usr/machines/<host>/ for each host with a disko block (see Machine
folder).
just generateVerification commands
Section titled “Verification commands”Run these checks before deploying to catch regressions.
💠 check
Section titled “💠 check”Runs code verification (check-code), DNF unit tests and
flake verification (check-flake). Unit tests only run on a
framework clone: a dnf/ symlinked to the store was tested before publication.
just check💠 check-code
Section titled “💠 check-code”Static analysis with statix and dead code detection with deadnix, on
all *.nix files.
just check-code💠 check-flake
Section titled “💠 check-flake”Runs nix flake check while filtering known warnings from DNF’s non-standard
outputs (colmena, colmenaHive, homeManagerModules, libTests,
mkNodes, secretsPlan, version).
just check-flakeFramework commands
Section titled “Framework commands”In the framework repository (dnf/). Tests and pkg-update also run
from the root of a co-development project.
🔆 unit-tests ⭐
Section titled “🔆 unit-tests ⭐”Runs nix-unit on the framework’s libTests tests.
just unit-tests🔆 check-recipes
Section titled “🔆 check-recipes”Verifies that the three bootstraps (dnf, project, codev) load correctly,
and that each nested just <recipe> call resolves to a recipe from its own
context. just only resolves these calls at runtime: CI runs the same
verification.
just check-recipes🔆 simulate [scenario]
Section titled “🔆 simulate [scenario]”Runs NixOS test scenarios (NixOS Test Driver).
| Argument | Effect |
|---|---|
| (empty) | Lists available scenarios |
all | Runs all scenarios (nix flake check) |
full | Regenerates fixtures then runs everything |
<name> | Runs a named scenario |
just simulate # listjust simulate all # run alljust simulate modules-node-console-git🔆 simulate-debug <scenario>
Section titled “🔆 simulate-debug <scenario>”Runs the interactive driver of a scenario (Python REPL).
just simulate-debug modules-node-console-git🔆 fixtures <action>
Section titled “🔆 fixtures <action>”Manages test fixtures: generation, drift check, regeneration of disposable keys and secrets.
| Action | Effect |
|---|---|
generate | Regenerates var/generated/ for all test environments |
check | Checks for drift without modifying the tree |
gen-secrets | Regenerates disposable test keys and secrets |
just fixtures check🔆 pkg-update <package> [version]
Section titled “🔆 pkg-update <package> [version]”Updates a package from dnf/pkgs/ to its latest upstream version, or to
version if given, using
nix-update 🡕. See Packages outside
nixpkgs.
just pkg-update rename-simplejust pkg-update fleet-update 0.2.0 # explicit version (release train)🔆 version
Section titled “🔆 version”Displays the framework version, its revision, its latest tag, and the generator release it pins.
just version🔆 changelog
Section titled “🔆 changelog”Displays what the next release entry would look like, without writing anything. Requires
git-cliff, provided by the devShell (just develop).
just changelog🔆 bump [level]
Section titled “🔆 bump [level]”Bumps the version, adds the CHANGELOG entry, commits and tags the framework, without pushing. See Publishing a release.
just bump # level inferred from commitsInstallation commands
Section titled “Installation commands”Installing a new host follows a precise sequence.
✳️ install <host> [user] [ip]
Section titled “✳️ install <host> [user] [ip]”Formats disks via disko and installs NixOS via nixos-anywhere.
The ip argument defaults to auto: the address is computed the same way as
for full-install, no need to look it up.
The recipe also drops on the target, before the system installation, the
age key /etc/sops/age/infra.key and, on an encrypted host, the SSH host key
of its initrd: sops works from the first activation and the very first boot
already listens on port 2222. The volume is formatted with the shared fleet
passphrase, so there is nothing to type.
just install myserverjust install myserver nixos 10.0.0.5 # custom IPjust install myserver nix auto test # test VM only✳️ full-install <host> [user] [ip] ⭐
Section titled “✳️ full-install <host> [user] [ip] ⭐”Full chain: install + wait for reboot + unlock + configure + apply + gc + reboot.
The starting address is calculated automatically: host name in its own zone, reserved pass-through address if plugged in elsewhere. See Machines outside their zone.
After reboot, the machine may not have returned to the same place: the recipe probes all its known addresses, on ports 22 and 2222, and continues on whichever responds. An encrypted host is unlocked along the way by just unlock.
The final reboot is not cosmetic: apply activates user space but not the kernel or initrd, and this reboot is the only automatic proof that the machine restarts on its own. On an encrypted host, it also proves that remote unlock works, while you are still in front of it rather than at the first power outage. unlock is therefore called again right after.
just full-install myserverjust full-install myserver nixos 10.0.3.42 # forced address✳️ install-key <host>
Section titled “✳️ install-key <host>”Formats a USB device with disko and installs NixOS on it. Seals the host like
install.
just install-key myusbhost✳️ install-here <hôte> <login> [empreinte] [yes] [passphrase]
Section titled “✳️ install-here <hôte> <login> [empreinte] [yes] [passphrase]”Installs the machine it runs on, booted from the generic DNF ISO, as the project’s administration workstation: disko wipes its disk, the keys are born on the target (bootstrap-keys), then nixos-install. The project joins /etc/nixos of the new system, owned by login. An encrypted disk requires its passphrase file, which becomes the fleet’s shared passphrase; the initrd SSH key is deposited on the target.
just install-here poste alice '<empreinte>'✳️ backup-admin <périphérique> [passphrase] [racine]
Section titled “✳️ backup-admin <périphérique> [passphrase] [racine]”Writes to a USB key, without formatting it, an age-encrypted backup of what nothing else replaces: the nix deployment key (which gives the admin age key), the infra age key and the project (git bundle). File dnf-backup-<domaine>.tar.age, with a plain README.txt; a previous backup of the same network is kept, renamed with its date.
périphérique: a partition of the key,/dev/disk/by-label/SECOURSfor example;passphrase: a file containing it; otherwise, age asks for it;racine: the system holding the keys,/mntfrom the installer.
darkone new runs it after installation.
just backup-admin /dev/disk/by-label/SECOURS✳️ backup-check <périphérique> [passphrase] [racine]
Section titled “✳️ backup-check <périphérique> [passphrase] [racine]”Reads back the backup-admin backup, same arguments, and compares it to the keys and the latest commit of the project.
✳️ configure <host> [ip]
Section titled “✳️ configure <host> [ip]”Chains copy-id → copy-hw → push-key → luks (the last one does nothing on a non-encrypted host).
The address is resolved once and passed to the whole chain. If the host is plugged outside its zone, the SSH redirection is set up in the process, so that the following apply reaches it: just roaming-clear <host> once the machine is back home.
just configure myserver✳️ copy-id <hôte>
Section titled “✳️ copy-id <hôte>”Checks that the nix deployment key can open the target host, and pushes the
shared private key to gateways (TLS certificate synchronization from the HCS).
just copy-id myserver✳️ copy-hw <host>
Section titled “✳️ copy-hw <host>”Runs nixos-generate-config --show-hardware-config remotely and saves the
result in usr/machines/<host>/hardware/hardware-configuration.nix,
then chains detect-hw.
just copy-hw myserver✳️ detect-hw <hôte> [ip] [user]
Section titled “✳️ detect-hw <hôte> [ip] [user]”Collects on the machine the kernel modules of its wired network cards and writes them to usr/machines/<hôte>/hardware/detected-hardware.nix (generated file, imported automatically). They join the initrd only if it has network, for remote LUKS unlocking. Also detects a virtual machine (systemd-detect-virt): no firmware is loaded on it (darkone.system.hardware.virtual). Called by install (nixos user of the ISO) and by copy-hw.
just detect-hw myserver✳️ push-key <host>
Section titled “✳️ push-key <host>”Transfers the age key /etc/sops/age/infra.key to the target host.
just push-key myserver✳️ host-info <hôte> [ip]
Section titled “✳️ host-info <hôte> [ip]”Displays the MAC address of a machine’s first active interface, to declare it
in etc/config.yaml before installing it. Useful when the host does not yet
have a DHCP reservation and can only be reached via the dynamic address shown
on its screen.
just host-info myserver 10.0.0.50✳️ luks <hôte> [action] [ip]
Section titled “✳️ luks <hôte> [action] [ip]”Provisions a host’s encryption : shared and per-host passphrases in sops,
initrd SSH key in sops then on the target, usr/secrets/luks.json manifest,
gateways’ WAN IP. See
Disk encryption (LUKS).
| Action | Effect |
|---|---|
| (default) | Prepares the secrets, then converges the machine |
pre | Offline half only, without touching the machine |
passwd | Rotates the per-host passphrase, then converges |
show | Read-only audit : keyslots and remote unlocking |
just luks myserverjust luks myserver showjust luks myserver passwd✳️ roaming [host] [ip]
Section titled “✳️ roaming [host] [ip]”Redirects SSH to a host connected outside its zone, for the duration of the installation. Colmena addresses a node by its name, which refers to its original address; this redirect points it to where the machine actually is.
Set up by just configure when needed, removed by full-install at the end of the run. Without arguments, displays the current redirects.
just roaming # displayjust roaming myserver # redirect (computed address)✳️ roaming-clear [host]
Section titled “✳️ roaming-clear [host]”Removes a host’s redirect, or all of them if none is given.
just roaming-clear myserverjust roaming-clear✳️ configure-admin-host ⭐
Section titled “✳️ configure-admin-host ⭐”Configure the administration machine: SSH keys, age SOPS keys,
.sops.yaml, default secrets, Harmonia signing key, and all
internal secrets required by declared services (OAuth2
clients, backups, service tokens, etc.).
just configure-admin-host✳️ bootstrap-keys [racine] [login] [empreinte]
Section titled “✳️ bootstrap-keys [racine] [login] [empreinte]”Creates the keys and the sops skeleton of a machine that has no nix account yet, under the given root (/, or /mnt from the installer). configure-admin-host relies on the same mechanism. The fingerprint of an account (mkpasswd, in single quotes) is optional.
just bootstrap-keys /mnt alice '<empreinte>'✳️ build-iso [arch]
Section titled “✳️ build-iso [arch]”Builds the installation ISO image for the given architecture. It bundles the administration public key (usr/secrets/nix.pub): just full-install connects to it without a password.
just build-iso # x86_64-linux (default)just build-iso "aarch64-linux"Deployment commands
Section titled “Deployment commands”The apply* commands rely on colmena 🡕
and first refresh the DNF lock via update-dnf. fleet-update drives a full
update using native Nix commands.
✳️ apply <target> [action] / a ⭐
Section titled “✳️ apply <target> [action] / a ⭐”Deploys the configuration on one or more targets.
| Parameter | Description |
|---|---|
target | Hostname, glob ('*'), list (a,b), colmena tag (@server) |
action | switch (default), boot, test, build |
just apply @all # all hostsjust apply myserver # switch (default)just apply myserver boot # bootjust apply 'db-*' # all hosts starting with db-✳️ apply-verbose <c> [a] / av ⭐
Section titled “✳️ apply-verbose <c> [a] / av ⭐”Same as apply with --verbose --show-trace.
just apply-verbose myserver✳️ apply-local [action] / al ⭐
Section titled “✳️ apply-local [action] / al ⭐”Applies the configuration on the current machine.
just apply-local✳️ apply-silenced <target> [action]
Section titled “✳️ apply-silenced <target> [action]”Enables Alertmanager maintenance mode before applying, disables it after.
just apply-silenced myserver✳️ fleet-update [options]
Section titled “✳️ fleet-update [options]”Updates, builds and deploys the entire fleet in waves. See Update the fleet with fleet-update.
just fleet-update # tout le parc, interface interactivejust fleet-update --on '+server' # les hôtes d'un profiljust fleet-update --build-only # construire sans rien activerjust fleet-update --help # toutes les options✳️ update-flake
Section titled “✳️ update-flake”Updates the root flake inputs. In co-development, updates dnf/ inputs first and commits them (chore(flake):, amended if the latest dnf/ commit is already one).
just update-flake✳️ update-dnf
Section titled “✳️ update-dnf”Syncs flake.lock with the local HEAD of dnf/ (co-development).
just update-dnfAdministration commands
Section titled “Administration commands”These commands interact with fleet hosts: maintenance, reboot, cleanup, and boot repair.
✳️ enter <hôte> / e ⭐
Section titled “✳️ enter <hôte> / e ⭐”Opens an interactive SSH session as nix@<hôte>, on port 22 only. A host outside its zone is located by dnf-locate (see
Joining a host while travelling).
A host waiting for its LUKS passphrase falls under just unlock.
just enter myserver✳️ unlock <hôte> [ip] [délai]
Section titled “✳️ unlock <hôte> [ip] [délai]”Answers the LUKS prompt of a host still sitting in its initrd, with no human present :
the passphrase is read from sops and pushed through the sshd on port 2222. It waits for
the host to show up (one dot per attempt), which makes it possible to chain it right
after a reboot. Called automatically by just full-install. No stored passphrase
accepted : from a terminal, the request is presented.
On a host without a LUKS volume, it is a logged no-op.
just unlock myserver✳️ remote-desktop <host> [ro|rw|login] / rd ⭐
Section titled “✳️ remote-desktop <host> [ro|rw|login] / rd ⭐”Opens the remote desktop of a host. ro (default) watches the already open graphical session, rw takes control of it; both fail if nobody is logged in. login opens your own session behind a GDM login screen instead. No port is opened on the host: the stream goes through an SSH tunnel set up by nix. See
Remote desktop.
just rd mypc # observationjust rd mypc rw # take controljust rd mypc login # own session, via GDM✳️ reboot <host>
Section titled “✳️ reboot <host>”Reboots the host via colmena exec.
just reboot myserverjust reboot 'web-*' # all web-*✳️ halt <host>
Section titled “✳️ halt <host>”Shuts down (poweroff) the host via colmena exec, after confirmation.
just halt myserver✳️ gc <host> [keep] ⭐
Section titled “✳️ gc <host> [keep] ⭐”Removes old generations, cleans the store, then regenerates the boot entries
(switch-to-configuration boot). keep sets what is retained:
keep | Generations retained |
|---|---|
| (empty) | Current only, all profiles (nix-collect-garbage -d) |
N (1 to 99) | Last N system generations, current included |
Nd (1 to 99) | Those less than N days old, plus the active one on that date |
# Clean hosts whose name starts with "server-"just gc "server-*" # Keep only the current generationjust gc "server-*" 3 # Keep the last 3 generations, current includedjust gc "server-*" 3d # Remove generations older than 3 days✳️ nfs-cleanup <hosts> [mode]
Section titled “✳️ nfs-cleanup <hosts> [mode]”Cleans up the home directories of a host removed from the NFS share: dead XDG
symlinks removed, .bak backups restored. check (default) writes nothing and
shows what apply would do. hosts is a comma-separated list, or all. See
Leaving the NFS home share.
just nfs-cleanup myserver # dry run, writes nothingjust nfs-cleanup myserver apply # actual execution✳️ fix-boot <hôte>
Section titled “✳️ fix-boot <hôte>”Reinstalls the bootloader with NIXOS_INSTALL_BOOTLOADER=1.
just fix-boot myserver✳️ fix-gdm-greeters <hôtes> [check|apply]
Section titled “✳️ fix-gdm-greeters <hôtes> [check|apply]”Realigns the UIDs of gdm-greeter* accounts with those of nixpkgs.
See Troubleshooting.
just fix-gdm-greeters poste-01,poste-02 # diagnostic, n'écrit rienjust fix-gdm-greeters poste-01,poste-02 applySecret management commands
Section titled “Secret management commands”Passwords and keys are encrypted with SOPS. These commands manage them without manipulating encrypted files by hand.
✳️ sops ⭐
Section titled “✳️ sops ⭐”Opens usr/secrets/secrets.yaml in vim (as user nix).
just sops✳️ invite <user> [mode] [hash] ⭐
Section titled “✳️ invite <user> [mode] [hash] ⭐”Welcomes a user or resets their access: session password, Kanidm link, vault invitation, welcome sheet to copy. An already defined access is only replaced after confirmation.
| Mode | For | Kanidm link |
|---|---|---|
normal / n (default) | Non-technical | 1 h, for the admin |
advanced / a | Technical | 24 h, for the user |
just invite alice # non-technicaljust invite alice advanced # technicaljust invite alice a '<hash>' # technical, fingerprint sent remotely✳️ passwd-default
Section titled “✳️ passwd-default”Records the fleet’s reference password (bcrypt hash in sops).
Does not configure any account: just passwd <utilisateur> takes care of it.
just passwd-default✳️ passwd <user> [fingerprint] ⭐
Section titled “✳️ passwd <user> [fingerprint] ⭐”Updates a user’s session password, or records the fingerprint they sent
(mkpasswd -m sha-512, in single quotes).
just passwd darkonejust passwd darkone '<fingerprint>'✳️ yubikey <user> [key] [action]
Section titled “✳️ yubikey <user> [key] [action]”Enrolls a YubiKey (main by default, or backup) for a user: PAM
(session/sudo), LUKS and Kanidm enrollment link, in a single pass on the
admin machine. action=revoke revokes the key across all machines at next
deployment. See Strong authentication.
just yubikey darkone # enrolls the primary keyjust yubikey darkone backup # enrolls the backup keyjust yubikey darkone main revoke✳️ rotate init|push-keys|finalize
Section titled “✳️ rotate init|push-keys|finalize”Rotation of the age key /etc/sops/age/infra.key in 3 steps with integrity
checks.
| Step | Action |
|---|---|
init | Generates a new key, keeps the old one, re-encrypts secrets |
push-keys | Pushes the combined key (new + old) to all hosts |
finalize | Verifies all hosts have the new key, removes the old one |
just rotate initjust rotate push-keysjust rotate finalizeAdvanced commands
Section titled “Advanced commands”These commands cover specific features: provisioning the Matrix alert bot and managing Kanidm replication.
✳️ configure-alert-bot
Section titled “✳️ configure-alert-bot”Creates or refreshes the Matrix bot, the webhook secret, and the alert and incident channels from the network.matrix section of config.yaml. The bot account is created on the Matrix host with dnf-mas, via SSH.
just configure-alert-bot✳️ send-msg
Section titled “✳️ send-msg”Sends a message to an alert channel (warnings or incidents), Markdown
body on standard input. Channels and token come from the project :
the caller only writes the text. Exit codes : 10 nothing configured,
11 message rejected by the server.
just send-msg warnings < rapport.md✳️ idm-sync-certs
Section titled “✳️ idm-sync-certs”Collects Kanidm replication certificates from all fleet nodes
into usr/secrets/replication/.
just idm-sync-certs✳️ idm-fix-replica <suppl> <cons>
Section titled “✳️ idm-fix-replica <suppl> <cons>”Analyzes the health of Kanidm replication without modifying anything. Takes the supplier node (HCS) and the list of consumers (gateways, comma-separated).
just idm-fix-replica hcs agate,gwCo-development commands
Section titled “Co-development commands”At the root of a co-development project. Git commands operate on all
repositories of the project (default: src/*/, dnf, doc, and the
root). The short alias for git is g.
🔗 git <cmd> [project]
Section titled “🔗 git <cmd> [project]”Runs any git command on one or all projects.
just git "log --oneline -5" # latest commits of all projectsjust git "status" dnf # git status on dnf/ onlyjust git "remote -v" # remotes of all projects🔗 commit <message> [project] ⭐
Section titled “🔗 commit <message> [project] ⭐”add -A + commit -m on one or all projects. If the message is
identical to the latest commit, the recipe amends instead of creating a new
commit.
On all projects, the root is processed last, after update-dnf: its
commit pins the revision of dnf/ that was just committed.
just commit "fix(net): update dns config"just commit "fix(net): update dns config" dnf # dnf/ only🔗 amend [project] ⭐
Section titled “🔗 amend [project] ⭐”Adds the current changes to the latest commit of each project
(--no-edit). On all projects, the root lock is then realigned to dnf/.
just amend🔗 status [project] ⭐
Section titled “🔗 status [project] ⭐”Displays the git status of one or all projects.
just status🔗 diff [project]
Section titled “🔗 diff [project]”Displays the git diff of one or all projects.
just diff🔗 push [project] ⭐
Section titled “🔗 push [project] ⭐”Checks for an upstream branch and ahead commits before pushing.
just push🔗 pull [project]
Section titled “🔗 pull [project]”Pulls the latest changes for one or all projects.
just pull🔗 git-last-log
Section titled “🔗 git-last-log”Displays the latest commit message for all projects, formatted and aligned.
just git-last-log🔗 git-show-repos
Section titled “🔗 git-show-repos”Displays the list of repositories that git commands iterate over.
just git-show-repos🔗 gen-build
Section titled “🔗 gen-build”Builds the generator binary (src/generator/).
just gen-build🔗 gen-test
Section titled “🔗 gen-test”Runs the generator unit tests.
just gen-test🔗 cat [host] ⭐
Section titled “🔗 cat [host] ⭐”Chains clean → amend → apply-local test (or apply-verbose <host>).
just cat # tests locallyjust cat myserver # applies on myserver🔗 versions
Section titled “🔗 versions”Displays the version, latest tag and branch of each repository, along with the generator release pinned by the framework.
just versions🔗 release [release-level]
Section titled “🔗 release [release-level]”Publishes the whole ecosystem (generator, fleet-update, framework, documentation
and project templates) after checks and simulations. See The release
train.
just releaseAlias summary
Section titled “Alias summary”| Alias | Command | Context |
|---|---|---|
a | apply | ✳️ |
al | apply-local | ✳️ |
av | apply-verbose | ✳️ |
c | clean | 💠 |
d | develop | 💠 |
e | enter | ✳️ |
g | git | 🔗 |
amend | git-amend | 🔗 |
commit | git-commit | 🔗 |
diff | git-diff | 🔗 |
pull | git-pull | 🔗 |
push | git-push | 🔗 |
status | git-status | 🔗 |
rd | remote-desktop | ✳️ |