Simple, opinionated wrappers around nixos-rebuild, nix-darwin, and home-manager.
All wrappers are in the form COMMAND MACHINE_NAME [NIX_OPTIONS], example:
# build 'bigmachine' remotely on 'myname@bigmachine', switch 'bigmachine' to the built config
switch-pull myname@bigmachine --show-traceFlakem assumes that MACHINE_NAME is the same in both flake.nix and one of:
- IP address
- DNS name
hoststring in SSH config
For NixOS, the target should be an installed NixOS system; initial deployment can be done with nixos-anywhere, eg:
nix run github:nix-community/nixos-anywhere -- \
--flake .#HOSTNAME --build-on-remote root@HOST_IPThe build and switch commands auto-detect Darwin hosts via uname -s
and use nix build .#darwinConfigurations... instead of nixos-rebuild.
Darwin switch updates /nix/var/nix/profiles/system before activating.
build-there is NixOS-only.
switch-push and switch-pull support NixOS and Darwin targets declared
in the flake.
switch-pull and switch-push accept an optional leading action:
switch activates the target immediately.
boot sets the next NixOS boot generation without activating it.
If no action is given, they default to switch.
Darwin remote commands always activate, even if boot is supplied.
# build machine locally (auto-detects NixOS or Darwin)
nix run github:siriobalmelli/flakem/master#build $(hostname)
# build machine locally, apply locally (auto-detects NixOS or Darwin)
nix run github:siriobalmelli/flakem/master#switch $(hostname)
# build machine remotely (NixOS only)
nix run github:siriobalmelli/flakem/master#build-there bigmachine # can also be 'myuser@bigmachine'
# build machine remotely, apply remotely
nix run github:siriobalmelli/flakem/master#switch-pull myuser@bigmachine # can also be 'bigmachine'
# build machine remotely, set as next boot generation without activating
nix run github:siriobalmelli/flakem/master#switch-pull boot myuser@bigmachine
# build machine locally, apply remotely
nix run github:siriobalmelli/flakem/master#switch-push bigmachine # can also be 'myuser@bigmachine'
# build machine locally, set as next boot generation without activating
nix run github:siriobalmelli/flakem/master#switch-push boot bigmachine
# switch-pull boot, followed by a reboot and a nix-collect-garbage
nix run github:siriobalmelli/flakem/master#switch-pull-reset root@10.3.2.1 another-machine
# switch-push boot, followed by a reboot and a nix-collect-garbage
nix run github:siriobalmelli/flakem/master#switch-push-reset 192.168.42.43 internal-machine
# timeout-loop waiting for successful ssh
nix run github:siriobalmelli/flakem/master#ssh-wait my-host "uname -a"
# decrypt and deploy a SOPS private key to a machine
nix run github:siriobalmelli/flakem/master#ssh-deploy my-hostStandalone Home-Manager deployment commands for homeConfigurations in your flake.
# switch home-manager config locally (auto-detects user@hostname)
nix run github:siriobalmelli/flakem/master#hm-switch
# switch home-manager config locally (explicit target)
nix run github:siriobalmelli/flakem/master#hm-switch sirio@panigale --show-trace
# build home-manager locally, copy closure to remote, activate remotely
nix run github:siriobalmelli/flakem/master#hm-push sirio@panigale
# hm-push with explicit flake target different from SSH host
nix run github:siriobalmelli/flakem/master#hm-push sirio@192.168.1.10 panigale
# ssh to remote, build and activate home-manager there (flake must exist on remote)
nix run github:siriobalmelli/flakem/master#hm-pull sirio@panigale{
description = "My Flake";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
flake-utils.url = "github:numtide/flake-utils";
flakem = {
url = "github:siriobalmelli/flakem";
inputs.nixpkgs.follows = "nixpkgs";
inputs.flake-utils.follows = "flake-utils";
};
};
outputs = {
self,
nixpkgs,
flake-utils,
flakem,
}: let
inherit (flake-utils.lib) eachDefaultSystem;
in
eachDefaultSystem (system: let
pkgs = import nixpkgs {
inherit system;
overlays = [self.overlays.default];
};
in {
packages = {
inherit (pkgs) build build-there hm-push hm-pull hm-switch ssh-deploy ssh-wait switch switch-pull switch-pull-reset switch-push switch-push-reset;
# ... other packages here
};
})
// {
nixosConfigurations = {
bigmachine = nixpkgs.lib.nixosSystem {
# NixOS configuration
};
};
};
}Then, from that flake's directory:
# build and deploy remotely
nix run .#switch-pull bigmachine
# etc ...On NixOS:
# called from a flake with 'specialArgs = { inherit inputs; };'
{inputs, lib, ...}: with lib; {
imports = [
inputs.flakem.nixosModules.default
];
packages.flakem.enable = mkDefault true;
}On Darwin (nix-darwin):
# called from a flake with 'specialArgs = { inherit inputs; };'
{inputs, lib, ...}: with lib; {
imports = [
inputs.flakem.darwinModules.default
];
packages.flakem.enable = mkDefault true;
}Both modules expose all flakem commands (system + Home-Manager).
System commands (build, switch, etc.) detect the OS at runtime via uname -s:
- Linux: uses
nixos-rebuildwith--fast --use-remote-sudo --use-substitutes - Darwin: uses
nix build .#darwinConfigurations.<host>.systemfollowed by./result/activate
Remote commands (build-there, switch-push, switch-pull, etc.) always use nixos-rebuild
and are NixOS-only.
Home-Manager commands (hm-switch, hm-push, hm-pull) use home-manager CLI
or direct activation of the built activationPackage.
All scripts execute with set -x to show the exact commands being run.
- CI with
nix flake update - Remote Darwin deployment support