Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,23 @@ nixup # NixOS: sudo nixos-rebuild switch --flake ~/repos/dots
There is also `nixboot` on NixOS hosts to stage a change for the next reboot
without switching immediately.

### Build here, deploy to a remote NixOS host
### Deploy to a remote host

`nixos-rebuild` is available natively on NixOS hosts but not on home-manager-only
or nix-darwin hosts. When deploying from one of those, bring it in via `nix shell`:
Preferred: [deploy-rs](https://github.com/serokell/deploy-rs), which handles
build/copy/activate and automatically rolls back if the new generation breaks
SSH connectivity. See the [Deploying](README.md#deploying) section of
`README.md` for full details, usage, and scope.

```bash
nix run .#deploy-rs -- .#<hostname> # build, copy, activate, confirm
nix run .#deploy-rs -- .#<hostname> --dry-activate # preview without switching
nix run .#deploy-rs -- .#<hostname> --skip-checks # required when running from mightymac (see README)
```

For hosts/scenarios outside deploy-rs's scope, or as a manual fallback,
`nixos-rebuild` can also be invoked directly - available natively on NixOS
hosts but not on home-manager-only or nix-darwin hosts, where it needs to be
brought in via `nix shell`:

```bash
nix shell nixpkgs#nixos-rebuild -c nixos-rebuild switch \
Expand Down
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
This repo is a Nix flake that manages most of my setup on macOS and fully manages machines I have that run NixOS as their operating system. It also contains as much configruation as I can make work on other Linux distros such as Ubuntu.

- [Flake structure](#flake-structure)
- [Deploying](#deploying)
- [Formatting and CI](#formatting-and-ci)
- [Historical bits](#historical-bits)
- [Host Bootstrapping](#host-bootstrapping)
Expand Down Expand Up @@ -38,6 +39,40 @@ This repo is a Nix flake that manages most of my setup on macOS and fully manage
- `modules/hosts/darwin/` - macOS host configs
- `modules/hosts/home-manager-only/` - Home Manager-only configs

## Deploying

Local changes are applied with the `nixup`/`nixdiff` aliases (see `AGENTS.md`
for the exact commands they wrap). For deploying to a remote host without
SSHing in and running `nixup` by hand, use
[deploy-rs](https://github.com/serokell/deploy-rs):

```bash
nix run .#deploy-rs -- .#<host> # build, copy, activate, confirm
nix run .#deploy-rs -- .#<host> --dry-activate # preview without switching
```

Every node in `deploy.nodes` (`flake.nix`) builds itself (`remoteBuild =
true`), so this can be run from any machine that can reach the target over
SSH - not just `mightymac`. Hostnames are resolved via Tailscale MagicDNS, so
no domain needs to be configured anywhere in this repo.

deploy-rs's automatic rollback (magic-rollback) is the main reason to use it
over a manual `nixos-rebuild switch --target-host`: if the new generation
breaks SSH connectivity, it rolls back on its own - important for
`kiosk-entryway` and `kiosk-gene-desk`, which have no keyboard normally
attached and would otherwise need a physical visit to recover.

`--skip-checks` is required when deploying from `mightymac` specifically:
deploy-rs's own pre-deploy `nix flake check` tries to build every system's
derivations locally regardless of any node's `remoteBuild` setting, and
mightymac can't build `x86_64-linux` at all (no local builder for it). Run
`nix flake check` separately beforehand instead - it validates the same
things without attempting to build anything locally that can't be.

Scope: all NixOS hosts plus `mightymac`. `AirPuppet`/`Blue-Rock` and
home-manager-only hosts stay on their existing `darwin-rebuild`/`home-manager
switch` workflows.

## Formatting and CI

This repo uses the following tools for code quality:
Expand Down
88 changes: 80 additions & 8 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

71 changes: 71 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@
inputs.nixpkgs.follows = "nixpkgs";
};

# Codified remote deploys (build/copy/activate + automatic rollback)
deploy-rs = {
url = "github:serokell/deploy-rs";
inputs.nixpkgs.follows = "nixpkgs";
};

flox = {
url = "github:flox/flox/v1.4.4";
};
Expand Down Expand Up @@ -267,6 +273,62 @@
#};
}; # end nixosConfigurations

# Codified remote deploys (`nix run .#deploy-rs -- .#<host>`) - see
# sshUser/profiles.system wiring in lib/mkDeployNode.nix. Every node
# builds itself (remoteBuild = true) so the deploy can be invoked
# from any machine that can reach the target over SSH, not just
# mightymac. `hostname` is used directly as the SSH target, resolved
# via Tailscale MagicDNS - deliberately not a hardcoded FQDN (e.g.
# private-flake's own config.private-flake.tailnetDomain), since a
# baked-in default read at flake-eval time wouldn't reflect a
# per-host override of that setting anyway.
deploy.nodes = {
bigboy = localLib.mkDeployNode {
hostname = "bigboy";
system = "x86_64-linux";
fastConnection = true;
remoteBuild = true;
};
hetznix01 = localLib.mkDeployNode {
hostname = "hetznix01";
system = "x86_64-linux";
fastConnection = false;
remoteBuild = true;
};
hetznix02 = localLib.mkDeployNode {
hostname = "hetznix02";
system = "aarch64-linux";
fastConnection = false;
remoteBuild = true;
};
kiosk-entryway = localLib.mkDeployNode {
hostname = "kiosk-entryway";
system = "x86_64-linux";
fastConnection = true;
remoteBuild = true;
};
kiosk-gene-desk = localLib.mkDeployNode {
hostname = "kiosk-gene-desk";
system = "aarch64-linux";
fastConnection = true;
remoteBuild = true;
};
mightymac = localLib.mkDeployNode {
hostname = "mightymac";
system = "aarch64-darwin";
fastConnection = true;
remoteBuild = true;
darwin = true;
sshUser = "gene.liverman"; # matches mkDarwinHost's username override for this host below
};
nixnuc = localLib.mkDeployNode {
hostname = "nixnuc";
system = "x86_64-linux";
fastConnection = true;
remoteBuild = true;
};
}; # end deploy.nodes

# Home Manager (only) users
homeConfigurations = {
gene-x86_64-linux = localLib.mkHomeConfig {
Expand All @@ -288,6 +350,15 @@
pkgs = nixpkgs.legacyPackages.${system};
in
import ./pkgs { inherit inputs pkgs; }
// {
deploy-rs = inputs.deploy-rs.packages.${system}.deploy-rs;
}
);

# Validates every deploy.nodes entry builds (nix flake check) -
# pure evaluation, zero deploy risk.
checks = builtins.mapAttrs (
system: deployLib: deployLib.deployChecks self.deploy
) inputs.deploy-rs.lib;
};
}
2 changes: 2 additions & 0 deletions lib/default.nix
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{ inputs, ... }:
let
mkDarwinHost = import ./mkDarwinHost.nix { inherit inputs; };
mkDeployNode = import ./mkDeployNode.nix { inherit inputs; };
mkHomeConfig = import ./mkHomeConfig.nix { inherit inputs; };
mkNixosHost = import ./mkNixosHost.nix { inherit inputs; };
genebeanLib = {
Expand All @@ -11,6 +12,7 @@ let
in
{
inherit (mkDarwinHost) mkDarwinHost;
inherit (mkDeployNode) mkDeployNode;
inherit (mkHomeConfig) mkHomeConfig;
inherit (mkNixosHost) mkNixosHost;
inherit genebeanLib;
Expand Down
24 changes: 24 additions & 0 deletions lib/mkDeployNode.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{ inputs, ... }:
{
mkDeployNode =
{
hostname, # matches nixosConfigurations.<hostname> (or darwinConfigurations.<hostname> when darwin = true); also used as-is for SSH, resolved via Tailscale MagicDNS
system,
fastConnection,
remoteBuild,
darwin ? false,
sshUser ? "gene", # mkDarwinHost defaults to "gene" too, but some darwin hosts (mightymac, Blue-Rock) override username to "gene.liverman" - pass that through explicitly for those nodes
}:
{
inherit hostname sshUser;
inherit fastConnection remoteBuild;
profiles.system = {
user = "root";
path =
if darwin then
inputs.deploy-rs.lib.${system}.activate.darwin inputs.self.darwinConfigurations.${hostname}
else
inputs.deploy-rs.lib.${system}.activate.nixos inputs.self.nixosConfigurations.${hostname};
};
};
}
Loading
Loading