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"; #
};
}
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 file: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 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 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…
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 file: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;
}