14 KiB
Morph for managing NixOS
Morph is a tool for managing existing NixOS hosts - basically a fancy wrapper around nix-build, nix copy, nix-env, nix/store…/bin/switch-to-configuration, scp and more. Morph supports updating multiple hosts in a row, and with support for health checks makes it fairly safe to do so.
Interestingly, it seems like I can just use my NixOps laptop profile…? stealin' it! that's nice.
Deploying My Laptops
My laptops are installed through my NixOS Automatic Partitioning Installer and carry My NixOS configuration for laptops, the "endpoint configuration".
let
endpointCfg = ../roles/endpoint;
# nixpkgsPin = (import ../versions.nix {}).nixpkgs;
# pkgs = import (builtins.fetchTarball nixpkgsPin) {};
pkgs = import <nixpkgs> {};
in {
network.pkgs = pkgs;
network.description = "my laptops";
network.enableRollback = true;
# meadow-crush = {config, pkgs, ...}:
# {
# imports = [ endpointCfg ../hosts/meadow-crush ];
# deployment.targetHost = "meadow-crush";
# deployment.targetUser = "root";
# system.stateVersion = "22.05";
# };
virtuous-cassette = {config, pkgs, ...}:
{
imports = [ endpointCfg ../hosts/virtuous-cassette ];
deployment.targetHost = "virtuous-cassette";
system.stateVersion = "22.05";
};
window-smoke = {config, pkgs, ...}:
{
imports = [ endpointCfg ../hosts/window-smoke ];
deployment.targetHost = "window-smoke";
# deployment.targetUser = "root";
# deployment.targetHost = "192.168.69.44";
system.stateVersion = "22.11"; #
};
rose-quine = {config, pkgs, ...}:
{
imports = [ endpointCfg ../hosts/rose-quine ];
deployment.targetHost = "rose-quine";
# deployment.targetUser = "root";
# deployment.targetHost = "192.168.69.31";
system.stateVersion = "23.05"; #
};
}
Meadow Crush
hosts/meadow-crush/default.nix
replaces the generated.nix
, basically, for my GPD Pocket:
{
imports = [ ./hardware-configuration.nix ../../nixos/gpd-pocket.nix ];
networking.hostName = "meadow-crush";
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
services.tailscale.authKey = "tskey-kqvV5P3CNTRL-K3bdvSJcUreG8nrGcDKXCh";
# networking.wireguard.interfaces.wg0 = {
# privateKeyFile = "/etc/wireguard-key/meadow-crush.key";
# ips = ["10.10.10.4/32"];
# };
networking.hostId = "c9ec7cad"; # required for zfs use
boot.initrd.luks.devices = {
"swap" = { name = "swap"; device = "/dev/mmcblk0p2"; preLVM = true; };
"root" = { name = "root"; device = "/dev/mmcblk0p3"; preLVM = true; };
};
fileSystems."/mnt/music" =
{ device = "/dev/disk/by-label/muzak";
fsType = "ext4";
noCheck = true;
};
}
I pull /rrix/complete-computing-environment/src/branch/exwm/nixlib/hosts/meadow-crush/hardware-configuration.nix with nixops:
nixops scp --from meadow-crush /etc/nixos/hardware-configuration.nix nixlib/hosts/meadow-crush/hardware-configuration.nix
I put my Wireguard configuration on the device (for now) using nixops scp
nixops ssh meadow-crush mkdir -p /etc/wireguard-key/ && \ nixops scp --to meadow-crush wireguard/meadow-crush.key /etc/wireguard-key/meadow-crush.key && \ nixops ssh meadow-crush chown 400 /etc/wireguard-key/meadow-crush.key
I need to make sure this stays in sync with my JustDoIt script!
Virtuous Cassette
Virtuous Cassette is my roam:Framework Laptop.
hosts/tres-ebow/default.nix
replaces the generated.nix
, basically, for my GPD Pocket:
{
imports = [ ./hardware-configuration.nix ];
networking.hostName = "virtuous-cassette";
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
services.xserver.dpi = 204;
# networking.wg-quick.interfaces.wg0 = {
# privateKeyFile = "/etc/wireguard-key/virtuous-cassette.key";
# address = ["10.10.10.13/32" "2620:fc:c000:0:1000::d/128"];
# };
# networking.wg-quick.interfaces.wg1 = {
# privateKeyFile = "/etc/wireguard-key/virtuous-cassette.key";
# address = ["10.10.10.13/32" "2620:fc:c000:0:1000::d/128"];
# };
services.tailscale.authKey = "tskey-kMJ8ZX2CNTRL-tDGQZ1dZQLZ9hnuGRgKXS";
networking.hostId = "754ccef7"; # required for zfs use
boot.initrd.luks.devices = {
"swap" = { name = "swap"; device = "/dev/nvme0n1p2"; preLVM = true; };
"root" = { name = "root"; device = "/dev/nvme0n1p3"; preLVM = true; };
};
}
Window Smoke
Window Smoke is my desktop. It runs my Endpoint Configuration and some roam:NixOS Tower Customizations
{ lib, ... }:
{
imports = [ ./hardware-configuration.nix ../../roles/desktop ];
networking.hostName = "window-smoke";
# boot.loader.grub.efiInstallAsRemovable = true;
# boot.loader.grub.efiSupport = true;
# boot.loader.grub.device = "nodev";
boot.loader.efi.canTouchEfiVariables = true;
boot.loader.systemd-boot.enable = true;
services.xserver.dpi = 204;
services.tailscale.authKey = "tskey-auth-k38z9b3CNTRL-DeWdeU2Zt4ccxM2RqHduzbu9h2D7mmP74";
networking.hostId = "141e1b4f"; # required for zfs use
boot.zfs.devNodes = lib.mkForce "/dev/disk/by-id/";
boot.initrd.luks.devices = {
"swap" = { name = "swap"; device = "/dev/nvme0n1p2"; preLVM = true; };
"root" = { name = "root"; device = "/dev/nvme0n1p3"; preLVM = true; };
};
fileSystems."/" =
{ device = "window-smoke/root";
fsType = "zfs";
};
fileSystems."/home" =
{ device = "window-smoke/home";
fsType = "zfs";
};
fileSystems."/nix" =
{ device = "window-smoke/nix";
fsType = "zfs";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/12CA-451F";
fsType = "vfat";
};
fileSystems."/media" =
{ device = "tank/media";
fsType = "zfs";
};
swapDevices =
[ { device = "/dev/disk/by-uuid/26776a6d-4e53-4e39-b0e5-5a540ce78406"; }
];
}
NEXT implement nixos encrypted secrets and make these safe! maybe hosts.toml for a lot of this too…
Rose Quine
Rose Quine is my roam:GPD Pocket 3.
{ config, pkgs, lib, ... }:
{
imports = [ <arroyo/nixos/gpd-pocket-3.nix> ];
networking.hostName = "rose-quine";
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
services.xserver.dpi = 280;
services.tailscale.authKey = "tskey-auth-k7zq8i5CNTRL-UgF9rKPc9MWouGgLnm6pRWChgTBEZ6ywb";
networking.hostId = "30501580"; # required for zfs use
boot.zfs.devNodes = "/dev/mapper";
boot.initrd.luks.devices = {
"swap" = { name = "swap"; device = "/dev/nvme0n1p2"; preLVM = true; };
"root" = { name = "root"; device = "/dev/nvme0n1p3"; preLVM = true; };
};
# === from hardware-configuration.nix
boot.initrd.availableKernelModules = [ "xhci_pci" "thunderbolt" "nvme" "usbhid" "usb_storage" "sd_mod" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "tank/root";
fsType = "zfs";
};
fileSystems."/home" =
{ device = "tank/home";
fsType = "zfs";
};
fileSystems."/nix" =
{ device = "tank/nix";
fsType = "zfs";
};
fileSystems."/media" =
{ device = "tank/media";
fsType = "zfs";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/A0F9-D8A8";
fsType = "vfat";
};
swapDevices =
[ { device = "/dev/disk/by-uuid/8aa13fd3-34d7-442e-b52d-cf438d0b3709"; }
];
nixpkgs.hostPlatform = "x86_64-linux";
powerManagement.cpuFreqGovernor = "powersave";
}
NEXT derivation for umpc-display-rotate.c
NEXT split and document all this out in to an import on roam:GPD Pocket 3 Support page
Deploying My NixOS Set Top Box
let
settopCfg = ../roles/settop;
# nixpkgsPin = (import ../versions.nix {}).nixpkgs;
# pkgs = import (builtins.fetchTarball nixpkgsPin) {};
pkgs = import <nixpkgs> {};
in {
network.pkgs = pkgs;
network.description = "my settop";
network.enableRollback = true;
tres-ebow = {config, pkgs, ...}:
{
imports = [ settopCfg ../hosts/tres-ebow ];
deployment.targetHost = "10.0.0.167";
};
}
Tres Ebow
Tres Ebow is my Thinkpad Yoga gen 3 – a decent 2-in-1 with very un-Lenovo serviceability, and due to ordering error and soldered RAM, only 4 GiB of RAM. awkward. it'll be a fine kodi box.
{
imports = [ ./hardware-configuration.nix ];
networking.hostName = "tres-ebow";
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
# networking.wg-quick.interfaces.wg0 = {
# privateKeyFile = "/etc/wireguard-key/tres-ebow.key";
# address = ["10.10.10.2/32" "2620:fc:c000:0:1000::b/128"];
# };
# networking.wg-quick.interfaces.wg1 = {
# privateKeyFile = "/etc/wireguard-key/tres-ebow.key";
# address = ["10.10.10.2/32" "2620:fc:c000:0:1000::b/128"];
# };
services.tailscale.authKey = "tskey-kGxjxy1CNTRL-ZoepgcGatEA78ezQKX5VVb";
networking.hostId = "c9ec7cad"; # required for zfs use
boot.initrd.luks.devices = {
"swap" = { name = "swap"; device = "/dev/nvme0n1p2"; preLVM = true; };
"root" = { name = "root"; device = "/dev/nvme0n1p3"; preLVM = true; };
};
}
I pull /rrix/complete-computing-environment/src/branch/exwm/nixlib/hosts/tres-ebow/hardware-configuration.nix with nixops:
nixops scp --from tres-ebow /etc/nixos/hardware-configuration.nix nixlib/hosts/tres-ebow/hardware-configuration.nix
I put my Wireguard configuration on the device (for now) using nixops scp
nixops ssh tres-ebow mkdir -p /etc/wireguard-key/ && \ nixops scp --to tres-ebow wireguard/tres-ebow.key /etc/wireguard-key/tres-ebow.key && \ nixops ssh tres-ebow chown 400 /etc/wireguard-key/tres-ebow.key
I need to make sure this stays in sync with my JustDoIt script!
Deploying The Wobserver
let
serverCfg = ../roles/server;
pkgs = import <nixpkgs> {};
in {
network.pkgs = pkgs;
network.description = "my wobserver";
network.enableRollback = true;
terra-firma = {config, pkgs, ...}:
{
imports = [ serverCfg ../hosts/terra-firma ];
deployment.targetHost = "terra-firma";
system.stateVersion = "22.11";
};
}
Terra Firma
Terra Firma is my Wobserver hosted by Wobscale Technologies in Seattle, WA.
{
imports = [ ./hardware-configuration.nix ];
networking.hostName = "terra-firma";
boot.loader.grub.enable = true;
# boot.loader.grub.device = "/dev/sde";
boot.loader.grub.device = "/dev/sdf";
networking.hostId = "628c9fc3"; # required for zfs use
services.tailscale.authKey = "tskey-auth-kc6ULA7CNTRL-DwkDu5vJo2RrekxqbUHNxQP4LmMDnRjS3";
}
{ config, lib, pkgs, modulesPath, ... }:
{
imports =
[ (modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [ "ehci_pci" "ata_piix" "uhci_hcd" "xhci_pci" "usb_storage" "usbhid" "sd_mod" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "terra-firma/root";
fsType = "zfs";
};
fileSystems."/home" =
{ device = "tank/home";
fsType = "zfs";
};
fileSystems."/media" =
{ device = "tank/media";
fsType = "zfs";
};
fileSystems."/srv" =
{ device = "tank/srv";
fsType = "zfs";
};
fileSystems."/nix" =
{ device = "terra-firma/nix";
fsType = "zfs";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/2C1E-582F";
fsType = "vfat";
};
swapDevices =
[ { device = "/dev/disk/by-uuid/1ee46640-6164-4882-a59d-aa260c7780a2"; }
];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.eno1.useDHCP = lib.mkDefault true;
# networking.interfaces.eno2.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}