add hosts

This commit is contained in:
2026-07-28 00:19:14 +09:00
parent 09a4fd83a7
commit b1954ba5be
11 changed files with 519 additions and 40 deletions
+85 -15
View File
@@ -487,6 +487,59 @@ A host registry may use a specification like this:
```nix ```nix
# hosts/default.nix # hosts/default.nix
{ {
nix-example = {
system = "x86_64-linux";
stateVersion = "26.05";
user = "moons";
path = ./nix-example;
profiles = [
"base"
"interface.cli"
"platform.vm"
"workload.development"
"workload.remote-access"
];
};
ops = {
system = "x86_64-linux";
stateVersion = "26.05";
user = "moons";
path = ./ops;
profiles = [
"base"
"interface.cli"
"platform.vm"
"workload.remote-access"
];
};
internal-app-01 = {
system = "x86_64-linux";
stateVersion = "26.05";
user = "moons";
path = ./internal-app-01;
profiles = [
"base"
"interface.cli"
"platform.vm"
"workload.server"
];
};
installer = {
system = "x86_64-linux";
stateVersion = "26.05";
user = "moons";
path = ./installer;
homeManager = false;
profiles = [ "base" ];
};
x1g9 = { x1g9 = {
system = "x86_64-linux"; system = "x86_64-linux";
stateVersion = "26.05"; stateVersion = "26.05";
@@ -544,14 +597,16 @@ A host registry may use a specification like this:
} }
``` ```
The current role assignment is intentional: x1g9 is a full NixOS desktop with The current role assignment is intentional: nix-example is the development VM;
niri, GNOME, ly, the shared Linux desktop applications, and the personal ops is the remote-access VM with host-specific static networking;
workload. x1g13 is the secure NixOS development and personal ThinkPad, with the internal-app-01 is the container server VM; and installer builds the minimal
same desktop sessions plus Tailscale client, SOPS, Secure Boot, and TPM-backed installation ISO without Home Manager. x1g9 is a full NixOS desktop with niri,
disk unlock. m2 is the daily-use macOS development and personal machine with GNOME, ly, the shared Linux desktop applications, and the personal workload.
the macOS interface defaults. Keep the desktop sessions independently x1g13 is the secure NixOS development and personal ThinkPad, with the same
selectable, and keep the development and personal profiles usable across NixOS desktop sessions plus Tailscale client, SOPS, Secure Boot, and TPM-backed disk
and Darwin. unlock. m2 is the daily-use macOS development and personal machine with the
macOS interface defaults. Keep the desktop sessions independently selectable,
and keep the development and personal profiles usable across NixOS and Darwin.
Treat entries in `profiles` and the exceptional `applications` field as IDs Treat entries in `profiles` and the exceptional `applications` field as IDs
relative to their respective category roots. Add the category prefixes during relative to their respective category roots. Add the category prefixes during
@@ -581,6 +636,17 @@ configuration fragments. For example:
```text ```text
hosts/ hosts/
├── installer/
│ └── nixos.nix
├── internal-app-01/
│ ├── nixos.nix
│ └── hardware-configuration.nix
├── nix-example/
│ ├── nixos.nix
│ └── hardware-configuration.nix
├── ops/
│ ├── nixos.nix
│ └── hardware-configuration.nix
├── x1g9/ ├── x1g9/
│ ├── nixos.nix │ ├── nixos.nix
│ └── hardware-configuration.nix │ └── hardware-configuration.nix
@@ -606,9 +672,10 @@ Derive the system class from the host's `system`:
- A host with integrated Home Manager additionally receives `home.nix`. - A host with integrated Home Manager additionally receives `home.nix`.
Home Manager is additive, not a system class mutually exclusive with NixOS or Home Manager is additive, not a system class mutually exclusive with NixOS or
nix-darwin. The supported combinations are NixOS plus Home Manager and nix-darwin. Normal machine configurations combine NixOS or nix-darwin with Home
nix-darwin plus Home Manager. If standalone Home Manager is supported later, add Manager; the installer ISO explicitly sets `homeManager = false`. If standalone
an explicit host kind because `system` alone cannot distinguish it from NixOS. Home Manager is supported later, add an explicit host kind because `system`
alone cannot distinguish it from NixOS.
Do not duplicate reusable settings in hosts, but do not force genuinely Do not duplicate reusable settings in hosts, but do not force genuinely
machine-specific values into a common unit merely to remove a host-local line. machine-specific values into a common unit merely to remove a host-local line.
@@ -694,10 +761,13 @@ For profile changes, additionally:
required host-owned values. required host-owned values.
- When adding a Darwin application fragment, verify the resulting - When adding a Darwin application fragment, verify the resulting
`homebrew.casks` selection as well as module evaluation. `homebrew.casks` selection as well as module evaluation.
- Preserve the intended host roles: x1g9 provides niri, GNOME, ly, and the - Preserve the intended host roles: nix-example remains the development VM;
personal application set; x1g13 additionally provides the development, ops remains the statically networked remote-access VM; internal-app-01 remains
Tailscale client, secrets, Secure Boot, and TPM storage roles; m2 remains the the container server VM; installer remains the Home Manager-free installation
daily-use development and personal machine. ISO; x1g9 provides niri, GNOME, ly, and the personal application set; x1g13
additionally provides the development, Tailscale client, secrets, Secure Boot,
and TPM storage roles; m2 remains the daily-use development and personal
machine.
## Commit and Pull Request Guidelines ## Commit and Pull Request Guidelines
+53
View File
@@ -1,4 +1,57 @@
{ {
nix-example = {
system = "x86_64-linux";
stateVersion = "26.05";
user = "moons";
path = ./nix-example;
profiles = [
"base"
"interface.cli"
"platform.vm"
"workload.development"
"workload.remote-access"
];
};
ops = {
system = "x86_64-linux";
stateVersion = "26.05";
user = "moons";
path = ./ops;
profiles = [
"base"
"interface.cli"
"platform.vm"
"workload.remote-access"
];
};
internal-app-01 = {
system = "x86_64-linux";
stateVersion = "26.05";
user = "moons";
path = ./internal-app-01;
profiles = [
"base"
"interface.cli"
"platform.vm"
"workload.server"
];
};
installer = {
system = "x86_64-linux";
stateVersion = "26.05";
user = "moons";
path = ./installer;
homeManager = false;
profiles = [ "base" ];
};
x1g9 = { x1g9 = {
system = "x86_64-linux"; system = "x86_64-linux";
stateVersion = "26.05"; stateVersion = "26.05";
+189
View File
@@ -0,0 +1,189 @@
{
pkgs,
lib,
modulesPath,
...
}:
{
imports = [ "${modulesPath}/installer/cd-dvd/installation-cd-minimal.nix" ];
boot.zfs.forceImportRoot = false;
networking = {
hostName = "nixos-installer";
networkmanager = {
enable = true;
wifi.powersave = false;
};
};
services.openssh = {
enable = true;
settings = {
PermitRootLogin = "prohibit-password";
PasswordAuthentication = false;
KbdInteractiveAuthentication = false;
PubkeyAuthentication = "yes";
};
};
users.users.root.openssh.authorizedKeys.keys = [
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIKhxDkucmeCor6CKoXAua7DgDSzuXrZOtpdkyzQxz5+aAAAABHNzaDo= moons@moons14.com"
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIN6hZJyng/5LgFKPjR6uZAd/00UkO0vN0uQOoIvfSELdAAAABHNzaDo= moons@moons14.com"
];
environment.systemPackages = with pkgs; [
git
disko
sops
age
ssh-to-age
age-plugin-yubikey
yubikey-manager
pcsc-tools
mkpasswd
rsync
vim
wget
curl
jq
parted
cryptsetup
btrfs-progs
];
services.pcscd.enable = true;
environment.etc."installer-help.txt".text = ''
╔══════════════════════════════════════════════════════════════╗
║ NixOS Installer ISO ║
╠══════════════════════════════════════════════════════════════╣
║ ║
║ SSH Access: ║
║ ssh root@<ip-address> ║
║ ║
║ Network Setup: ║
║ Wired: Auto-configured via DHCP ║
║ WiFi: nmcli device wifi connect <SSID> --ask ║
║ ║
║ Installation Workflow: ║
║ ║
║ 1. Clone dotfiles: ║
║ git clone git@github.com:moons-14/dotfiles.git ~/dotfiles║
║ ║
║ 2. Generate SSH host key for new host: ║
║ ssh-keygen -t ed25519 -f /tmp/ssh_host_ed25519_key -N "" ║
║ ║
║ 3. Get age public key from SSH host key: ║
║ ssh-to-age -i /tmp/ssh_host_ed25519_key.pub ║
║ ║
║ 4. Add age key to .sops.yaml: ║
║ cd ~/dotfiles ║
║ # Edit .sops.yaml and add the age key ║
║ # Add new host entry to creation_rules ║
║ ║
║ 5. Re-encrypt secrets: ║
║ sops updatekeys secrets/common/system.yaml ║
║ sops updatekeys secrets/hosts/<host>/*.yaml ║
║ ║
║ 6. Create disko.nix for new host: ║
║ # Check disk devices ║
║ lsblk -f ║
║ ║
║ # Create hosts/<host>/disko.nix ║
║ # Example: LUKS + btrfs ║
║ # See hosts/x1g13/disko.nix for reference ║
║ ║
║ 7. Partition disk with disko: ║
║ nix run github:nix-community/disko -- \ ║
║ --mode disko hosts/<host>/disko.nix ║
║ ║
║ 8. Copy host key to installed system: ║
║ mkdir -p /mnt/etc/ssh ║
║ cp /tmp/ssh_host_ed25519_key* /mnt/etc/ssh/ ║
║ chmod 600 /mnt/etc/ssh/ssh_host_ed25519_key ║
║ ║
║ 9. Install NixOS: ║
║ nixos-install --flake ~/dotfiles#<host> ║
║ ║
║ Disko Configuration Examples: ║
║ ║
║ Simple (no encryption): ║
║ disko.devices.disk.main = { ║
║ type = "disk"; ║
║ device = "/dev/sda"; ║
║ content = { ║
║ type = "gpt"; ║
║ partitions = { ║
║ ESP = { size = "512M"; type = "EF00"; ║
║ content = { type = "filesystem"; ║
║ format = "vfat"; mountpoint = "/boot"; }; }; ║
║ root = { size = "100%"; ║
║ content = { type = "filesystem"; ║
║ format = "ext4"; mountpoint = "/"; }; }; ║
║ }; ║
║ }; ║
║ }; ║
║ ║
║ LUKS + btrfs (see hosts/x1g13/disko.nix): ║
║ - Use partuuid for device path ║
║ - Set askPassword = true for LUKS ║
║ - Configure btrfs subvolumes ║
║ ║
╚══════════════════════════════════════════════════════════════╝
'';
systemd.services.installer-banner = {
description = "Display installer help on console";
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "oneshot";
ExecStart = "${pkgs.coreutils}/bin/cat /etc/installer-help.txt";
StandardOutput = "tty";
TTYPath = "/dev/tty1";
};
};
systemd.services.display-ip = {
description = "Display IP address on console";
wantedBy = [ "multi-user.target" ];
after = [ "network-online.target" ];
wants = [ "network-online.target" ];
serviceConfig = {
Type = "oneshot";
ExecStart = pkgs.writeShellScript "display-ip" ''
sleep 2
echo ""
echo "=== Network Interfaces ==="
${pkgs.iproute2}/bin/ip -4 addr show | ${pkgs.gnugrep}/bin/grep inet
echo ""
echo "=== SSH Access ==="
for ip in $(${pkgs.iproute2}/bin/ip -4 addr show | ${pkgs.gnugrep}/bin/grep -oP 'inet \K[\d.]+' | ${pkgs.gnugrep}/bin/grep -v '127.0.0.1'); do
echo " ssh root@$ip"
done
echo ""
'';
StandardOutput = "tty";
TTYPath = "/dev/tty1";
};
};
nix = {
settings = {
experimental-features = [
"nix-command"
"flakes"
];
trusted-users = [ "root" ];
};
extraOptions = ''
experimental-features = nix-command flakes
'';
};
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}
@@ -0,0 +1,36 @@
# Do not modify this file! It was generated by `nixos-generate-config` and may
# be overwritten by future invocations.
{ lib, modulesPath, ... }:
{
imports = [ (modulesPath + "/profiles/qemu-guest.nix") ];
boot.initrd.availableKernelModules = [
"ata_piix"
"uhci_hcd"
"virtio_pci"
"virtio_scsi"
"sd_mod"
"sr_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "/dev/disk/by-uuid/1b12ab98-2537-4207-a3f4-bb8ba7b53b00";
fsType = "ext4";
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/8365-C778";
fsType = "vfat";
options = [
"fmask=0077"
"dmask=0077"
];
};
swapDevices = [ ];
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}
+3
View File
@@ -0,0 +1,3 @@
{
imports = [ ./hardware-configuration.nix ];
}
@@ -0,0 +1,36 @@
# Do not modify this file! It was generated by `nixos-generate-config` and may
# be overwritten by future invocations.
{ lib, modulesPath, ... }:
{
imports = [ (modulesPath + "/profiles/qemu-guest.nix") ];
boot.initrd.availableKernelModules = [
"ata_piix"
"uhci_hcd"
"virtio_pci"
"virtio_scsi"
"sd_mod"
"sr_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "/dev/disk/by-uuid/8f0eaec6-5dc9-4821-aa8d-fb6809b5a5bf";
fsType = "ext4";
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/201C-961B";
fsType = "vfat";
options = [
"fmask=0077"
"dmask=0077"
];
};
swapDevices = [ ];
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}
+3
View File
@@ -0,0 +1,3 @@
{
imports = [ ./hardware-configuration.nix ];
}
+36
View File
@@ -0,0 +1,36 @@
# Do not modify this file! It was generated by `nixos-generate-config` and may
# be overwritten by future invocations.
{ lib, modulesPath, ... }:
{
imports = [ (modulesPath + "/profiles/qemu-guest.nix") ];
boot.initrd.availableKernelModules = [
"ata_piix"
"uhci_hcd"
"virtio_pci"
"virtio_scsi"
"sd_mod"
"sr_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "/dev/disk/by-uuid/69fa2193-1e4f-438a-8898-5de8a3f36e5b";
fsType = "ext4";
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/D09B-4277";
fsType = "vfat";
options = [
"fmask=0077"
"dmask=0077"
];
};
swapDevices = [ ];
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}
+51
View File
@@ -0,0 +1,51 @@
{
imports = [ ./hardware-configuration.nix ];
networking = {
useDHCP = false;
interfaces = {
ens18 = {
useDHCP = false;
ipv4.addresses = [
{
address = "10.50.128.20";
prefixLength = 24;
}
];
};
ens19 = {
useDHCP = false;
ipv4.addresses = [
{
address = "10.50.7.101";
prefixLength = 24;
}
];
};
ens20 = {
useDHCP = false;
ipv4.routes = [
{
address = "10.50.64.0";
prefixLength = 24;
via = "10.50.82.1";
}
];
ipv4.addresses = [
{
address = "10.50.82.10";
prefixLength = 24;
}
];
};
};
defaultGateway = {
address = "10.50.128.1";
interface = "ens18";
};
};
}
+24 -24
View File
@@ -20,30 +20,30 @@ when removing it from any supported host would make that host invalid.
## Compatibility ## Compatibility
| Profile | Supported host class | | Profile | Supported host class |
| ------------------------------------ | ------------------------------------- | | ------------------------------------ | --------------------------------------------- |
| `base` | NixOS, macOS | | `base` | NixOS, macOS |
| `interface.cli` | NixOS, macOS with Home Manager | | `interface.cli` | NixOS, macOS with Home Manager |
| `interface.gui` | NixOS, macOS with Home Manager | | `interface.gui` | NixOS, macOS with Home Manager |
| `interface.macos` | macOS | | `interface.macos` | macOS |
| `interface.linux-desktop` | NixOS with Home Manager | | `interface.linux-desktop` | NixOS with Home Manager |
| `interface.gnome` | NixOS with Home Manager | | `interface.gnome` | NixOS with Home Manager |
| `interface.niri` | NixOS with Home Manager | | `interface.niri` | NixOS with Home Manager |
| `platform.nixos` | NixOS | | `platform.nixos` | NixOS |
| `platform.desktop` | Physical NixOS desktop | | `platform.desktop` | Physical NixOS desktop |
| `platform.laptop` | Physical NixOS laptop | | `platform.laptop` | Physical NixOS laptop |
| `platform.thinkpad-x1` | Intel ThinkPad X1 running NixOS | | `platform.thinkpad-x1` | Intel ThinkPad X1 running NixOS |
| `platform.vm` | QEMU NixOS guest | | `platform.vm` | UEFI QEMU NixOS guest with NFS client support |
| `workload.development` | NixOS, macOS with Home Manager | | `workload.development` | NixOS, macOS with Home Manager |
| `workload.personal` | NixOS, macOS with Home Manager | | `workload.personal` | NixOS, macOS with Home Manager |
| `workload.remote-access` | NixOS, macOS | | `workload.remote-access` | NixOS, macOS |
| `workload.server` | NixOS, macOS with Home Manager | | `workload.server` | NixOS, macOS with Home Manager |
| `networking.tailscale-client` | NixOS, macOS | | `networking.tailscale-client` | NixOS, macOS |
| `networking.tailscale-subnet-router` | NixOS | | `networking.tailscale-subnet-router` | NixOS |
| `security.fingerprint` | NixOS, macOS | | `security.fingerprint` | NixOS, macOS |
| `security.secrets` | NixOS, macOS | | `security.secrets` | NixOS, macOS |
| `security.secure-boot` | NixOS | | `security.secure-boot` | NixOS |
| `security.tpm-storage` | NixOS with a host-defined LUKS device | | `security.tpm-storage` | NixOS with a host-defined LUKS device |
Select independent concerns independently in `hosts/default.nix`. For example, Select independent concerns independently in `hosts/default.nix`. For example,
a NixOS desktop can combine `interface.gnome` and `interface.niri` to provide a NixOS desktop can combine `interface.gnome` and `interface.niri` to provide
+3 -1
View File
@@ -1,8 +1,10 @@
{ {
description = "QEMU NixOS guest"; description = "UEFI QEMU NixOS guest with NFS client support";
includes = [ includes = [
"profiles.platform.nixos" "profiles.platform.nixos"
"hardwares.qemu-guest" "hardwares.qemu-guest"
"systems.boot.nfs"
"systems.boot.uefi"
]; ];
} }