style(nix): apply style fixes #53
@@ -109,31 +109,36 @@ in
|
|||||||
inherit (cfg.reverseProxy) trustedSources;
|
inherit (cfg.reverseProxy) trustedSources;
|
||||||
};
|
};
|
||||||
volumes = lib.mapAttrs (_urlPath: volume: {
|
volumes = lib.mapAttrs (_urlPath: volume: {
|
||||||
inherit (volume) path access flags readOnly;
|
inherit (volume)
|
||||||
|
path
|
||||||
|
access
|
||||||
|
flags
|
||||||
|
readOnly
|
||||||
|
;
|
||||||
}) cfg.volumes;
|
}) cfg.volumes;
|
||||||
};
|
};
|
||||||
|
|
||||||
mounts =
|
mounts = {
|
||||||
{
|
${cfg.stateDir} = {
|
||||||
${cfg.stateDir} = {
|
directory = cfg.statePath;
|
||||||
directory = cfg.statePath;
|
owner = config.registry."stable-uid".${config.networking.hostName}.copyparty;
|
||||||
owner = config.registry."stable-uid".${config.networking.hostName}.copyparty;
|
group = "storage";
|
||||||
group = "storage";
|
mode = "0770";
|
||||||
mode = "0770";
|
};
|
||||||
};
|
${"/run/secrets/${cfg.passwordSecret}"} = {
|
||||||
${"/run/secrets/${cfg.passwordSecret}"} = {
|
file = config.sops.secrets.${cfg.passwordSecret}.path;
|
||||||
file = config.sops.secrets.${cfg.passwordSecret}.path;
|
readOnly = true;
|
||||||
readOnly = true;
|
};
|
||||||
};
|
}
|
||||||
|
// lib.mapAttrs' (
|
||||||
|
_urlPath: volume:
|
||||||
|
lib.nameValuePair volume.path {
|
||||||
|
directory = volume.hostPath;
|
||||||
|
owner = "root";
|
||||||
|
group = "storage";
|
||||||
|
mode = "2770";
|
||||||
}
|
}
|
||||||
// lib.mapAttrs' (_urlPath: volume:
|
) cfg.volumes;
|
||||||
lib.nameValuePair volume.path {
|
|
||||||
directory = volume.hostPath;
|
|
||||||
owner = "root";
|
|
||||||
group = "storage";
|
|
||||||
mode = "2770";
|
|
||||||
}
|
|
||||||
) cfg.volumes;
|
|
||||||
limits = {
|
limits = {
|
||||||
memory = lib.mkDefault "2G";
|
memory = lib.mkDefault "2G";
|
||||||
cpu = lib.mkDefault "200%";
|
cpu = lib.mkDefault "200%";
|
||||||
|
|||||||
@@ -88,43 +88,47 @@ in
|
|||||||
guests.palworld = {
|
guests.palworld = {
|
||||||
interior.modules.services.games.palworld = {
|
interior.modules.services.games.palworld = {
|
||||||
enable = true;
|
enable = true;
|
||||||
inherit (cfg) serverName port publicIP autoStart;
|
inherit (cfg)
|
||||||
|
serverName
|
||||||
|
port
|
||||||
|
publicIP
|
||||||
|
autoStart
|
||||||
|
;
|
||||||
inherit steamDir installDir stateDir;
|
inherit steamDir installDir stateDir;
|
||||||
passwordFile = "/run/secrets/${cfg.passwordSecret}";
|
passwordFile = "/run/secrets/${cfg.passwordSecret}";
|
||||||
adminPasswordFile = "/run/secrets/${cfg.adminPasswordSecret}";
|
adminPasswordFile = "/run/secrets/${cfg.adminPasswordSecret}";
|
||||||
};
|
};
|
||||||
|
|
||||||
mounts =
|
mounts = {
|
||||||
{
|
${steamDir} = {
|
||||||
${steamDir} = {
|
directory = cfg.steamPath;
|
||||||
directory = cfg.steamPath;
|
owner = config.registry."stable-uid".${config.networking.hostName}.steamcmd;
|
||||||
owner = config.registry."stable-uid".${config.networking.hostName}.steamcmd;
|
group = "storage";
|
||||||
group = "storage";
|
mode = "0770";
|
||||||
mode = "0770";
|
|
||||||
};
|
|
||||||
${installDir} = {
|
|
||||||
directory = cfg.installPath;
|
|
||||||
owner = config.registry."stable-uid".${config.networking.hostName}.steamcmd;
|
|
||||||
group = "storage";
|
|
||||||
mode = "0770";
|
|
||||||
};
|
|
||||||
${stateDir} = {
|
|
||||||
directory = cfg.statePath;
|
|
||||||
owner = config.registry."stable-uid".${config.networking.hostName}.steamcmd;
|
|
||||||
group = "storage";
|
|
||||||
mode = "0770";
|
|
||||||
};
|
|
||||||
${"/run/secrets/${cfg.passwordSecret}"} = {
|
|
||||||
file = config.sops.secrets.${cfg.passwordSecret}.path;
|
|
||||||
readOnly = true;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// lib.optionalAttrs (cfg.adminPasswordSecret != cfg.passwordSecret) {
|
|
||||||
${"/run/secrets/${cfg.adminPasswordSecret}"} = {
|
|
||||||
file = config.sops.secrets.${cfg.adminPasswordSecret}.path;
|
|
||||||
readOnly = true;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
${installDir} = {
|
||||||
|
directory = cfg.installPath;
|
||||||
|
owner = config.registry."stable-uid".${config.networking.hostName}.steamcmd;
|
||||||
|
group = "storage";
|
||||||
|
mode = "0770";
|
||||||
|
};
|
||||||
|
${stateDir} = {
|
||||||
|
directory = cfg.statePath;
|
||||||
|
owner = config.registry."stable-uid".${config.networking.hostName}.steamcmd;
|
||||||
|
group = "storage";
|
||||||
|
mode = "0770";
|
||||||
|
};
|
||||||
|
${"/run/secrets/${cfg.passwordSecret}"} = {
|
||||||
|
file = config.sops.secrets.${cfg.passwordSecret}.path;
|
||||||
|
readOnly = true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// lib.optionalAttrs (cfg.adminPasswordSecret != cfg.passwordSecret) {
|
||||||
|
${"/run/secrets/${cfg.adminPasswordSecret}"} = {
|
||||||
|
file = config.sops.secrets.${cfg.adminPasswordSecret}.path;
|
||||||
|
readOnly = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
limits = {
|
limits = {
|
||||||
memory = lib.mkDefault "8G";
|
memory = lib.mkDefault "8G";
|
||||||
@@ -133,20 +137,19 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
sops.secrets =
|
sops.secrets = {
|
||||||
{
|
${cfg.passwordSecret} = {
|
||||||
${cfg.passwordSecret} = {
|
owner = "root";
|
||||||
owner = "root";
|
group = "storage";
|
||||||
group = "storage";
|
mode = "0440";
|
||||||
mode = "0440";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// lib.optionalAttrs (cfg.adminPasswordSecret != cfg.passwordSecret) {
|
|
||||||
${cfg.adminPasswordSecret} = {
|
|
||||||
owner = "root";
|
|
||||||
group = "storage";
|
|
||||||
mode = "0440";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
// lib.optionalAttrs (cfg.adminPasswordSecret != cfg.passwordSecret) {
|
||||||
|
${cfg.adminPasswordSecret} = {
|
||||||
|
owner = "root";
|
||||||
|
group = "storage";
|
||||||
|
mode = "0440";
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
registry.shell-shortcut.neogaia = {
|
registry.shell-shortcut.neogaia = {
|
||||||
vpn-on = "sudo systemctl start wireguard-wg-home.target";
|
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;
|
modules.monorepo.enable = true;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
{ ... }:
|
_:
|
||||||
# neogaia's disk layout for disko: one NVMe disk, GPT, with an EFI system
|
# neogaia's disk layout for disko: one NVMe disk, GPT, with an EFI system
|
||||||
# partition and a LUKS container holding btrfs subvolumes.
|
# partition and a LUKS container holding btrfs subvolumes.
|
||||||
# No swap partition, since swap is zram.
|
# 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.
|
# 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.
|
# 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.
|
# Disk layout is in ./disk.nix.
|
||||||
# `fileSystems` are derived from it, none declared here.
|
# `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";
|
nixpkgs.hostPlatform = "x86_64-linux";
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
{ ... }:
|
_:
|
||||||
# zeus's disk layout for disko: two NVMe disks with one EFI system partition
|
# zeus's disk layout for disko: two NVMe disks with one EFI system partition
|
||||||
# and two LUKS containers joined into one btrfs filesystem.
|
# and two LUKS containers joined into one btrfs filesystem.
|
||||||
# No swap partition, since swap is zram.
|
# No swap partition, since swap is zram.
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ let
|
|||||||
user = config.user.name;
|
user = config.user.name;
|
||||||
in
|
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 {
|
config = lib.mkIf cfg.enable {
|
||||||
home-manager.users.${user}.home.packages = [ pkgs.alacritty ];
|
home-manager.users.${user}.home.packages = [ pkgs.alacritty ];
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ let
|
|||||||
user = config.user.name;
|
user = config.user.name;
|
||||||
in
|
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 {
|
config = lib.mkIf cfg.enable {
|
||||||
home-manager.users.${user}.home.packages = [ pkgs.obsidian ];
|
home-manager.users.${user}.home.packages = [ pkgs.obsidian ];
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ let
|
|||||||
user = config.user.name;
|
user = config.user.name;
|
||||||
in
|
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 {
|
config = lib.mkIf cfg.enable {
|
||||||
home-manager.users.${user}.home.packages = [ pkgs.vesktop ];
|
home-manager.users.${user}.home.packages = [ pkgs.vesktop ];
|
||||||
|
|||||||
@@ -67,22 +67,21 @@ in
|
|||||||
# UWSM launches the session without the shell profile that would carry
|
# UWSM launches the session without the shell profile that would carry
|
||||||
# them, so a variable the compositor or its children must see is set
|
# them, so a variable the compositor or its children must see is set
|
||||||
# here rather than through home-manager's sessionVariables.
|
# here rather than through home-manager's sessionVariables.
|
||||||
env =
|
env = [
|
||||||
[
|
# Chromium and Electron apps read this to select native Wayland;
|
||||||
# Chromium and Electron apps read this to select native Wayland;
|
# nixpkgs wrappers (Obsidian's included) gate their Wayland flags on
|
||||||
# nixpkgs wrappers (Obsidian's included) gate their Wayland flags on
|
# it, so without it they run under XWayland and blur at this DPI.
|
||||||
# it, so without it they run under XWayland and blur at this DPI.
|
"NIXOS_OZONE_WL,1"
|
||||||
"NIXOS_OZONE_WL,1"
|
]
|
||||||
]
|
# Bibata ships XCursor only.
|
||||||
# Bibata ships XCursor only.
|
# The hyprcursor variables name the same theme, which Hyprland
|
||||||
# The hyprcursor variables name the same theme, which Hyprland
|
# resolves through its XCursor fallback.
|
||||||
# resolves through its XCursor fallback.
|
++ lib.optionals (cursor != null) [
|
||||||
++ lib.optionals (cursor != null) [
|
"XCURSOR_THEME,${cursor.name}"
|
||||||
"XCURSOR_THEME,${cursor.name}"
|
"XCURSOR_SIZE,${toString cursor.size}"
|
||||||
"XCURSOR_SIZE,${toString cursor.size}"
|
"HYPRCURSOR_THEME,${cursor.name}"
|
||||||
"HYPRCURSOR_THEME,${cursor.name}"
|
"HYPRCURSOR_SIZE,${toString cursor.size}"
|
||||||
"HYPRCURSOR_SIZE,${toString cursor.size}"
|
];
|
||||||
];
|
|
||||||
|
|
||||||
input = {
|
input = {
|
||||||
kb_layout = "us";
|
kb_layout = "us";
|
||||||
|
|||||||
@@ -45,7 +45,8 @@ let
|
|||||||
'';
|
'';
|
||||||
in
|
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 {
|
config = lib.mkIf cfg.enable {
|
||||||
home-manager.users.${user} = {
|
home-manager.users.${user} = {
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ let
|
|||||||
cfg = config.modules.desktop.session.login;
|
cfg = config.modules.desktop.session.login;
|
||||||
in
|
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 {
|
config = lib.mkIf cfg.enable {
|
||||||
services.greetd = {
|
services.greetd = {
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ let
|
|||||||
'';
|
'';
|
||||||
in
|
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 {
|
config = lib.mkIf cfg.enable {
|
||||||
home-manager.users.${user} = {
|
home-manager.users.${user} = {
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ let
|
|||||||
user = config.user.name;
|
user = config.user.name;
|
||||||
in
|
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 {
|
config = lib.mkIf cfg.enable {
|
||||||
environment.systemPackages = [ pkgs.swayosd ];
|
environment.systemPackages = [ pkgs.swayosd ];
|
||||||
|
|||||||
@@ -41,7 +41,8 @@ let
|
|||||||
'';
|
'';
|
||||||
in
|
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 {
|
config = lib.mkIf cfg.enable {
|
||||||
home-manager.users.${user} = {
|
home-manager.users.${user} = {
|
||||||
|
|||||||
@@ -32,7 +32,8 @@ let
|
|||||||
'';
|
'';
|
||||||
in
|
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 {
|
config = lib.mkIf cfg.enable {
|
||||||
home-manager.users.${user} = {
|
home-manager.users.${user} = {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
cfg = config.modules.host;
|
cfg = config.modules.host;
|
||||||
user = config.user;
|
inherit (config) user;
|
||||||
hostSecrets = ../secrets + "/${config.networking.hostName}.yaml";
|
hostSecrets = ../secrets + "/${config.networking.hostName}.yaml";
|
||||||
passwordSecret = "${user.name}-password";
|
passwordSecret = "${user.name}-password";
|
||||||
in
|
in
|
||||||
|
|||||||
@@ -104,8 +104,7 @@ let
|
|||||||
isWorkstation = elem currentHost cfg.hosts.workstations;
|
isWorkstation = elem currentHost cfg.hosts.workstations;
|
||||||
|
|
||||||
defaultAuthorizedKeys = lib.flatten (
|
defaultAuthorizedKeys = lib.flatten (
|
||||||
clientKeysFor workstationNames
|
clientKeysFor workstationNames ++ optional isServer (clientKeysFor serverNames)
|
||||||
++ optional isServer (clientKeysFor serverNames)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
outboundTargetNames =
|
outboundTargetNames =
|
||||||
@@ -120,7 +119,8 @@ let
|
|||||||
in
|
in
|
||||||
filter (name: name != currentHost) (targetNamesIn groupTargets);
|
filter (name: name != currentHost) (targetNamesIn groupTargets);
|
||||||
|
|
||||||
sshSettingsFor = name:
|
sshSettingsFor =
|
||||||
|
name:
|
||||||
let
|
let
|
||||||
target = cfg.targets.${name};
|
target = cfg.targets.${name};
|
||||||
in
|
in
|
||||||
@@ -131,7 +131,8 @@ let
|
|||||||
}
|
}
|
||||||
// optionalAttrs (target.port != 22) { Port = target.port; };
|
// optionalAttrs (target.port != 22) { Port = target.port; };
|
||||||
|
|
||||||
knownHostNamesFor = target:
|
knownHostNamesFor =
|
||||||
|
target:
|
||||||
let
|
let
|
||||||
names = unique (target.aliases ++ [ target.hostName ]);
|
names = unique (target.aliases ++ [ target.hostName ]);
|
||||||
withPort = name: if target.port == 22 then name else "[${name}]:${toString target.port}";
|
withPort = name: if target.port == 22 then name else "[${name}]:${toString target.port}";
|
||||||
@@ -142,7 +143,8 @@ let
|
|||||||
concatLists (
|
concatLists (
|
||||||
mapAttrsToList (
|
mapAttrsToList (
|
||||||
targetName: target:
|
targetName: target:
|
||||||
imap0 (i: key:
|
imap0 (
|
||||||
|
i: key:
|
||||||
nameValuePair "${targetName}-${toString i}" {
|
nameValuePair "${targetName}-${toString i}" {
|
||||||
hostNames = knownHostNamesFor target;
|
hostNames = knownHostNamesFor target;
|
||||||
publicKey = keyWithoutComment key;
|
publicKey = keyWithoutComment key;
|
||||||
@@ -290,58 +292,56 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf cfg.enable (
|
config = mkIf cfg.enable (mkMerge [
|
||||||
mkMerge [
|
{
|
||||||
{
|
services.openssh.enable = true;
|
||||||
services.openssh.enable = true;
|
|
||||||
|
|
||||||
users.users.${user}.openssh.authorizedKeys.keys =
|
users.users.${user}.openssh.authorizedKeys.keys =
|
||||||
if cfg.authorizedKeys != null then
|
if cfg.authorizedKeys != null then
|
||||||
cfg.authorizedKeys
|
cfg.authorizedKeys
|
||||||
else
|
else
|
||||||
defaultAuthorizedKeys ++ cfg.extraAuthorizedKeys;
|
defaultAuthorizedKeys ++ cfg.extraAuthorizedKeys;
|
||||||
|
|
||||||
programs.ssh.knownHosts = knownHosts;
|
programs.ssh.knownHosts = knownHosts;
|
||||||
|
|
||||||
home-manager.users.${user}.programs.ssh = {
|
home-manager.users.${user}.programs.ssh = {
|
||||||
enable = true;
|
enable = true;
|
||||||
enableDefaultConfig = false;
|
enableDefaultConfig = false;
|
||||||
settings =
|
settings =
|
||||||
mapAttrs (name: _: sshSettingsFor name) (genAttrs outboundTargetNames (name: name))
|
mapAttrs (name: _: sshSettingsFor name) (genAttrs outboundTargetNames (name: name))
|
||||||
// cfg.extraSettings;
|
// cfg.extraSettings;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
(mkIf cfg.hostKeys.restore {
|
(mkIf cfg.hostKeys.restore {
|
||||||
assertions = [
|
assertions = [
|
||||||
{
|
{
|
||||||
assertion = cfg.hostKeys.sopsFile != null;
|
assertion = cfg.hostKeys.sopsFile != null;
|
||||||
message = "modules.network.ssh.hostKeys.restore requires modules.network.ssh.hostKeys.sopsFile to name the encrypted host keys.";
|
message = "modules.network.ssh.hostKeys.restore requires modules.network.ssh.hostKeys.sopsFile to name the encrypted host keys.";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
sops.secrets = genAttrs (map hostKeySecret cfg.hostKeys.types) (_: {
|
sops.secrets = genAttrs (map hostKeySecret cfg.hostKeys.types) (_: {
|
||||||
inherit (cfg.hostKeys) sopsFile;
|
inherit (cfg.hostKeys) sopsFile;
|
||||||
mode = "0400";
|
mode = "0400";
|
||||||
restartUnits = [ "sshd.service" ];
|
restartUnits = [ "sshd.service" ];
|
||||||
});
|
});
|
||||||
|
|
||||||
services.openssh.hostKeys = [ ];
|
services.openssh.hostKeys = [ ];
|
||||||
services.openssh.extraConfig = concatStringsSep "" (
|
services.openssh.extraConfig = concatStringsSep "" (
|
||||||
map (type: "HostKey ${config.sops.secrets.${hostKeySecret type}.path}\n") cfg.hostKeys.types
|
map (type: "HostKey ${config.sops.secrets.${hostKeySecret type}.path}\n") cfg.hostKeys.types
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
|
|
||||||
(mkIf (cfg.userKey.sopsFile != null) {
|
(mkIf (cfg.userKey.sopsFile != null) {
|
||||||
sops.secrets.${userKeySecret} = {
|
sops.secrets.${userKeySecret} = {
|
||||||
inherit (cfg.userKey) sopsFile;
|
inherit (cfg.userKey) sopsFile;
|
||||||
mode = "0400";
|
mode = "0400";
|
||||||
owner = user;
|
owner = user;
|
||||||
};
|
};
|
||||||
|
|
||||||
home-manager.users.${user}.programs.ssh.settings."*".IdentityFile =
|
home-manager.users.${user}.programs.ssh.settings."*".IdentityFile =
|
||||||
config.sops.secrets.${userKeySecret}.path;
|
config.sops.secrets.${userKeySecret}.path;
|
||||||
})
|
})
|
||||||
]
|
]);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,10 +75,11 @@ in
|
|||||||
];
|
];
|
||||||
|
|
||||||
# networkd owns these interfaces so NetworkManager does not contend for them.
|
# networkd owns these interfaces so NetworkManager does not contend for them.
|
||||||
networking.networkmanager.unmanaged =
|
networking.networkmanager.unmanaged = [
|
||||||
[ "interface-name:${cfg.trunk}" ]
|
"interface-name:${cfg.trunk}"
|
||||||
++ map (id: "interface-name:${bridgeName id}") cfg.ids
|
]
|
||||||
++ map (id: "interface-name:${vlanName id}") cfg.ids;
|
++ map (id: "interface-name:${bridgeName id}") cfg.ids
|
||||||
|
++ map (id: "interface-name:${vlanName id}") cfg.ids;
|
||||||
|
|
||||||
systemd.network = {
|
systemd.network = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|||||||
@@ -88,16 +88,18 @@ in
|
|||||||
|
|
||||||
networking.wireguard.interfaces.${cfg.interface} = {
|
networking.wireguard.interfaces.${cfg.interface} = {
|
||||||
ips = [ cfg.address ];
|
ips = [ cfg.address ];
|
||||||
mtu = cfg.mtu;
|
inherit (cfg) mtu;
|
||||||
privateKeyFile = config.sops.secrets.${cfg.privateKeySecret}.path;
|
privateKeyFile = config.sops.secrets.${cfg.privateKeySecret}.path;
|
||||||
|
|
||||||
peers = [
|
peers = [
|
||||||
({
|
(
|
||||||
inherit (cfg.peer) publicKey endpoint allowedIPs;
|
{
|
||||||
}
|
inherit (cfg.peer) publicKey endpoint allowedIPs;
|
||||||
// lib.optionalAttrs (cfg.peer.persistentKeepalive != null) {
|
}
|
||||||
inherit (cfg.peer) persistentKeepalive;
|
// lib.optionalAttrs (cfg.peer.persistentKeepalive != null) {
|
||||||
})
|
inherit (cfg.peer) persistentKeepalive;
|
||||||
|
}
|
||||||
|
)
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -45,14 +45,14 @@ in
|
|||||||
users.users.${cfg.user} = {
|
users.users.${cfg.user} = {
|
||||||
isSystemUser = true;
|
isSystemUser = true;
|
||||||
uid = config.registry."stable-uid".${config.networking.hostName}.actualbudget;
|
uid = config.registry."stable-uid".${config.networking.hostName}.actualbudget;
|
||||||
group = cfg.group;
|
inherit (cfg) group;
|
||||||
};
|
};
|
||||||
|
|
||||||
services.actual = {
|
services.actual = {
|
||||||
enable = true;
|
enable = true;
|
||||||
openFirewall = true;
|
openFirewall = true;
|
||||||
user = cfg.user;
|
inherit (cfg) user;
|
||||||
group = cfg.group;
|
inherit (cfg) group;
|
||||||
settings = {
|
settings = {
|
||||||
inherit (cfg) port dataDir;
|
inherit (cfg) port dataDir;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -40,13 +40,16 @@ let
|
|||||||
|
|
||||||
renderAccess = permission: accounts: " ${permission}: ${lib.concatStringsSep ", " accounts}";
|
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_d" flags)) [ "chmod_d: 2770" ]
|
||||||
++ lib.optionals (!(hasFlag "chmod_f" flags)) [ "chmod_f: 660" ];
|
++ 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: ''
|
renderVolume = urlPath: volume: ''
|
||||||
[${urlPath}]
|
[${urlPath}]
|
||||||
@@ -54,8 +57,8 @@ let
|
|||||||
accs:
|
accs:
|
||||||
${lib.concatStringsSep "\n" (lib.mapAttrsToList renderAccess volume.access)}
|
${lib.concatStringsSep "\n" (lib.mapAttrsToList renderAccess volume.access)}
|
||||||
${lib.optionalString (volume.flags != [ ]) ''
|
${lib.optionalString (volume.flags != [ ]) ''
|
||||||
flags:
|
flags:
|
||||||
${renderFlags volume.flags}
|
${renderFlags volume.flags}
|
||||||
''}
|
''}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
@@ -173,7 +176,7 @@ in
|
|||||||
users.users.${cfg.user} = {
|
users.users.${cfg.user} = {
|
||||||
isSystemUser = true;
|
isSystemUser = true;
|
||||||
uid = config.registry."stable-uid".${config.networking.hostName}.copyparty;
|
uid = config.registry."stable-uid".${config.networking.hostName}.copyparty;
|
||||||
group = cfg.group;
|
inherit (cfg) group;
|
||||||
home = cfg.stateDir;
|
home = cfg.stateDir;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -202,7 +205,10 @@ in
|
|||||||
PrivateTmp = true;
|
PrivateTmp = true;
|
||||||
ProtectSystem = "strict";
|
ProtectSystem = "strict";
|
||||||
ProtectHome = true;
|
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,19 +134,18 @@
|
|||||||
appId = 2394010;
|
appId = 2394010;
|
||||||
inherit (service) autoStart;
|
inherit (service) autoStart;
|
||||||
executable = "${startScript}";
|
executable = "${startScript}";
|
||||||
arguments =
|
arguments = [
|
||||||
[
|
"-useperfthreads"
|
||||||
"-useperfthreads"
|
"-NoAsyncLoadingThread"
|
||||||
"-NoAsyncLoadingThread"
|
"-UseMultithreadForDS"
|
||||||
"-UseMultithreadForDS"
|
"-port=${toString service.port}"
|
||||||
"-port=${toString service.port}"
|
"-publicport=${toString service.port}"
|
||||||
"-publicport=${toString service.port}"
|
"-servername=${service.serverName}"
|
||||||
"-servername=${service.serverName}"
|
"-players=${toString service.maxPlayers}"
|
||||||
"-players=${toString service.maxPlayers}"
|
]
|
||||||
]
|
++ lib.optional service.publicLobby "-publiclobby"
|
||||||
++ lib.optional service.publicLobby "-publiclobby"
|
++ lib.optionals (service.publicIP != null) [ "-publicip=${service.publicIP}" ]
|
||||||
++ lib.optionals (service.publicIP != null) [ "-publicip=${service.publicIP}" ]
|
++ lib.optional service.rcon.enable "-rcon";
|
||||||
++ lib.optional service.rcon.enable "-rcon";
|
|
||||||
udpPorts = [ service.port ];
|
udpPorts = [ service.port ];
|
||||||
tcpPorts = [ service.port ];
|
tcpPorts = [ service.port ];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,7 +7,9 @@
|
|||||||
let
|
let
|
||||||
cfg = config.modules.services.homepage;
|
cfg = config.modules.services.homepage;
|
||||||
|
|
||||||
mkRegistryPath = registryName: host: entry: "registry.${registryName}.${host}.${entry}";
|
mkRegistryPath =
|
||||||
|
registryName: host: entry:
|
||||||
|
"registry.${registryName}.${host}.${entry}";
|
||||||
|
|
||||||
homepageEntries = lib.concatLists (
|
homepageEntries = lib.concatLists (
|
||||||
lib.mapAttrsToList (
|
lib.mapAttrsToList (
|
||||||
@@ -19,7 +21,8 @@ let
|
|||||||
) registry.homepage
|
) registry.homepage
|
||||||
);
|
);
|
||||||
|
|
||||||
mkHref = item:
|
mkHref =
|
||||||
|
item:
|
||||||
if item.homepage.href != null then
|
if item.homepage.href != null then
|
||||||
item.homepage.href
|
item.homepage.href
|
||||||
else if (item.composite.route or null) != null then
|
else if (item.composite.route or null) != null then
|
||||||
@@ -32,7 +35,8 @@ let
|
|||||||
else
|
else
|
||||||
throw "${mkRegistryPath "homepage" item.host item.entry} needs href or a matching route entry";
|
throw "${mkRegistryPath "homepage" item.host item.entry} needs href or a matching route entry";
|
||||||
|
|
||||||
mkServiceAttrs = item:
|
mkServiceAttrs =
|
||||||
|
item:
|
||||||
lib.filterAttrs (_: value: value != null) {
|
lib.filterAttrs (_: value: value != null) {
|
||||||
href = mkHref item;
|
href = mkHref item;
|
||||||
inherit (item.homepage) description icon;
|
inherit (item.homepage) description icon;
|
||||||
@@ -40,15 +44,15 @@ let
|
|||||||
|
|
||||||
sortedEntries = lib.sort (left: right: left.homepage.name < right.homepage.name) homepageEntries;
|
sortedEntries = lib.sort (left: right: left.homepage.name < right.homepage.name) homepageEntries;
|
||||||
|
|
||||||
insertEntry = acc: item:
|
insertEntry =
|
||||||
|
acc: item:
|
||||||
acc
|
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.section} = (acc.${item.homepage.tab}.${item.homepage.section} or [ ]) ++ [
|
{ ${item.homepage.name} = mkServiceAttrs item; }
|
||||||
{ ${item.homepage.name} = mkServiceAttrs item; }
|
];
|
||||||
];
|
};
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
entriesByTab = lib.foldl' insertEntry { } sortedEntries;
|
entriesByTab = lib.foldl' insertEntry { } sortedEntries;
|
||||||
@@ -80,13 +84,15 @@ let
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
orderedSections = tab: sections:
|
orderedSections =
|
||||||
|
tab: sections:
|
||||||
let
|
let
|
||||||
sectionOrder = sectionOrderByTab.${tab} or [ ];
|
sectionOrder = sectionOrderByTab.${tab} or [ ];
|
||||||
in
|
in
|
||||||
sectionOrder ++ lib.filter (section: !lib.elem section sectionOrder) (lib.attrNames sections);
|
sectionOrder ++ lib.filter (section: !lib.elem section sectionOrder) (lib.attrNames sections);
|
||||||
|
|
||||||
mkTab = tab:
|
mkTab =
|
||||||
|
tab:
|
||||||
let
|
let
|
||||||
sections = entriesByTab.${tab};
|
sections = entriesByTab.${tab};
|
||||||
in
|
in
|
||||||
@@ -148,7 +154,9 @@ in
|
|||||||
openFirewall = true;
|
openFirewall = true;
|
||||||
inherit (cfg) listenPort;
|
inherit (cfg) listenPort;
|
||||||
environmentFiles = [ cfg.environmentFile ];
|
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;
|
services = homepageServices;
|
||||||
widgets = [
|
widgets = [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ in
|
|||||||
user = "navidrome";
|
user = "navidrome";
|
||||||
group = "storage";
|
group = "storage";
|
||||||
openFirewall = true;
|
openFirewall = true;
|
||||||
environmentFile = cfg.environmentFile;
|
inherit (cfg) environmentFile;
|
||||||
settings = {
|
settings = {
|
||||||
Address = "0.0.0.0";
|
Address = "0.0.0.0";
|
||||||
Port = 4533;
|
Port = 4533;
|
||||||
|
|||||||
@@ -7,15 +7,20 @@
|
|||||||
let
|
let
|
||||||
cfg = config.modules.services.reverse-proxy;
|
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}";
|
mkBackend = address: port: "http://${address}:${toString port}";
|
||||||
|
|
||||||
mkVirtualHost = host: entry: mode:
|
mkVirtualHost =
|
||||||
|
host: entry: mode:
|
||||||
let
|
let
|
||||||
compositeEntry = registry.join host entry;
|
compositeEntry = registry.join host entry;
|
||||||
route = compositeEntry.route;
|
inherit (compositeEntry) route;
|
||||||
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}");
|
||||||
isHttp = mode == "http";
|
isHttp = mode == "http";
|
||||||
port = if isHttp then route.http.port else route.port;
|
port = if isHttp then route.http.port else route.port;
|
||||||
in
|
in
|
||||||
@@ -63,7 +68,11 @@ let
|
|||||||
domain: virtualHosts:
|
domain: virtualHosts:
|
||||||
if lib.length virtualHosts > 1 then
|
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
|
else
|
||||||
[ ]
|
[ ]
|
||||||
@@ -76,13 +85,21 @@ let
|
|||||||
else
|
else
|
||||||
lib.listToAttrs generatedVirtualHostList;
|
lib.listToAttrs generatedVirtualHostList;
|
||||||
|
|
||||||
mkUdpStream = host: entry: port:
|
mkUdpStream =
|
||||||
|
host: entry: port:
|
||||||
let
|
let
|
||||||
compositeEntry = registry.join host entry;
|
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
|
in
|
||||||
{
|
{
|
||||||
inherit host entry port address;
|
inherit
|
||||||
|
host
|
||||||
|
entry
|
||||||
|
port
|
||||||
|
address
|
||||||
|
;
|
||||||
};
|
};
|
||||||
|
|
||||||
generatedUdpStreams = lib.concatLists (
|
generatedUdpStreams = lib.concatLists (
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ let
|
|||||||
user = config.user.name;
|
user = config.user.name;
|
||||||
in
|
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 {
|
config = lib.mkIf cfg.enable {
|
||||||
home-manager.users.${user}.home.packages = [ pkgs.bazel ];
|
home-manager.users.${user}.home.packages = [ pkgs.bazel ];
|
||||||
|
|||||||
@@ -107,8 +107,7 @@ in
|
|||||||
|
|
||||||
# Rendered by home-manager into ~/.config/fish/config.fish.
|
# Rendered by home-manager into ~/.config/fish/config.fish.
|
||||||
interactiveShellInit = lib.concatStringsSep "\n" (
|
interactiveShellInit = lib.concatStringsSep "\n" (
|
||||||
(lib.mapAttrsToList exportEnvVar envVars)
|
(lib.mapAttrsToList exportEnvVar envVars) ++ [ (builtins.readFile ./config.fish) ]
|
||||||
++ [ (builtins.readFile ./config.fish) ]
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ let
|
|||||||
user = config.user.name;
|
user = config.user.name;
|
||||||
in
|
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 {
|
config = lib.mkIf cfg.enable {
|
||||||
registry.shell-shortcut.${config.networking.hostName}.hs = "herdr --session";
|
registry.shell-shortcut.${config.networking.hostName}.hs = "herdr --session";
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ let
|
|||||||
user = config.user.name;
|
user = config.user.name;
|
||||||
in
|
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 {
|
config = lib.mkIf cfg.enable {
|
||||||
registry.shell-shortcut.${config.networking.hostName} = {
|
registry.shell-shortcut.${config.networking.hostName} = {
|
||||||
|
|||||||
@@ -18,8 +18,7 @@ let
|
|||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.modules.shell.pi = {
|
options.modules.shell.pi = {
|
||||||
enable = lib.mkEnableOption ''
|
enable = lib.mkEnableOption "Pi, a terminal coding agent, configured through home-manager";
|
||||||
Pi, a terminal coding agent, configured through home-manager'';
|
|
||||||
};
|
};
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ let
|
|||||||
user = config.user.name;
|
user = config.user.name;
|
||||||
in
|
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 {
|
config = lib.mkIf cfg.enable {
|
||||||
registry.env-var.${config.networking.hostName}.PYTHON_TOOLCHAIN_ROOT = "${pkgs.python3}";
|
registry.env-var.${config.networking.hostName}.PYTHON_TOOLCHAIN_ROOT = "${pkgs.python3}";
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ let
|
|||||||
};
|
};
|
||||||
in
|
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 {
|
config = lib.mkIf cfg.enable {
|
||||||
registry.env-var.${config.networking.hostName}.RUST_TOOLCHAIN_ROOT = "${toolchain}";
|
registry.env-var.${config.networking.hostName}.RUST_TOOLCHAIN_ROOT = "${toolchain}";
|
||||||
|
|||||||
@@ -6,14 +6,16 @@
|
|||||||
message = "Route domains must be unique.";
|
message = "Route domains must be unique.";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
assertion = entries:
|
assertion =
|
||||||
|
entries:
|
||||||
lib.registry.predicates.uniqueValue (entry: entry.value) (
|
lib.registry.predicates.uniqueValue (entry: entry.value) (
|
||||||
lib.concatMap (entry: map (port: entry // { value = port; }) entry.value.udp.ports) entries
|
lib.concatMap (entry: map (port: entry // { value = port; }) entry.value.udp.ports) entries
|
||||||
);
|
);
|
||||||
message = "Route UDP ports must be unique.";
|
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.";
|
message = "Route entries must not set both port and http.port.";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -7,12 +7,14 @@ let
|
|||||||
unique
|
unique
|
||||||
;
|
;
|
||||||
|
|
||||||
serviceNamesByUid = entries:
|
serviceNamesByUid =
|
||||||
|
entries:
|
||||||
mapAttrs (_uid: uidEntries: unique (map (entry: entry.entry) uidEntries)) (
|
mapAttrs (_uid: uidEntries: unique (map (entry: entry.entry) uidEntries)) (
|
||||||
groupBy (entry: toString entry.value) entries
|
groupBy (entry: toString entry.value) entries
|
||||||
);
|
);
|
||||||
|
|
||||||
duplicateUids = entries:
|
duplicateUids =
|
||||||
|
entries:
|
||||||
filterAttrs (_uid: serviceNames: builtins.length serviceNames > 1) (serviceNamesByUid entries);
|
filterAttrs (_uid: serviceNames: builtins.length serviceNames > 1) (serviceNamesByUid entries);
|
||||||
|
|
||||||
in
|
in
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
{ self, nixpkgs, ... }@inputs:
|
{ self, nixpkgs, ... }@inputs:
|
||||||
import ./src/dotfiles {
|
import ./src/dotfiles {
|
||||||
inherit inputs self;
|
inherit inputs self;
|
||||||
lib = nixpkgs.lib;
|
inherit (nixpkgs) lib;
|
||||||
root = ./configs/nixos;
|
root = ./configs/nixos;
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,19 +10,21 @@ in
|
|||||||
{
|
{
|
||||||
fix = {
|
fix = {
|
||||||
type = "app";
|
type = "app";
|
||||||
program = lib.getExe (pkgs.writeShellApplication {
|
program = lib.getExe (
|
||||||
name = "fix";
|
pkgs.writeShellApplication {
|
||||||
runtimeInputs = [
|
name = "fix";
|
||||||
formatter.config.build.wrapper
|
runtimeInputs = [
|
||||||
pkgs.statix
|
formatter.config.build.wrapper
|
||||||
pkgs.deadnix
|
pkgs.statix
|
||||||
];
|
pkgs.deadnix
|
||||||
text = ''
|
];
|
||||||
treefmt
|
text = ''
|
||||||
statix fix .
|
treefmt
|
||||||
deadnix --edit --exclude configs/nixos/hosts/*/hardware-configuration.nix -- .
|
statix fix .
|
||||||
treefmt
|
deadnix --edit --exclude configs/nixos/hosts/*/hardware-configuration.nix -- .
|
||||||
'';
|
treefmt
|
||||||
});
|
'';
|
||||||
|
}
|
||||||
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,16 +17,13 @@ let
|
|||||||
directoryMounts = lib.filterAttrs (_: mount: mount.directory != null) cfg.mounts;
|
directoryMounts = lib.filterAttrs (_: mount: mount.directory != null) cfg.mounts;
|
||||||
|
|
||||||
directoryScript = lib.concatStringsSep "\n" (
|
directoryScript = lib.concatStringsSep "\n" (
|
||||||
lib.mapAttrsToList (
|
lib.mapAttrsToList (_: mount: ''
|
||||||
_: mount:
|
${config.system.path}/bin/install -d \
|
||||||
''
|
${lib.optionalString (mount.owner != null) "-o ${lib.escapeShellArg (toString mount.owner)}"} \
|
||||||
${config.system.path}/bin/install -d \
|
${lib.optionalString (mount.group != null) "-g ${lib.escapeShellArg mount.group}"} \
|
||||||
${lib.optionalString (mount.owner != null) "-o ${lib.escapeShellArg (toString mount.owner)}"} \
|
${lib.optionalString (mount.mode != null) "-m ${lib.escapeShellArg mount.mode}"} \
|
||||||
${lib.optionalString (mount.group != null) "-g ${lib.escapeShellArg mount.group}"} \
|
${lib.escapeShellArg mount.directory}
|
||||||
${lib.optionalString (mount.mode != null) "-m ${lib.escapeShellArg mount.mode}"} \
|
'') directoryMounts
|
||||||
${lib.escapeShellArg mount.directory}
|
|
||||||
''
|
|
||||||
) directoryMounts
|
|
||||||
);
|
);
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
@@ -171,14 +168,20 @@ let
|
|||||||
assertions =
|
assertions =
|
||||||
let
|
let
|
||||||
hasDirectorySettings = mount: mount.owner != null || mount.group != null || mount.mode != null;
|
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);
|
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 (
|
fileMountsWithHostSettings = lib.attrNames (
|
||||||
lib.filterAttrs (_: mount: mount.file != null && hasDirectorySettings mount) cfg.mounts
|
lib.filterAttrs (_: mount: mount.file != null && hasDirectorySettings mount) cfg.mounts
|
||||||
);
|
);
|
||||||
directoryMountsWithPartialHostSettings = lib.attrNames (
|
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
|
in
|
||||||
[
|
[
|
||||||
@@ -203,20 +206,23 @@ let
|
|||||||
{
|
{
|
||||||
assertion = lib.elem cfg.vlan config.modules.network.vlans.ids;
|
assertion = lib.elem cfg.vlan config.modules.network.vlans.ids;
|
||||||
message = ''
|
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} =
|
registry.address.${config.networking.hostName}.${name} = lib.mkIf (cfg.address != null) cfg.address;
|
||||||
lib.mkIf (cfg.address != null) cfg.address;
|
|
||||||
|
|
||||||
registry.route.${config.networking.hostName}.${name} =
|
registry.route.${config.networking.hostName}.${name} =
|
||||||
lib.mkIf cfg.reverseProxy.enable cfg.reverseProxy.route;
|
lib.mkIf cfg.reverseProxy.enable cfg.reverseProxy.route;
|
||||||
|
|
||||||
systemd.services."container@${name}" =
|
systemd.services."container@${name}" =
|
||||||
let
|
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
|
in
|
||||||
{
|
{
|
||||||
after = [ bridgeDevice ];
|
after = [ bridgeDevice ];
|
||||||
@@ -268,10 +274,11 @@ let
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
in
|
|
||||||
let
|
|
||||||
files = util.collectNixFiles root;
|
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);
|
names = map (file: lib.removeSuffix ".nix" file) (lib.attrNames guestFiles);
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ let
|
|||||||
guestModules
|
guestModules
|
||||||
|
|
||||||
# TODO: refactor
|
# TODO: refactor
|
||||||
registryModule (root + "/${name}")
|
registryModule
|
||||||
|
(root + "/${name}")
|
||||||
|
|
||||||
{
|
{
|
||||||
networking.hostName = name;
|
networking.hostName = name;
|
||||||
@@ -34,12 +35,8 @@ let
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
in
|
|
||||||
let
|
|
||||||
directories = lib.filterAttrs (_name: type: type == "directory") (builtins.readDir root);
|
directories = lib.filterAttrs (_name: type: type == "directory") (builtins.readDir root);
|
||||||
names = lib.attrNames directories;
|
names = lib.attrNames directories;
|
||||||
in
|
in
|
||||||
lib.genAttrs names (
|
lib.genAttrs names (name: mkHost { inherit root name; })
|
||||||
name:
|
|
||||||
mkHost { inherit root name; }
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
{ hosts, lib, root }:
|
{
|
||||||
|
hosts,
|
||||||
|
lib,
|
||||||
|
root,
|
||||||
|
}:
|
||||||
let
|
let
|
||||||
checkType = lib.types.submodule {
|
checkType = lib.types.submodule {
|
||||||
options = {
|
options = {
|
||||||
@@ -19,7 +23,8 @@ let
|
|||||||
};
|
};
|
||||||
|
|
||||||
predicates = {
|
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 // {
|
registryLib = lib // {
|
||||||
@@ -57,15 +62,18 @@ let
|
|||||||
|
|
||||||
registryName = fileName: lib.removeSuffix ".nix" fileName;
|
registryName = fileName: lib.removeSuffix ".nix" fileName;
|
||||||
|
|
||||||
registryOption = registry: lib.mkOption {
|
registryOption =
|
||||||
type = lib.types.attrsOf (lib.types.attrsOf registry.type);
|
registry:
|
||||||
default = { };
|
lib.mkOption {
|
||||||
description = ''
|
type = lib.types.attrsOf (lib.types.attrsOf registry.type);
|
||||||
Lazily collected fleet-visible registry entries, nested by host and entry name.
|
default = { };
|
||||||
'';
|
description = ''
|
||||||
};
|
Lazily collected fleet-visible registry entries, nested by host and entry name.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
mkRegistry = path:
|
mkRegistry =
|
||||||
|
path:
|
||||||
let
|
let
|
||||||
evaluated = lib.evalModules {
|
evaluated = lib.evalModules {
|
||||||
specialArgs.lib = registryLib;
|
specialArgs.lib = registryLib;
|
||||||
@@ -79,15 +87,21 @@ let
|
|||||||
inherit (evaluated.config) type replicate checks;
|
inherit (evaluated.config) type replicate checks;
|
||||||
};
|
};
|
||||||
|
|
||||||
definitions = lib.mapAttrs' (
|
definitions =
|
||||||
name: type:
|
lib.mapAttrs'
|
||||||
let
|
(
|
||||||
path = root + "/${name}";
|
name: _type:
|
||||||
in
|
let
|
||||||
lib.nameValuePair (registryName name) (mkRegistry path)
|
path = root + "/${name}";
|
||||||
) (lib.filterAttrs (name: type: type == "regular" && lib.hasSuffix ".nix" name) (builtins.readDir root));
|
in
|
||||||
|
lib.nameValuePair (registryName name) (mkRegistry path)
|
||||||
|
)
|
||||||
|
(
|
||||||
|
lib.filterAttrs (name: type: type == "regular" && lib.hasSuffix ".nix" name) (builtins.readDir root)
|
||||||
|
);
|
||||||
|
|
||||||
flattenRegistryEntries = registryName: data:
|
flattenRegistryEntries =
|
||||||
|
registryName: data:
|
||||||
lib.concatLists (
|
lib.concatLists (
|
||||||
lib.mapAttrsToList (
|
lib.mapAttrsToList (
|
||||||
host: entries:
|
host: entries:
|
||||||
@@ -98,10 +112,12 @@ let
|
|||||||
) data
|
) data
|
||||||
);
|
);
|
||||||
|
|
||||||
rawDeclarations = registryName: hosts:
|
rawDeclarations =
|
||||||
|
registryName: hosts:
|
||||||
lib.mapAttrs (_hostName: host: host.config.registry.${registryName} or { }) hosts;
|
lib.mapAttrs (_hostName: host: host.config.registry.${registryName} or { }) hosts;
|
||||||
|
|
||||||
replicatedEntries = registryName: raw:
|
replicatedEntries =
|
||||||
|
registryName: raw:
|
||||||
let
|
let
|
||||||
entries = lib.concatLists (
|
entries = lib.concatLists (
|
||||||
lib.concatLists (
|
lib.concatLists (
|
||||||
@@ -126,18 +142,21 @@ let
|
|||||||
else
|
else
|
||||||
throw "conflicting replicated registry entry ${entry.path} does not match ${acc.${entry.entryName}.path}"
|
throw "conflicting replicated registry entry ${entry.path} does not match ${acc.${entry.entryName}.path}"
|
||||||
else
|
else
|
||||||
acc // {
|
acc
|
||||||
|
// {
|
||||||
${entry.entryName} = entry;
|
${entry.entryName} = entry;
|
||||||
}
|
}
|
||||||
) { } entries;
|
) { } entries;
|
||||||
|
|
||||||
replicatedData = registryName: hosts: raw:
|
replicatedData =
|
||||||
|
registryName: hosts: raw:
|
||||||
let
|
let
|
||||||
entries = lib.mapAttrs (_entryName: entry: entry.value) (replicatedEntries registryName raw);
|
entries = lib.mapAttrs (_entryName: entry: entry.value) (replicatedEntries registryName raw);
|
||||||
in
|
in
|
||||||
lib.mapAttrs (_hostName: _host: entries) hosts;
|
lib.mapAttrs (_hostName: _host: entries) hosts;
|
||||||
|
|
||||||
validationAssertions = data:
|
validationAssertions =
|
||||||
|
data:
|
||||||
lib.concatLists (
|
lib.concatLists (
|
||||||
lib.mapAttrsToList (
|
lib.mapAttrsToList (
|
||||||
registryName: registry:
|
registryName: registry:
|
||||||
@@ -151,7 +170,8 @@ let
|
|||||||
) definitions
|
) definitions
|
||||||
);
|
);
|
||||||
|
|
||||||
assertValid = data:
|
assertValid =
|
||||||
|
data:
|
||||||
let
|
let
|
||||||
assertions = validationAssertions data;
|
assertions = validationAssertions data;
|
||||||
failures = lib.filter (assertion: !assertion.assertion) assertions;
|
failures = lib.filter (assertion: !assertion.assertion) assertions;
|
||||||
@@ -161,9 +181,12 @@ let
|
|||||||
);
|
);
|
||||||
data;
|
data;
|
||||||
|
|
||||||
join = registry: host: entry:
|
join =
|
||||||
|
registry: host: entry:
|
||||||
lib.filterAttrs (_name: value: value != null) (
|
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 =
|
collectData =
|
||||||
@@ -180,7 +203,8 @@ let
|
|||||||
in
|
in
|
||||||
assertValid data;
|
assertValid data;
|
||||||
|
|
||||||
withOperations = registry:
|
withOperations =
|
||||||
|
registry:
|
||||||
registry
|
registry
|
||||||
// {
|
// {
|
||||||
join = host: entry: join registry host entry;
|
join = host: entry: join registry host entry;
|
||||||
@@ -190,8 +214,10 @@ in
|
|||||||
types = lib.mapAttrs (_name: definition: definition.type) definitions;
|
types = lib.mapAttrs (_name: definition: definition.type) definitions;
|
||||||
|
|
||||||
module = {
|
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;
|
hash = builtins.hashString "sha256" name;
|
||||||
octet = i: builtins.substring (i * 2) 2 hash;
|
octet = i: builtins.substring (i * 2) 2 hash;
|
||||||
in
|
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