style(nix): apply style fixes #53
@@ -109,12 +109,16 @@ in
|
||||
inherit (cfg.reverseProxy) trustedSources;
|
||||
};
|
||||
volumes = lib.mapAttrs (_urlPath: volume: {
|
||||
inherit (volume) path access flags readOnly;
|
||||
inherit (volume)
|
||||
path
|
||||
access
|
||||
flags
|
||||
readOnly
|
||||
;
|
||||
}) cfg.volumes;
|
||||
};
|
||||
|
||||
mounts =
|
||||
{
|
||||
mounts = {
|
||||
${cfg.stateDir} = {
|
||||
directory = cfg.statePath;
|
||||
owner = config.registry."stable-uid".${config.networking.hostName}.copyparty;
|
||||
@@ -126,7 +130,8 @@ in
|
||||
readOnly = true;
|
||||
};
|
||||
}
|
||||
// lib.mapAttrs' (_urlPath: volume:
|
||||
// lib.mapAttrs' (
|
||||
_urlPath: volume:
|
||||
lib.nameValuePair volume.path {
|
||||
directory = volume.hostPath;
|
||||
owner = "root";
|
||||
|
||||
@@ -88,14 +88,18 @@ in
|
||||
guests.palworld = {
|
||||
interior.modules.services.games.palworld = {
|
||||
enable = true;
|
||||
inherit (cfg) serverName port publicIP autoStart;
|
||||
inherit (cfg)
|
||||
serverName
|
||||
port
|
||||
publicIP
|
||||
autoStart
|
||||
;
|
||||
inherit steamDir installDir stateDir;
|
||||
passwordFile = "/run/secrets/${cfg.passwordSecret}";
|
||||
adminPasswordFile = "/run/secrets/${cfg.adminPasswordSecret}";
|
||||
};
|
||||
|
||||
mounts =
|
||||
{
|
||||
mounts = {
|
||||
${steamDir} = {
|
||||
directory = cfg.steamPath;
|
||||
owner = config.registry."stable-uid".${config.networking.hostName}.steamcmd;
|
||||
@@ -133,8 +137,7 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
sops.secrets =
|
||||
{
|
||||
sops.secrets = {
|
||||
${cfg.passwordSecret} = {
|
||||
owner = "root";
|
||||
group = "storage";
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
registry.shell-shortcut.neogaia = {
|
||||
vpn-on = "sudo systemctl start wireguard-wg-home.target";
|
||||
vpn-off = ''sudo systemctl stop 'wireguard-wg-home*.service' wireguard-wg-home.target'';
|
||||
vpn-off = "sudo systemctl stop 'wireguard-wg-home*.service' wireguard-wg-home.target";
|
||||
};
|
||||
|
||||
modules.monorepo.enable = true;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{ ... }:
|
||||
_:
|
||||
# neogaia's disk layout for disko: one NVMe disk, GPT, with an EFI system
|
||||
# partition and a LUKS container holding btrfs subvolumes.
|
||||
# No swap partition, since swap is zram.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{ ... }:
|
||||
_:
|
||||
# pikachu's install layout for disko: one NVMe boot disk with an EFI system partition and ext4 root.
|
||||
# The existing 8 TB ZFS mirror is imported by name and is never declared here.
|
||||
{
|
||||
|
||||
@@ -8,7 +8,10 @@
|
||||
# Disk layout is in ./disk.nix.
|
||||
# `fileSystems` are derived from it, none declared here.
|
||||
{
|
||||
imports = [ ./disk.nix ] ++ lib.optional (builtins.pathExists ./hardware-configuration.nix) ./hardware-configuration.nix;
|
||||
imports = [
|
||||
./disk.nix
|
||||
]
|
||||
++ lib.optional (builtins.pathExists ./hardware-configuration.nix) ./hardware-configuration.nix;
|
||||
|
||||
nixpkgs.hostPlatform = "x86_64-linux";
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{ ... }:
|
||||
_:
|
||||
# zeus's disk layout for disko: two NVMe disks with one EFI system partition
|
||||
# and two LUKS containers joined into one btrfs filesystem.
|
||||
# No swap partition, since swap is zram.
|
||||
|
||||
@@ -10,7 +10,8 @@ let
|
||||
user = config.user.name;
|
||||
in
|
||||
{
|
||||
options.modules.desktop.apps.alacritty.enable = lib.mkEnableOption "Alacritty as the desktop terminal";
|
||||
options.modules.desktop.apps.alacritty.enable =
|
||||
lib.mkEnableOption "Alacritty as the desktop terminal";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
home-manager.users.${user}.home.packages = [ pkgs.alacritty ];
|
||||
|
||||
@@ -10,7 +10,8 @@ let
|
||||
user = config.user.name;
|
||||
in
|
||||
{
|
||||
options.modules.desktop.apps.obsidian.enable = lib.mkEnableOption "Obsidian as the desktop note-taking vault";
|
||||
options.modules.desktop.apps.obsidian.enable =
|
||||
lib.mkEnableOption "Obsidian as the desktop note-taking vault";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
home-manager.users.${user}.home.packages = [ pkgs.obsidian ];
|
||||
|
||||
@@ -10,7 +10,8 @@ let
|
||||
user = config.user.name;
|
||||
in
|
||||
{
|
||||
options.modules.desktop.apps.vencord.enable = lib.mkEnableOption "Vesktop, a Discord client with Vencord built in";
|
||||
options.modules.desktop.apps.vencord.enable =
|
||||
lib.mkEnableOption "Vesktop, a Discord client with Vencord built in";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
home-manager.users.${user}.home.packages = [ pkgs.vesktop ];
|
||||
|
||||
@@ -67,8 +67,7 @@ in
|
||||
# UWSM launches the session without the shell profile that would carry
|
||||
# them, so a variable the compositor or its children must see is set
|
||||
# here rather than through home-manager's sessionVariables.
|
||||
env =
|
||||
[
|
||||
env = [
|
||||
# Chromium and Electron apps read this to select native Wayland;
|
||||
# nixpkgs wrappers (Obsidian's included) gate their Wayland flags on
|
||||
# it, so without it they run under XWayland and blur at this DPI.
|
||||
|
||||
@@ -45,7 +45,8 @@ let
|
||||
'';
|
||||
in
|
||||
{
|
||||
options.modules.desktop.session.hyprland.hyprlock.enable = lib.mkEnableOption "the hyprlock lock screen";
|
||||
options.modules.desktop.session.hyprland.hyprlock.enable =
|
||||
lib.mkEnableOption "the hyprlock lock screen";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
home-manager.users.${user} = {
|
||||
|
||||
@@ -10,7 +10,8 @@ let
|
||||
cfg = config.modules.desktop.session.login;
|
||||
in
|
||||
{
|
||||
options.modules.desktop.session.login.enable = lib.mkEnableOption "greetd with the tuigreet text greeter";
|
||||
options.modules.desktop.session.login.enable =
|
||||
lib.mkEnableOption "greetd with the tuigreet text greeter";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.greetd = {
|
||||
|
||||
@@ -25,7 +25,8 @@ let
|
||||
'';
|
||||
in
|
||||
{
|
||||
options.modules.desktop.utilities.clipboard.enable = lib.mkEnableOption "cliphist clipboard history";
|
||||
options.modules.desktop.utilities.clipboard.enable =
|
||||
lib.mkEnableOption "cliphist clipboard history";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
home-manager.users.${user} = {
|
||||
|
||||
@@ -10,7 +10,8 @@ let
|
||||
user = config.user.name;
|
||||
in
|
||||
{
|
||||
options.modules.desktop.utilities.osd.enable = lib.mkEnableOption "the SwayOSD volume and brightness popup";
|
||||
options.modules.desktop.utilities.osd.enable =
|
||||
lib.mkEnableOption "the SwayOSD volume and brightness popup";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
environment.systemPackages = [ pkgs.swayosd ];
|
||||
|
||||
@@ -41,7 +41,8 @@ let
|
||||
'';
|
||||
in
|
||||
{
|
||||
options.modules.desktop.utilities.recording.enable = lib.mkEnableOption "wf-recorder screen recording";
|
||||
options.modules.desktop.utilities.recording.enable =
|
||||
lib.mkEnableOption "wf-recorder screen recording";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
home-manager.users.${user} = {
|
||||
|
||||
@@ -32,7 +32,8 @@ let
|
||||
'';
|
||||
in
|
||||
{
|
||||
options.modules.desktop.utilities.screenshot.enable = lib.mkEnableOption "screenshots via grimblast and satty";
|
||||
options.modules.desktop.utilities.screenshot.enable =
|
||||
lib.mkEnableOption "screenshots via grimblast and satty";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
home-manager.users.${user} = {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}:
|
||||
let
|
||||
cfg = config.modules.host;
|
||||
user = config.user;
|
||||
inherit (config) user;
|
||||
hostSecrets = ../secrets + "/${config.networking.hostName}.yaml";
|
||||
passwordSecret = "${user.name}-password";
|
||||
in
|
||||
|
||||
@@ -104,8 +104,7 @@ let
|
||||
isWorkstation = elem currentHost cfg.hosts.workstations;
|
||||
|
||||
defaultAuthorizedKeys = lib.flatten (
|
||||
clientKeysFor workstationNames
|
||||
++ optional isServer (clientKeysFor serverNames)
|
||||
clientKeysFor workstationNames ++ optional isServer (clientKeysFor serverNames)
|
||||
);
|
||||
|
||||
outboundTargetNames =
|
||||
@@ -120,7 +119,8 @@ let
|
||||
in
|
||||
filter (name: name != currentHost) (targetNamesIn groupTargets);
|
||||
|
||||
sshSettingsFor = name:
|
||||
sshSettingsFor =
|
||||
name:
|
||||
let
|
||||
target = cfg.targets.${name};
|
||||
in
|
||||
@@ -131,7 +131,8 @@ let
|
||||
}
|
||||
// optionalAttrs (target.port != 22) { Port = target.port; };
|
||||
|
||||
knownHostNamesFor = target:
|
||||
knownHostNamesFor =
|
||||
target:
|
||||
let
|
||||
names = unique (target.aliases ++ [ target.hostName ]);
|
||||
withPort = name: if target.port == 22 then name else "[${name}]:${toString target.port}";
|
||||
@@ -142,7 +143,8 @@ let
|
||||
concatLists (
|
||||
mapAttrsToList (
|
||||
targetName: target:
|
||||
imap0 (i: key:
|
||||
imap0 (
|
||||
i: key:
|
||||
nameValuePair "${targetName}-${toString i}" {
|
||||
hostNames = knownHostNamesFor target;
|
||||
publicKey = keyWithoutComment key;
|
||||
@@ -290,8 +292,7 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable (
|
||||
mkMerge [
|
||||
config = mkIf cfg.enable (mkMerge [
|
||||
{
|
||||
services.openssh.enable = true;
|
||||
|
||||
@@ -342,6 +343,5 @@ in
|
||||
home-manager.users.${user}.programs.ssh.settings."*".IdentityFile =
|
||||
config.sops.secrets.${userKeySecret}.path;
|
||||
})
|
||||
]
|
||||
);
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -75,8 +75,9 @@ in
|
||||
];
|
||||
|
||||
# networkd owns these interfaces so NetworkManager does not contend for them.
|
||||
networking.networkmanager.unmanaged =
|
||||
[ "interface-name:${cfg.trunk}" ]
|
||||
networking.networkmanager.unmanaged = [
|
||||
"interface-name:${cfg.trunk}"
|
||||
]
|
||||
++ map (id: "interface-name:${bridgeName id}") cfg.ids
|
||||
++ map (id: "interface-name:${vlanName id}") cfg.ids;
|
||||
|
||||
|
||||
@@ -88,16 +88,18 @@ in
|
||||
|
||||
networking.wireguard.interfaces.${cfg.interface} = {
|
||||
ips = [ cfg.address ];
|
||||
mtu = cfg.mtu;
|
||||
inherit (cfg) mtu;
|
||||
privateKeyFile = config.sops.secrets.${cfg.privateKeySecret}.path;
|
||||
|
||||
peers = [
|
||||
({
|
||||
(
|
||||
{
|
||||
inherit (cfg.peer) publicKey endpoint allowedIPs;
|
||||
}
|
||||
// lib.optionalAttrs (cfg.peer.persistentKeepalive != null) {
|
||||
inherit (cfg.peer) persistentKeepalive;
|
||||
})
|
||||
}
|
||||
)
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
@@ -45,14 +45,14 @@ in
|
||||
users.users.${cfg.user} = {
|
||||
isSystemUser = true;
|
||||
uid = config.registry."stable-uid".${config.networking.hostName}.actualbudget;
|
||||
group = cfg.group;
|
||||
inherit (cfg) group;
|
||||
};
|
||||
|
||||
services.actual = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
user = cfg.user;
|
||||
group = cfg.group;
|
||||
inherit (cfg) user;
|
||||
inherit (cfg) group;
|
||||
settings = {
|
||||
inherit (cfg) port dataDir;
|
||||
};
|
||||
|
||||
@@ -40,13 +40,16 @@ let
|
||||
|
||||
renderAccess = permission: accounts: " ${permission}: ${lib.concatStringsSep ", " accounts}";
|
||||
|
||||
hasFlag = name: flags: lib.any (flag: lib.hasPrefix "${name}:" flag || lib.hasPrefix "${name}=" flag) flags;
|
||||
hasFlag =
|
||||
name: flags: lib.any (flag: lib.hasPrefix "${name}:" flag || lib.hasPrefix "${name}=" flag) flags;
|
||||
|
||||
defaultPermissionFlags = flags:
|
||||
defaultPermissionFlags =
|
||||
flags:
|
||||
lib.optionals (!(hasFlag "chmod_d" flags)) [ "chmod_d: 2770" ]
|
||||
++ lib.optionals (!(hasFlag "chmod_f" flags)) [ "chmod_f: 660" ];
|
||||
|
||||
renderFlags = flags: lib.concatMapStringsSep "\n" (flag: " ${flag}") (flags ++ defaultPermissionFlags flags);
|
||||
renderFlags =
|
||||
flags: lib.concatMapStringsSep "\n" (flag: " ${flag}") (flags ++ defaultPermissionFlags flags);
|
||||
|
||||
renderVolume = urlPath: volume: ''
|
||||
[${urlPath}]
|
||||
@@ -173,7 +176,7 @@ in
|
||||
users.users.${cfg.user} = {
|
||||
isSystemUser = true;
|
||||
uid = config.registry."stable-uid".${config.networking.hostName}.copyparty;
|
||||
group = cfg.group;
|
||||
inherit (cfg) group;
|
||||
home = cfg.stateDir;
|
||||
};
|
||||
|
||||
@@ -202,7 +205,10 @@ in
|
||||
PrivateTmp = true;
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
ReadWritePaths = [ cfg.stateDir ] ++ map (volume: volume.path) (lib.filter (volume: !volume.readOnly) (lib.attrValues cfg.volumes));
|
||||
ReadWritePaths = [
|
||||
cfg.stateDir
|
||||
]
|
||||
++ map (volume: volume.path) (lib.filter (volume: !volume.readOnly) (lib.attrValues cfg.volumes));
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -134,8 +134,7 @@
|
||||
appId = 2394010;
|
||||
inherit (service) autoStart;
|
||||
executable = "${startScript}";
|
||||
arguments =
|
||||
[
|
||||
arguments = [
|
||||
"-useperfthreads"
|
||||
"-NoAsyncLoadingThread"
|
||||
"-UseMultithreadForDS"
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
let
|
||||
cfg = config.modules.services.homepage;
|
||||
|
||||
mkRegistryPath = registryName: host: entry: "registry.${registryName}.${host}.${entry}";
|
||||
mkRegistryPath =
|
||||
registryName: host: entry:
|
||||
"registry.${registryName}.${host}.${entry}";
|
||||
|
||||
homepageEntries = lib.concatLists (
|
||||
lib.mapAttrsToList (
|
||||
@@ -19,7 +21,8 @@ let
|
||||
) registry.homepage
|
||||
);
|
||||
|
||||
mkHref = item:
|
||||
mkHref =
|
||||
item:
|
||||
if item.homepage.href != null then
|
||||
item.homepage.href
|
||||
else if (item.composite.route or null) != null then
|
||||
@@ -32,7 +35,8 @@ let
|
||||
else
|
||||
throw "${mkRegistryPath "homepage" item.host item.entry} needs href or a matching route entry";
|
||||
|
||||
mkServiceAttrs = item:
|
||||
mkServiceAttrs =
|
||||
item:
|
||||
lib.filterAttrs (_: value: value != null) {
|
||||
href = mkHref item;
|
||||
inherit (item.homepage) description icon;
|
||||
@@ -40,11 +44,11 @@ let
|
||||
|
||||
sortedEntries = lib.sort (left: right: left.homepage.name < right.homepage.name) homepageEntries;
|
||||
|
||||
insertEntry = acc: item:
|
||||
insertEntry =
|
||||
acc: item:
|
||||
acc
|
||||
// {
|
||||
${item.homepage.tab} = (acc.${item.homepage.tab} or { })
|
||||
// {
|
||||
${item.homepage.tab} = (acc.${item.homepage.tab} or { }) // {
|
||||
${item.homepage.section} = (acc.${item.homepage.tab}.${item.homepage.section} or [ ]) ++ [
|
||||
{ ${item.homepage.name} = mkServiceAttrs item; }
|
||||
];
|
||||
@@ -80,13 +84,15 @@ let
|
||||
];
|
||||
};
|
||||
|
||||
orderedSections = tab: sections:
|
||||
orderedSections =
|
||||
tab: sections:
|
||||
let
|
||||
sectionOrder = sectionOrderByTab.${tab} or [ ];
|
||||
in
|
||||
sectionOrder ++ lib.filter (section: !lib.elem section sectionOrder) (lib.attrNames sections);
|
||||
|
||||
mkTab = tab:
|
||||
mkTab =
|
||||
tab:
|
||||
let
|
||||
sections = entriesByTab.${tab};
|
||||
in
|
||||
@@ -148,7 +154,9 @@ in
|
||||
openFirewall = true;
|
||||
inherit (cfg) listenPort;
|
||||
environmentFiles = [ cfg.environmentFile ];
|
||||
allowedHosts = lib.concatStringsSep "," (if cfg.allowedHosts == null then derivedAllowedHosts else cfg.allowedHosts);
|
||||
allowedHosts = lib.concatStringsSep "," (
|
||||
if cfg.allowedHosts == null then derivedAllowedHosts else cfg.allowedHosts
|
||||
);
|
||||
services = homepageServices;
|
||||
widgets = [
|
||||
{
|
||||
|
||||
@@ -50,7 +50,7 @@ in
|
||||
user = "navidrome";
|
||||
group = "storage";
|
||||
openFirewall = true;
|
||||
environmentFile = cfg.environmentFile;
|
||||
inherit (cfg) environmentFile;
|
||||
settings = {
|
||||
Address = "0.0.0.0";
|
||||
Port = 4533;
|
||||
|
||||
@@ -7,15 +7,20 @@
|
||||
let
|
||||
cfg = config.modules.services.reverse-proxy;
|
||||
|
||||
mkRegistryPath = registryName: host: entry: "registry.${registryName}.${host}.${entry}";
|
||||
mkRegistryPath =
|
||||
registryName: host: entry:
|
||||
"registry.${registryName}.${host}.${entry}";
|
||||
|
||||
mkBackend = address: port: "http://${address}:${toString port}";
|
||||
|
||||
mkVirtualHost = host: entry: mode:
|
||||
mkVirtualHost =
|
||||
host: entry: mode:
|
||||
let
|
||||
compositeEntry = registry.join host entry;
|
||||
route = compositeEntry.route;
|
||||
address = compositeEntry.address or (throw "no matching entry in registry.address for ${mkRegistryPath "route" host entry}");
|
||||
inherit (compositeEntry) route;
|
||||
address =
|
||||
compositeEntry.address
|
||||
or (throw "no matching entry in registry.address for ${mkRegistryPath "route" host entry}");
|
||||
isHttp = mode == "http";
|
||||
port = if isHttp then route.http.port else route.port;
|
||||
in
|
||||
@@ -63,7 +68,11 @@ let
|
||||
domain: virtualHosts:
|
||||
if lib.length virtualHosts > 1 then
|
||||
[
|
||||
"duplicate route domain ${domain} in ${lib.concatMapStringsSep " and " (virtualHost: mkRegistryPath virtualHost.registryName virtualHost.host virtualHost.entry) virtualHosts}"
|
||||
"duplicate route domain ${domain} in ${
|
||||
lib.concatMapStringsSep " and " (
|
||||
virtualHost: mkRegistryPath virtualHost.registryName virtualHost.host virtualHost.entry
|
||||
) virtualHosts
|
||||
}"
|
||||
]
|
||||
else
|
||||
[ ]
|
||||
@@ -76,13 +85,21 @@ let
|
||||
else
|
||||
lib.listToAttrs generatedVirtualHostList;
|
||||
|
||||
mkUdpStream = host: entry: port:
|
||||
mkUdpStream =
|
||||
host: entry: port:
|
||||
let
|
||||
compositeEntry = registry.join host entry;
|
||||
address = compositeEntry.address or (throw "no matching entry in registry.address for ${mkRegistryPath "route" host entry}");
|
||||
address =
|
||||
compositeEntry.address
|
||||
or (throw "no matching entry in registry.address for ${mkRegistryPath "route" host entry}");
|
||||
in
|
||||
{
|
||||
inherit host entry port address;
|
||||
inherit
|
||||
host
|
||||
entry
|
||||
port
|
||||
address
|
||||
;
|
||||
};
|
||||
|
||||
generatedUdpStreams = lib.concatLists (
|
||||
|
||||
@@ -10,7 +10,8 @@ let
|
||||
user = config.user.name;
|
||||
in
|
||||
{
|
||||
options.modules.shell.bazel.enable = lib.mkEnableOption "Bazel for the primary user's shell environment";
|
||||
options.modules.shell.bazel.enable =
|
||||
lib.mkEnableOption "Bazel for the primary user's shell environment";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
home-manager.users.${user}.home.packages = [ pkgs.bazel ];
|
||||
|
||||
@@ -107,8 +107,7 @@ in
|
||||
|
||||
# Rendered by home-manager into ~/.config/fish/config.fish.
|
||||
interactiveShellInit = lib.concatStringsSep "\n" (
|
||||
(lib.mapAttrsToList exportEnvVar envVars)
|
||||
++ [ (builtins.readFile ./config.fish) ]
|
||||
(lib.mapAttrsToList exportEnvVar envVars) ++ [ (builtins.readFile ./config.fish) ]
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -10,7 +10,8 @@ let
|
||||
user = config.user.name;
|
||||
in
|
||||
{
|
||||
options.modules.shell.herdr.enable = lib.mkEnableOption "Herdr, a terminal multiplexer for coding agents";
|
||||
options.modules.shell.herdr.enable =
|
||||
lib.mkEnableOption "Herdr, a terminal multiplexer for coding agents";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
registry.shell-shortcut.${config.networking.hostName}.hs = "herdr --session";
|
||||
|
||||
@@ -11,7 +11,8 @@ let
|
||||
user = config.user.name;
|
||||
in
|
||||
{
|
||||
options.modules.shell.nvim.enable = lib.mkEnableOption "Neovim, configured declaratively via nixvim";
|
||||
options.modules.shell.nvim.enable =
|
||||
lib.mkEnableOption "Neovim, configured declaratively via nixvim";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
registry.shell-shortcut.${config.networking.hostName} = {
|
||||
|
||||
@@ -18,8 +18,7 @@ let
|
||||
in
|
||||
{
|
||||
options.modules.shell.pi = {
|
||||
enable = lib.mkEnableOption ''
|
||||
Pi, a terminal coding agent, configured through home-manager'';
|
||||
enable = lib.mkEnableOption "Pi, a terminal coding agent, configured through home-manager";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
@@ -10,7 +10,8 @@ let
|
||||
user = config.user.name;
|
||||
in
|
||||
{
|
||||
options.modules.shell.python.enable = lib.mkEnableOption "Python tools for the primary user's shell environment";
|
||||
options.modules.shell.python.enable =
|
||||
lib.mkEnableOption "Python tools for the primary user's shell environment";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
registry.env-var.${config.networking.hostName}.PYTHON_TOOLCHAIN_ROOT = "${pkgs.python3}";
|
||||
|
||||
@@ -20,7 +20,8 @@ let
|
||||
};
|
||||
in
|
||||
{
|
||||
options.modules.shell.rust.enable = lib.mkEnableOption "Rust tools for the primary user's shell environment";
|
||||
options.modules.shell.rust.enable =
|
||||
lib.mkEnableOption "Rust tools for the primary user's shell environment";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
registry.env-var.${config.networking.hostName}.RUST_TOOLCHAIN_ROOT = "${toolchain}";
|
||||
|
||||
@@ -6,14 +6,16 @@
|
||||
message = "Route domains must be unique.";
|
||||
}
|
||||
{
|
||||
assertion = entries:
|
||||
assertion =
|
||||
entries:
|
||||
lib.registry.predicates.uniqueValue (entry: entry.value) (
|
||||
lib.concatMap (entry: map (port: entry // { value = port; }) entry.value.udp.ports) entries
|
||||
);
|
||||
message = "Route UDP ports must be unique.";
|
||||
}
|
||||
{
|
||||
assertion = entries: lib.all (entry: entry.value.port == null || entry.value.http.port == null) entries;
|
||||
assertion =
|
||||
entries: lib.all (entry: entry.value.port == null || entry.value.http.port == null) entries;
|
||||
message = "Route entries must not set both port and http.port.";
|
||||
}
|
||||
];
|
||||
|
||||
@@ -7,12 +7,14 @@ let
|
||||
unique
|
||||
;
|
||||
|
||||
serviceNamesByUid = entries:
|
||||
serviceNamesByUid =
|
||||
entries:
|
||||
mapAttrs (_uid: uidEntries: unique (map (entry: entry.entry) uidEntries)) (
|
||||
groupBy (entry: toString entry.value) entries
|
||||
);
|
||||
|
||||
duplicateUids = entries:
|
||||
duplicateUids =
|
||||
entries:
|
||||
filterAttrs (_uid: serviceNames: builtins.length serviceNames > 1) (serviceNamesByUid entries);
|
||||
|
||||
in
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
{ self, nixpkgs, ... }@inputs:
|
||||
import ./src/dotfiles {
|
||||
inherit inputs self;
|
||||
lib = nixpkgs.lib;
|
||||
inherit (nixpkgs) lib;
|
||||
root = ./configs/nixos;
|
||||
system = "x86_64-linux";
|
||||
};
|
||||
|
||||
@@ -10,7 +10,8 @@ in
|
||||
{
|
||||
fix = {
|
||||
type = "app";
|
||||
program = lib.getExe (pkgs.writeShellApplication {
|
||||
program = lib.getExe (
|
||||
pkgs.writeShellApplication {
|
||||
name = "fix";
|
||||
runtimeInputs = [
|
||||
formatter.config.build.wrapper
|
||||
@@ -23,6 +24,7 @@ in
|
||||
deadnix --edit --exclude configs/nixos/hosts/*/hardware-configuration.nix -- .
|
||||
treefmt
|
||||
'';
|
||||
});
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -17,16 +17,13 @@ let
|
||||
directoryMounts = lib.filterAttrs (_: mount: mount.directory != null) cfg.mounts;
|
||||
|
||||
directoryScript = lib.concatStringsSep "\n" (
|
||||
lib.mapAttrsToList (
|
||||
_: mount:
|
||||
''
|
||||
lib.mapAttrsToList (_: mount: ''
|
||||
${config.system.path}/bin/install -d \
|
||||
${lib.optionalString (mount.owner != null) "-o ${lib.escapeShellArg (toString mount.owner)}"} \
|
||||
${lib.optionalString (mount.group != null) "-g ${lib.escapeShellArg mount.group}"} \
|
||||
${lib.optionalString (mount.mode != null) "-m ${lib.escapeShellArg mount.mode}"} \
|
||||
${lib.escapeShellArg mount.directory}
|
||||
''
|
||||
) directoryMounts
|
||||
'') directoryMounts
|
||||
);
|
||||
in
|
||||
{
|
||||
@@ -171,14 +168,20 @@ let
|
||||
assertions =
|
||||
let
|
||||
hasDirectorySettings = mount: mount.owner != null || mount.group != null || mount.mode != null;
|
||||
hasCompleteDirectorySettings = mount: mount.owner != null && mount.group != null && mount.mode != null;
|
||||
hasCompleteDirectorySettings =
|
||||
mount: mount.owner != null && mount.group != null && mount.mode != null;
|
||||
hasOneSource = mount: (mount.directory != null) != (mount.file != null);
|
||||
mountsWithInvalidSource = lib.attrNames (lib.filterAttrs (_: mount: !hasOneSource mount) cfg.mounts);
|
||||
mountsWithInvalidSource = lib.attrNames (
|
||||
lib.filterAttrs (_: mount: !hasOneSource mount) cfg.mounts
|
||||
);
|
||||
fileMountsWithHostSettings = lib.attrNames (
|
||||
lib.filterAttrs (_: mount: mount.file != null && hasDirectorySettings mount) cfg.mounts
|
||||
);
|
||||
directoryMountsWithPartialHostSettings = lib.attrNames (
|
||||
lib.filterAttrs (_: mount: mount.directory != null && hasDirectorySettings mount && !hasCompleteDirectorySettings mount) cfg.mounts
|
||||
lib.filterAttrs (
|
||||
_: mount:
|
||||
mount.directory != null && hasDirectorySettings mount && !hasCompleteDirectorySettings mount
|
||||
) cfg.mounts
|
||||
);
|
||||
in
|
||||
[
|
||||
@@ -203,20 +206,23 @@ let
|
||||
{
|
||||
assertion = lib.elem cfg.vlan config.modules.network.vlans.ids;
|
||||
message = ''
|
||||
guests.${name}.vlan = ${toString cfg.vlan} is not among its host's modules.network.vlans.ids (${lib.concatMapStringsSep ", " toString config.modules.network.vlans.ids}). Declare the VLAN on the host or correct the guest's placement.
|
||||
guests.${name}.vlan = ${toString cfg.vlan} is not among its host's modules.network.vlans.ids (${
|
||||
lib.concatMapStringsSep ", " toString config.modules.network.vlans.ids
|
||||
}). Declare the VLAN on the host or correct the guest's placement.
|
||||
'';
|
||||
}
|
||||
];
|
||||
|
||||
registry.address.${config.networking.hostName}.${name} =
|
||||
lib.mkIf (cfg.address != null) cfg.address;
|
||||
registry.address.${config.networking.hostName}.${name} = lib.mkIf (cfg.address != null) cfg.address;
|
||||
|
||||
registry.route.${config.networking.hostName}.${name} =
|
||||
lib.mkIf cfg.reverseProxy.enable cfg.reverseProxy.route;
|
||||
|
||||
systemd.services."container@${name}" =
|
||||
let
|
||||
bridgeDevice = "sys-subsystem-net-devices-${lib.replaceStrings [ "-" ] [ "\\x2d" ] (util.bridgeName cfg.vlan)}.device";
|
||||
bridgeDevice = "sys-subsystem-net-devices-${
|
||||
lib.replaceStrings [ "-" ] [ "\\x2d" ] (util.bridgeName cfg.vlan)
|
||||
}.device";
|
||||
in
|
||||
{
|
||||
after = [ bridgeDevice ];
|
||||
@@ -268,10 +274,11 @@ let
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
let
|
||||
|
||||
files = util.collectNixFiles root;
|
||||
guestFiles = lib.filterAttrs (file: type: type == "regular" && lib.hasSuffix ".nix" file) (builtins.readDir root);
|
||||
guestFiles = lib.filterAttrs (file: type: type == "regular" && lib.hasSuffix ".nix" file) (
|
||||
builtins.readDir root
|
||||
);
|
||||
names = map (file: lib.removeSuffix ".nix" file) (lib.attrNames guestFiles);
|
||||
in
|
||||
{
|
||||
|
||||
@@ -26,7 +26,8 @@ let
|
||||
guestModules
|
||||
|
||||
# TODO: refactor
|
||||
registryModule (root + "/${name}")
|
||||
registryModule
|
||||
(root + "/${name}")
|
||||
|
||||
{
|
||||
networking.hostName = name;
|
||||
@@ -34,12 +35,8 @@ let
|
||||
}
|
||||
];
|
||||
};
|
||||
in
|
||||
let
|
||||
|
||||
directories = lib.filterAttrs (_name: type: type == "directory") (builtins.readDir root);
|
||||
names = lib.attrNames directories;
|
||||
in
|
||||
lib.genAttrs names (
|
||||
name:
|
||||
mkHost { inherit root name; }
|
||||
)
|
||||
lib.genAttrs names (name: mkHost { inherit root name; })
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
{ hosts, lib, root }:
|
||||
{
|
||||
hosts,
|
||||
lib,
|
||||
root,
|
||||
}:
|
||||
let
|
||||
checkType = lib.types.submodule {
|
||||
options = {
|
||||
@@ -19,7 +23,8 @@ let
|
||||
};
|
||||
|
||||
predicates = {
|
||||
uniqueValue = value: entries: builtins.length (lib.unique (map value entries)) == builtins.length entries;
|
||||
uniqueValue =
|
||||
value: entries: builtins.length (lib.unique (map value entries)) == builtins.length entries;
|
||||
};
|
||||
|
||||
registryLib = lib // {
|
||||
@@ -57,7 +62,9 @@ let
|
||||
|
||||
registryName = fileName: lib.removeSuffix ".nix" fileName;
|
||||
|
||||
registryOption = registry: lib.mkOption {
|
||||
registryOption =
|
||||
registry:
|
||||
lib.mkOption {
|
||||
type = lib.types.attrsOf (lib.types.attrsOf registry.type);
|
||||
default = { };
|
||||
description = ''
|
||||
@@ -65,7 +72,8 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
mkRegistry = path:
|
||||
mkRegistry =
|
||||
path:
|
||||
let
|
||||
evaluated = lib.evalModules {
|
||||
specialArgs.lib = registryLib;
|
||||
@@ -79,15 +87,21 @@ let
|
||||
inherit (evaluated.config) type replicate checks;
|
||||
};
|
||||
|
||||
definitions = lib.mapAttrs' (
|
||||
name: type:
|
||||
definitions =
|
||||
lib.mapAttrs'
|
||||
(
|
||||
name: _type:
|
||||
let
|
||||
path = root + "/${name}";
|
||||
in
|
||||
lib.nameValuePair (registryName name) (mkRegistry path)
|
||||
) (lib.filterAttrs (name: type: type == "regular" && lib.hasSuffix ".nix" name) (builtins.readDir root));
|
||||
)
|
||||
(
|
||||
lib.filterAttrs (name: type: type == "regular" && lib.hasSuffix ".nix" name) (builtins.readDir root)
|
||||
);
|
||||
|
||||
flattenRegistryEntries = registryName: data:
|
||||
flattenRegistryEntries =
|
||||
registryName: data:
|
||||
lib.concatLists (
|
||||
lib.mapAttrsToList (
|
||||
host: entries:
|
||||
@@ -98,10 +112,12 @@ let
|
||||
) data
|
||||
);
|
||||
|
||||
rawDeclarations = registryName: hosts:
|
||||
rawDeclarations =
|
||||
registryName: hosts:
|
||||
lib.mapAttrs (_hostName: host: host.config.registry.${registryName} or { }) hosts;
|
||||
|
||||
replicatedEntries = registryName: raw:
|
||||
replicatedEntries =
|
||||
registryName: raw:
|
||||
let
|
||||
entries = lib.concatLists (
|
||||
lib.concatLists (
|
||||
@@ -126,18 +142,21 @@ let
|
||||
else
|
||||
throw "conflicting replicated registry entry ${entry.path} does not match ${acc.${entry.entryName}.path}"
|
||||
else
|
||||
acc // {
|
||||
acc
|
||||
// {
|
||||
${entry.entryName} = entry;
|
||||
}
|
||||
) { } entries;
|
||||
|
||||
replicatedData = registryName: hosts: raw:
|
||||
replicatedData =
|
||||
registryName: hosts: raw:
|
||||
let
|
||||
entries = lib.mapAttrs (_entryName: entry: entry.value) (replicatedEntries registryName raw);
|
||||
in
|
||||
lib.mapAttrs (_hostName: _host: entries) hosts;
|
||||
|
||||
validationAssertions = data:
|
||||
validationAssertions =
|
||||
data:
|
||||
lib.concatLists (
|
||||
lib.mapAttrsToList (
|
||||
registryName: registry:
|
||||
@@ -151,7 +170,8 @@ let
|
||||
) definitions
|
||||
);
|
||||
|
||||
assertValid = data:
|
||||
assertValid =
|
||||
data:
|
||||
let
|
||||
assertions = validationAssertions data;
|
||||
failures = lib.filter (assertion: !assertion.assertion) assertions;
|
||||
@@ -161,9 +181,12 @@ let
|
||||
);
|
||||
data;
|
||||
|
||||
join = registry: host: entry:
|
||||
join =
|
||||
registry: host: entry:
|
||||
lib.filterAttrs (_name: value: value != null) (
|
||||
lib.mapAttrs (registryName: _registry: (registry.${registryName}.${host} or { }).${entry} or null) definitions
|
||||
lib.mapAttrs (
|
||||
registryName: _registry: (registry.${registryName}.${host} or { }).${entry} or null
|
||||
) definitions
|
||||
);
|
||||
|
||||
collectData =
|
||||
@@ -180,7 +203,8 @@ let
|
||||
in
|
||||
assertValid data;
|
||||
|
||||
withOperations = registry:
|
||||
withOperations =
|
||||
registry:
|
||||
registry
|
||||
// {
|
||||
join = host: entry: join registry host entry;
|
||||
@@ -190,8 +214,10 @@ in
|
||||
types = lib.mapAttrs (_name: definition: definition.type) definitions;
|
||||
|
||||
module = {
|
||||
options.registry = lib.mapAttrs (_name: registry: registryOption registry) definitions;
|
||||
options.registry = lib.mapAttrs (_name: registryOption) definitions;
|
||||
};
|
||||
|
||||
collected = withOperations (collectData { inherit hosts; });
|
||||
collected = withOperations (collectData {
|
||||
inherit hosts;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -28,5 +28,14 @@ in
|
||||
hash = builtins.hashString "sha256" name;
|
||||
octet = i: builtins.substring (i * 2) 2 hash;
|
||||
in
|
||||
lib.concatStringsSep ":" ([ "02" ] ++ map octet [ 0 1 2 3 4 ]);
|
||||
lib.concatStringsSep ":" (
|
||||
[ "02" ]
|
||||
++ map octet [
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user