refactor(nix): order let bindings
This commit was merged in pull request #103.
This commit is contained in:
@@ -8,8 +8,8 @@
|
||||
# Firefox as the desktop browser: stock mainline, hardened and de-monetized by policy.
|
||||
let
|
||||
cfg = config.modules.desktop.apps.firefox; # NOLINT(let_order)
|
||||
user = config.user.name;
|
||||
firefoxAddons = inputs.firefox-addons.packages.${pkgs.stdenv.hostPlatform.system};
|
||||
user = config.user.name;
|
||||
in
|
||||
{
|
||||
options.modules.desktop.apps.firefox = {
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
# The Hyprland compositor.
|
||||
let
|
||||
cfg = config.modules.desktop.session.hyprland; # NOLINT(let_order)
|
||||
user = config.user.name;
|
||||
cursor = config.stylix.cursor;
|
||||
|
||||
# Numbered-workspace switch and move for 1..9, the operator's i3 muscle memory.
|
||||
@@ -16,6 +15,8 @@ let
|
||||
"$mod SHIFT, ${toString n}, movetoworkspace, ${toString n}"
|
||||
]) (lib.range 1 9);
|
||||
|
||||
user = config.user.name;
|
||||
|
||||
# Flip the tiling strategy between the two built-in layouts, since neither a
|
||||
# dispatcher nor a keyword toggles it on its own.
|
||||
toggleLayout = pkgs.writeShellScript "hypr-toggle-layout" ''
|
||||
|
||||
@@ -7,14 +7,15 @@
|
||||
# hypridle: idle-triggered locking and display power management.
|
||||
let
|
||||
cfg = config.modules.desktop.session.hyprland.hypridle; # NOLINT(let_order)
|
||||
|
||||
# The guard drops the call when a locker is already up, so no idle trigger
|
||||
# stacks a second hyprlock over the first.
|
||||
lockCmd = "${pkgs.procps}/bin/pidof hyprlock || ${hyprlock}";
|
||||
user = config.user.name;
|
||||
|
||||
hyprctl = "${config.programs.hyprland.package}/bin/hyprctl";
|
||||
hyprlock = "${config.home-manager.users.${user}.programs.hyprlock.package}/bin/hyprlock";
|
||||
|
||||
# The guard drops the call when a locker is already up, so no idle trigger
|
||||
# stacks a second hyprlock over the first.
|
||||
lockCmd = "${pkgs.procps}/bin/pidof hyprlock || ${hyprlock}";
|
||||
in
|
||||
{
|
||||
options.modules.desktop.session.hyprland.hypridle = {
|
||||
|
||||
@@ -8,11 +8,12 @@
|
||||
let
|
||||
cfg = config.modules.desktop.session.waybar; # NOLINT(let_order)
|
||||
vpnClient = config.modules.network.vpn-client;
|
||||
user = config.user.name;
|
||||
|
||||
# A Nerd Font Private-Use-Area codepoint as a literal character, decoded
|
||||
# through JSON so the glyph survives as bytes rather than an editor paste.
|
||||
g = code: builtins.fromJSON ''"\u${code}"'';
|
||||
user = config.user.name;
|
||||
|
||||
sleepOffIcon = builtins.fromJSON ''"\udb81\udcb3"'';
|
||||
|
||||
# Renders and toggles mako's do-not-disturb mode.
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
# Nord theming for the graphical layer, driven from one base16 scheme by Stylix.
|
||||
let
|
||||
cfg = config.modules.desktop.utilities.theming; # NOLINT(let_order)
|
||||
user = config.user.name;
|
||||
|
||||
# A single static Nord wallpaper, drawn as a vertical gradient across the
|
||||
# Polar Night shades so it needs no committed binary and no network fetch.
|
||||
@@ -16,6 +15,7 @@ let
|
||||
-size 2560x1440 gradient:'#2E3440'-'#3B4252' \
|
||||
"$out"
|
||||
'';
|
||||
user = config.user.name;
|
||||
in
|
||||
{
|
||||
options.modules.desktop.utilities.theming.enable =
|
||||
|
||||
@@ -7,32 +7,6 @@
|
||||
# SSH on this machine, in both directions.
|
||||
let
|
||||
cfg = config.modules.network.ssh; # NOLINT(let_order)
|
||||
user = config.user.name;
|
||||
|
||||
inherit (lib)
|
||||
concatLists
|
||||
concatStringsSep
|
||||
elem
|
||||
filter
|
||||
genAttrs
|
||||
hasAttr
|
||||
imap0
|
||||
listToAttrs
|
||||
mapAttrs
|
||||
mapAttrsToList
|
||||
mkIf
|
||||
mkMerge
|
||||
mkOption
|
||||
nameValuePair
|
||||
optional
|
||||
optionalAttrs
|
||||
types
|
||||
unique
|
||||
;
|
||||
|
||||
hostKeySecret = type: "ssh-host-${type}-key";
|
||||
userKeySecret = "ssh-user-ed25519-key";
|
||||
|
||||
targetType = types.submodule (
|
||||
{ name, ... }:
|
||||
{
|
||||
@@ -90,54 +64,18 @@ let
|
||||
}
|
||||
);
|
||||
|
||||
keyWithoutComment = key: concatStringsSep " " (lib.take 2 (lib.splitString " " key));
|
||||
|
||||
targetNamesIn = names: filter (name: hasAttr name cfg.targets) names;
|
||||
|
||||
workstationNames = targetNamesIn cfg.hosts.workstations;
|
||||
serverNames = targetNamesIn cfg.hosts.servers;
|
||||
|
||||
clientKeysFor = names: filter (key: key != null) (map (name: cfg.targets.${name}.clientKey) names);
|
||||
|
||||
currentHost = config.networking.hostName;
|
||||
isServer = elem currentHost cfg.hosts.servers;
|
||||
isWorkstation = elem currentHost cfg.hosts.workstations;
|
||||
|
||||
defaultAuthorizedKeys = lib.flatten (
|
||||
clientKeysFor workstationNames ++ optional isServer (clientKeysFor serverNames)
|
||||
);
|
||||
|
||||
outboundTargetNames =
|
||||
let
|
||||
groupTargets =
|
||||
if isServer then
|
||||
[ "gitea" ] ++ cfg.hosts.servers
|
||||
else if isWorkstation then
|
||||
[ "gitea" ] ++ cfg.hosts.servers ++ cfg.hosts.workstations
|
||||
else
|
||||
[ "gitea" ];
|
||||
in
|
||||
filter (name: name != currentHost) (targetNamesIn groupTargets);
|
||||
clientKeysFor = names: filter (key: key != null) (map (name: cfg.targets.${name}.clientKey) names);
|
||||
|
||||
sshSettingsFor =
|
||||
name:
|
||||
let
|
||||
target = cfg.targets.${name};
|
||||
in
|
||||
{
|
||||
header = "Host ${concatStringsSep " " target.aliases}";
|
||||
HostName = target.hostName;
|
||||
User = target.user;
|
||||
}
|
||||
// optionalAttrs (target.port != 22) { Port = target.port; };
|
||||
workstationNames = targetNamesIn cfg.hosts.workstations;
|
||||
targetNamesIn = names: filter (name: hasAttr name cfg.targets) names;
|
||||
|
||||
knownHostNamesFor =
|
||||
target:
|
||||
let
|
||||
names = unique (target.aliases ++ [ target.hostName ]);
|
||||
withPort = name: if target.port == 22 then name else "[${name}]:${toString target.port}";
|
||||
in
|
||||
map withPort names;
|
||||
isServer = elem currentHost cfg.hosts.servers;
|
||||
currentHost = config.networking.hostName;
|
||||
serverNames = targetNamesIn cfg.hosts.servers;
|
||||
|
||||
knownHosts = listToAttrs (
|
||||
concatLists (
|
||||
@@ -153,6 +91,68 @@ let
|
||||
) cfg.targets
|
||||
)
|
||||
);
|
||||
knownHostNamesFor =
|
||||
target:
|
||||
let
|
||||
withPort = name: if target.port == 22 then name else "[${name}]:${toString target.port}";
|
||||
names = unique (target.aliases ++ [ target.hostName ]);
|
||||
in
|
||||
map withPort names;
|
||||
|
||||
keyWithoutComment = key: concatStringsSep " " (lib.take 2 (lib.splitString " " key));
|
||||
|
||||
sshSettingsFor =
|
||||
name:
|
||||
let
|
||||
target = cfg.targets.${name};
|
||||
in
|
||||
{
|
||||
header = "Host ${concatStringsSep " " target.aliases}";
|
||||
HostName = target.hostName;
|
||||
User = target.user;
|
||||
}
|
||||
// optionalAttrs (target.port != 22) { Port = target.port; };
|
||||
|
||||
outboundTargetNames =
|
||||
let
|
||||
groupTargets =
|
||||
if isServer then
|
||||
[ "gitea" ] ++ cfg.hosts.servers
|
||||
else if isWorkstation then
|
||||
[ "gitea" ] ++ cfg.hosts.servers ++ cfg.hosts.workstations
|
||||
else
|
||||
[ "gitea" ];
|
||||
in
|
||||
filter (name: name != currentHost) (targetNamesIn groupTargets);
|
||||
|
||||
isWorkstation = elem currentHost cfg.hosts.workstations;
|
||||
|
||||
hostKeySecret = type: "ssh-host-${type}-key";
|
||||
user = config.user.name;
|
||||
|
||||
inherit (lib)
|
||||
concatLists
|
||||
concatStringsSep
|
||||
elem
|
||||
filter
|
||||
genAttrs
|
||||
hasAttr
|
||||
imap0
|
||||
listToAttrs
|
||||
mapAttrs
|
||||
mapAttrsToList
|
||||
mkIf
|
||||
mkMerge
|
||||
mkOption
|
||||
nameValuePair
|
||||
optional
|
||||
optionalAttrs
|
||||
types
|
||||
unique
|
||||
;
|
||||
|
||||
userKeySecret = "ssh-user-ed25519-key";
|
||||
|
||||
in
|
||||
{
|
||||
options.modules.network.ssh = {
|
||||
|
||||
@@ -38,6 +38,31 @@ let
|
||||
};
|
||||
};
|
||||
|
||||
configScript = pkgs.writeShellScript "copyparty-config" ''
|
||||
set -eu
|
||||
|
||||
umask 077
|
||||
password="$(${pkgs.coreutils}/bin/tr -d '\n' < "$CREDENTIALS_DIRECTORY/password")"
|
||||
|
||||
cat > /run/copyparty/copyparty.conf <<EOF
|
||||
[global]
|
||||
p: ${toString cfg.port}
|
||||
usernames
|
||||
http-only
|
||||
no-crt
|
||||
no-thumb
|
||||
no-snap
|
||||
no-rescan
|
||||
ses-db: ${cfg.stateDir}/sessions.db
|
||||
chpw-db: ${cfg.stateDir}/chpw.json
|
||||
shr-db: ${cfg.stateDir}/shares.db
|
||||
${renderedReverseProxy}
|
||||
[accounts]
|
||||
${cfg.accountName}: $password
|
||||
|
||||
${renderedVolumes}
|
||||
EOF
|
||||
'';
|
||||
renderAccess = permission: accounts: " ${permission}: ${lib.concatStringsSep ", " accounts}";
|
||||
|
||||
hasFlag =
|
||||
@@ -72,31 +97,6 @@ let
|
||||
|
||||
renderedVolumes = lib.concatStringsSep "\n" (lib.mapAttrsToList renderVolume cfg.volumes);
|
||||
|
||||
configScript = pkgs.writeShellScript "copyparty-config" ''
|
||||
set -eu
|
||||
|
||||
umask 077
|
||||
password="$(${pkgs.coreutils}/bin/tr -d '\n' < "$CREDENTIALS_DIRECTORY/password")"
|
||||
|
||||
cat > /run/copyparty/copyparty.conf <<EOF
|
||||
[global]
|
||||
p: ${toString cfg.port}
|
||||
usernames
|
||||
http-only
|
||||
no-crt
|
||||
no-thumb
|
||||
no-snap
|
||||
no-rescan
|
||||
ses-db: ${cfg.stateDir}/sessions.db
|
||||
chpw-db: ${cfg.stateDir}/chpw.json
|
||||
shr-db: ${cfg.stateDir}/shares.db
|
||||
${renderedReverseProxy}
|
||||
[accounts]
|
||||
${cfg.accountName}: $password
|
||||
|
||||
${renderedVolumes}
|
||||
EOF
|
||||
'';
|
||||
in
|
||||
{
|
||||
options.modules.services.copyparty = {
|
||||
|
||||
@@ -7,9 +7,42 @@
|
||||
let
|
||||
cfg = config.modules.services.homepage; # NOLINT(let_order)
|
||||
|
||||
mkRegistryPath =
|
||||
registryName: host: entry:
|
||||
"registry.${registryName}.${host}.${entry}";
|
||||
derivedAllowedHosts = lib.unique (
|
||||
lib.optional (selfRoute != null) selfRoute.domain
|
||||
++ lib.optionals (selfAddress != null) [
|
||||
selfAddress
|
||||
"${selfAddress}:${toString cfg.listenPort}"
|
||||
]
|
||||
);
|
||||
selfRoute = selfEntry.route or null;
|
||||
|
||||
selfEntry = registry.join cfg.hostName cfg.entryName;
|
||||
selfAddress = selfEntry.address or null;
|
||||
homepageServices = map mkTab (lib.filter (tab: lib.hasAttr tab entriesByTab) orderedTabs);
|
||||
|
||||
mkTab =
|
||||
tab:
|
||||
let
|
||||
sections = entriesByTab.${tab};
|
||||
in
|
||||
{
|
||||
${tab} = map (section: { ${section} = sections.${section}; }) (orderedSections tab sections);
|
||||
};
|
||||
|
||||
entriesByTab = lib.foldl' insertEntry { } sortedEntries;
|
||||
|
||||
insertEntry =
|
||||
acc: item:
|
||||
acc
|
||||
// {
|
||||
${item.homepage.tab} = (acc.${item.homepage.tab} or { }) // {
|
||||
${item.homepage.section} = (acc.${item.homepage.tab}.${item.homepage.section} or [ ]) ++ [
|
||||
{ ${item.homepage.name} = mkServiceAttrs item; }
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
sortedEntries = lib.sort (left: right: left.homepage.name < right.homepage.name) homepageEntries;
|
||||
|
||||
homepageEntries = lib.concatLists (
|
||||
lib.mapAttrsToList (
|
||||
@@ -21,6 +54,18 @@ let
|
||||
) registry.homepage
|
||||
);
|
||||
|
||||
orderedTabs = tabOrder ++ lib.filter (tab: !lib.elem tab tabOrder) (lib.attrNames entriesByTab);
|
||||
|
||||
tabOrder = [
|
||||
"Apps"
|
||||
"Download"
|
||||
"System"
|
||||
];
|
||||
|
||||
mkRegistryPath =
|
||||
registryName: host: entry:
|
||||
"registry.${registryName}.${host}.${entry}";
|
||||
|
||||
mkHref =
|
||||
item:
|
||||
if item.homepage.href != null then
|
||||
@@ -42,29 +87,6 @@ let
|
||||
inherit (item.homepage) description icon;
|
||||
};
|
||||
|
||||
sortedEntries = lib.sort (left: right: left.homepage.name < right.homepage.name) homepageEntries;
|
||||
|
||||
insertEntry =
|
||||
acc: item:
|
||||
acc
|
||||
// {
|
||||
${item.homepage.tab} = (acc.${item.homepage.tab} or { }) // {
|
||||
${item.homepage.section} = (acc.${item.homepage.tab}.${item.homepage.section} or [ ]) ++ [
|
||||
{ ${item.homepage.name} = mkServiceAttrs item; }
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
entriesByTab = lib.foldl' insertEntry { } sortedEntries;
|
||||
|
||||
tabOrder = [
|
||||
"Apps"
|
||||
"Download"
|
||||
"System"
|
||||
];
|
||||
|
||||
orderedTabs = tabOrder ++ lib.filter (tab: !lib.elem tab tabOrder) (lib.attrNames entriesByTab);
|
||||
|
||||
sectionOrderByTab = {
|
||||
Apps = [
|
||||
"Media"
|
||||
@@ -91,28 +113,6 @@ let
|
||||
in
|
||||
sectionOrder ++ lib.filter (section: !lib.elem section sectionOrder) (lib.attrNames sections);
|
||||
|
||||
mkTab =
|
||||
tab:
|
||||
let
|
||||
sections = entriesByTab.${tab};
|
||||
in
|
||||
{
|
||||
${tab} = map (section: { ${section} = sections.${section}; }) (orderedSections tab sections);
|
||||
};
|
||||
|
||||
homepageServices = map mkTab (lib.filter (tab: lib.hasAttr tab entriesByTab) orderedTabs);
|
||||
|
||||
selfEntry = registry.join cfg.hostName cfg.entryName;
|
||||
selfAddress = selfEntry.address or null;
|
||||
selfRoute = selfEntry.route or null;
|
||||
|
||||
derivedAllowedHosts = lib.unique (
|
||||
lib.optional (selfRoute != null) selfRoute.domain
|
||||
++ lib.optionals (selfAddress != null) [
|
||||
selfAddress
|
||||
"${selfAddress}:${toString cfg.listenPort}"
|
||||
]
|
||||
);
|
||||
in
|
||||
{
|
||||
options.modules.services.homepage = {
|
||||
|
||||
@@ -7,61 +7,43 @@
|
||||
let
|
||||
cfg = config.modules.services.reverse-proxy; # NOLINT(let_order)
|
||||
|
||||
mkRegistryPath =
|
||||
registryName: host: entry:
|
||||
"registry.${registryName}.${host}.${entry}";
|
||||
generatedUdpStreams = lib.concatLists (
|
||||
lib.mapAttrsToList (
|
||||
host: routes:
|
||||
lib.concatLists (
|
||||
lib.mapAttrsToList (entry: route: map (mkUdpStream host entry) route.udp.ports) routes
|
||||
)
|
||||
) registry.route
|
||||
);
|
||||
|
||||
mkBackend = address: port: "http://${address}:${toString port}";
|
||||
|
||||
mkVirtualHost =
|
||||
host: entry: mode:
|
||||
mkUdpStream =
|
||||
host: entry: port:
|
||||
let
|
||||
compositeEntry = registry.join 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;
|
||||
compositeEntry = registry.join host entry;
|
||||
in
|
||||
{
|
||||
inherit host entry;
|
||||
registryName = "route";
|
||||
name = route.domain;
|
||||
value = {
|
||||
forceSSL = !isHttp;
|
||||
enableACME = !isHttp;
|
||||
locations."/".proxyPass = mkBackend address port;
|
||||
};
|
||||
inherit
|
||||
host
|
||||
entry
|
||||
port
|
||||
address
|
||||
;
|
||||
};
|
||||
|
||||
generatedHttpsVirtualHostList = lib.concatLists (
|
||||
lib.mapAttrsToList (
|
||||
host: routes:
|
||||
lib.mapAttrsToList (entry: _route: mkVirtualHost host entry "https") (
|
||||
lib.filterAttrs (_entry: route: route.port != null) routes
|
||||
)
|
||||
) registry.route
|
||||
);
|
||||
|
||||
generatedHttpVirtualHostList = lib.concatLists (
|
||||
lib.mapAttrsToList (
|
||||
host: routes:
|
||||
lib.mapAttrsToList (entry: _route: mkVirtualHost host entry "http") (
|
||||
lib.filterAttrs (_entry: route: route.http.port != null) routes
|
||||
)
|
||||
) registry.route
|
||||
);
|
||||
|
||||
generatedVirtualHostList = generatedHttpsVirtualHostList ++ generatedHttpVirtualHostList;
|
||||
|
||||
virtualHostsByDomain = lib.foldl' (
|
||||
acc: virtualHost:
|
||||
acc
|
||||
// {
|
||||
${virtualHost.name} = (acc.${virtualHost.name} or [ ]) ++ [ virtualHost ];
|
||||
generatedStreamConfig = lib.concatMapStringsSep "\n" (stream: ''
|
||||
server {
|
||||
listen ${toString stream.port} udp;
|
||||
proxy_pass ${stream.address}:${toString stream.port};
|
||||
}
|
||||
) { } generatedVirtualHostList;
|
||||
'') generatedUdpStreams;
|
||||
generatedVirtualHosts =
|
||||
if duplicateDomainMessages != [ ] then
|
||||
throw (builtins.head duplicateDomainMessages)
|
||||
else
|
||||
lib.listToAttrs generatedVirtualHostList;
|
||||
|
||||
duplicateDomainMessages = lib.concatLists (
|
||||
lib.mapAttrsToList (
|
||||
@@ -79,44 +61,62 @@ let
|
||||
) virtualHostsByDomain
|
||||
);
|
||||
|
||||
generatedVirtualHosts =
|
||||
if duplicateDomainMessages != [ ] then
|
||||
throw (builtins.head duplicateDomainMessages)
|
||||
else
|
||||
lib.listToAttrs generatedVirtualHostList;
|
||||
virtualHostsByDomain = lib.foldl' (
|
||||
acc: virtualHost:
|
||||
acc
|
||||
// {
|
||||
${virtualHost.name} = (acc.${virtualHost.name} or [ ]) ++ [ virtualHost ];
|
||||
}
|
||||
) { } generatedVirtualHostList;
|
||||
|
||||
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}");
|
||||
in
|
||||
{
|
||||
inherit
|
||||
host
|
||||
entry
|
||||
port
|
||||
address
|
||||
;
|
||||
};
|
||||
generatedVirtualHostList = generatedHttpsVirtualHostList ++ generatedHttpVirtualHostList;
|
||||
|
||||
generatedUdpStreams = lib.concatLists (
|
||||
generatedHttpsVirtualHostList = lib.concatLists (
|
||||
lib.mapAttrsToList (
|
||||
host: routes:
|
||||
lib.concatLists (
|
||||
lib.mapAttrsToList (entry: route: map (mkUdpStream host entry) route.udp.ports) routes
|
||||
lib.mapAttrsToList (entry: _route: mkVirtualHost host entry "https") (
|
||||
lib.filterAttrs (_entry: route: route.port != null) routes
|
||||
)
|
||||
) registry.route
|
||||
);
|
||||
|
||||
generatedStreamConfig = lib.concatMapStringsSep "\n" (stream: ''
|
||||
server {
|
||||
listen ${toString stream.port} udp;
|
||||
proxy_pass ${stream.address}:${toString stream.port};
|
||||
}
|
||||
'') generatedUdpStreams;
|
||||
mkVirtualHost =
|
||||
host: entry: mode:
|
||||
let
|
||||
isHttp = mode == "http";
|
||||
address =
|
||||
compositeEntry.address
|
||||
or (throw "no matching entry in registry.address for ${mkRegistryPath "route" host entry}");
|
||||
compositeEntry = registry.join host entry;
|
||||
inherit (compositeEntry) route;
|
||||
port = if isHttp then route.http.port else route.port;
|
||||
in
|
||||
{
|
||||
inherit host entry;
|
||||
registryName = "route";
|
||||
name = route.domain;
|
||||
value = {
|
||||
forceSSL = !isHttp;
|
||||
enableACME = !isHttp;
|
||||
locations."/".proxyPass = mkBackend address port;
|
||||
};
|
||||
};
|
||||
|
||||
mkBackend = address: port: "http://${address}:${toString port}";
|
||||
|
||||
generatedHttpVirtualHostList = lib.concatLists (
|
||||
lib.mapAttrsToList (
|
||||
host: routes:
|
||||
lib.mapAttrsToList (entry: _route: mkVirtualHost host entry "http") (
|
||||
lib.filterAttrs (_entry: route: route.http.port != null) routes
|
||||
)
|
||||
) registry.route
|
||||
);
|
||||
|
||||
mkRegistryPath =
|
||||
registryName: host: entry:
|
||||
"registry.${registryName}.${host}.${entry}";
|
||||
|
||||
in
|
||||
{
|
||||
options.modules.services.reverse-proxy = {
|
||||
|
||||
@@ -80,10 +80,10 @@
|
||||
|
||||
(lib.mkIf config.modules.services.steamcmd.enable (
|
||||
let
|
||||
service = config.modules.services.steamcmd;
|
||||
user = "steamcmd";
|
||||
group = "storage";
|
||||
|
||||
service = config.modules.services.steamcmd;
|
||||
user = "steamcmd";
|
||||
prepareScript = pkgs.writeShellScript "steamcmd-${service.serviceName}-prepare" ''
|
||||
set -eu
|
||||
|
||||
|
||||
@@ -7,13 +7,13 @@
|
||||
# fish for the primary user, configured through home-manager.
|
||||
let
|
||||
cfg = config.modules.shell.fish; # NOLINT(let_order)
|
||||
user = config.user.name;
|
||||
shortcuts = lib.attrByPath [ config.networking.hostName ] { } config.registry.shell-shortcut;
|
||||
envVars = lib.attrByPath [ config.networking.hostName ] { } config.registry.env-var;
|
||||
commandsOf = shortcuts: lib.mapAttrs (_name: shortcut: shortcut.command) shortcuts;
|
||||
shortcuts = lib.attrByPath [ config.networking.hostName ] { } config.registry.shell-shortcut;
|
||||
exportEnvVar = name: value: ''
|
||||
set -gx ${name} ${lib.escapeShellArg value}
|
||||
'';
|
||||
envVars = lib.attrByPath [ config.networking.hostName ] { } config.registry.env-var;
|
||||
user = config.user.name;
|
||||
in
|
||||
{
|
||||
options.modules.shell.fish = {
|
||||
|
||||
@@ -9,12 +9,12 @@
|
||||
# The login credential is left unmanaged, so it survives rebuilds.
|
||||
let
|
||||
cfg = config.modules.shell.pi; # NOLINT(let_order)
|
||||
user = config.user.name;
|
||||
piDir = "${config.users.users.${user}.home}/.pi/agent";
|
||||
vendoredPi = pkgs.pi-coding-agent.overrideAttrs {
|
||||
src = ../../../../../third_party/pi;
|
||||
patches = [ ];
|
||||
};
|
||||
user = config.user.name;
|
||||
piDir = "${config.users.users.${user}.home}/.pi/agent";
|
||||
in
|
||||
{
|
||||
options.modules.shell.pi = {
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
# Rust tools for the primary user's shell environment.
|
||||
let
|
||||
cfg = config.modules.shell.rust; # NOLINT(let_order)
|
||||
user = config.user.name;
|
||||
toolchain = pkgs.symlinkJoin {
|
||||
name = "rust-toolchain";
|
||||
paths = with pkgs; [
|
||||
@@ -18,6 +17,7 @@ let
|
||||
rustfmt
|
||||
];
|
||||
};
|
||||
user = config.user.name;
|
||||
in
|
||||
{
|
||||
options.modules.shell.rust.enable =
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib)
|
||||
filterAttrs
|
||||
groupBy
|
||||
mapAttrs
|
||||
unique
|
||||
;
|
||||
duplicateUids =
|
||||
entries:
|
||||
filterAttrs (_uid: serviceNames: builtins.length serviceNames > 1) (serviceNamesByUid entries);
|
||||
|
||||
serviceNamesByUid =
|
||||
entries:
|
||||
@@ -13,10 +10,6 @@ let
|
||||
groupBy (entry: toString entry.value) entries
|
||||
);
|
||||
|
||||
duplicateUids =
|
||||
entries:
|
||||
filterAttrs (_uid: serviceNames: builtins.length serviceNames > 1) (serviceNamesByUid entries);
|
||||
|
||||
in
|
||||
{
|
||||
# Next stable UID: 20005
|
||||
|
||||
Reference in New Issue
Block a user