Reformat all Nix files

This commit is contained in:
Geoffrey Frogeye 2024-12-15 00:29:51 +01:00
parent 9e0c1102a9
commit 355b63cf73
Signed by: geoffrey
GPG key ID: C72403E7F82E6AD8
81 changed files with 2293 additions and 1153 deletions

View file

@ -1,4 +1,9 @@
{ pkgs, lib, config, ... }:
{
pkgs,
lib,
config,
...
}:
{
boot.loader = {
grub = {
@ -10,4 +15,3 @@
};
}

View file

@ -6,10 +6,12 @@
eap=TTLS
identity="37C3"
password="37C3"
ca_cert="${builtins.fetchurl {
url = "https://letsencrypt.org/certs/isrgrootx1.pem";
sha256 = "sha256:1la36n2f31j9s03v847ig6ny9lr875q3g7smnq33dcsmf2i5gd92";
}}"
ca_cert="${
builtins.fetchurl {
url = "https://letsencrypt.org/certs/isrgrootx1.pem";
sha256 = "sha256:1la36n2f31j9s03v847ig6ny9lr875q3g7smnq33dcsmf2i5gd92";
}
}"
altsubject_match="DNS:radius.c3noc.net"
phase2="auth=PAP"
'';

View file

@ -1,4 +1,9 @@
{ pkgs, lib, config, ... }:
{
pkgs,
lib,
config,
...
}:
{
networking = {
hostName = config.frogeye.name;
@ -16,13 +21,17 @@
# Enable passwordless sudo
# TODO execWheelOnly? sudo-rs?
security.sudo.extraRules = [{
groups = [ "wheel" ];
commands = [{
command = "ALL";
options = [ "NOPASSWD" ];
}];
}];
security.sudo.extraRules = [
{
groups = [ "wheel" ];
commands = [
{
command = "ALL";
options = [ "NOPASSWD" ];
}
];
}
];
# UPST disko --root-mountpoint doesn't work when using flake, workaround:
disko.rootMountPoint = "/mnt/nixos";
@ -44,7 +53,10 @@
nix = {
package = pkgs.lix;
settings = {
experimental-features = [ "nix-command" "flakes" ];
experimental-features = [
"nix-command"
"flakes"
];
warn-dirty = false;
};
};

View file

@ -1,5 +1,11 @@
# Need nvidia proprietary drivers to work
{ pkgs, nixpkgs, config, lib, ... }:
{
pkgs,
nixpkgs,
config,
lib,
...
}:
{
config = lib.mkIf config.frogeye.cuda {
nix.settings = {
@ -11,7 +17,8 @@
];
};
nixpkgs.overlays = [
(self: super:
(
self: super:
let
pkgs_uf = import nixpkgs {
inherit (super) system;
@ -19,11 +26,14 @@
};
in
{
ctranslate2 = (pkgs_uf.ctranslate2.override {
withCUDA = true;
withCuDNN = true;
});
})
ctranslate2 = (
pkgs_uf.ctranslate2.override {
withCUDA = true;
withCuDNN = true;
}
);
}
)
];
};
}

View file

@ -1,12 +1,19 @@
{ pkgs, lib, config, ... }:
{
pkgs,
lib,
config,
...
}:
let
setupScript = "${pkgs.writeShellApplication {
name = "greeter-setup-script";
runtimeInputs = [ pkgs.autorandr ];
text = ''
autorandr --change
'';
}}/bin/greeter-setup-script";
setupScript = "${
pkgs.writeShellApplication {
name = "greeter-setup-script";
runtimeInputs = [ pkgs.autorandr ];
text = ''
autorandr --change
'';
}
}/bin/greeter-setup-script";
in
{
config = {

View file

@ -1,4 +1,9 @@
{ pkgs, lib, config, ... }:
{
pkgs,
lib,
config,
...
}:
{
config = lib.mkIf config.frogeye.desktop.xorg {
boot.kernelModules = [ "i2c-dev" ]; # Allows using ddcutil
@ -19,7 +24,7 @@
# https://wiki.archlinux.org/title/PipeWire#Noticeable_audio_delay_or_audible_pop/crack_when_starting_playback
preventGetTogetherDuoFromShuttingDown."monitor.bluez.rules" = [
{
matches = [{ "node.name" = "~bluez_output.41_42_D2_B5_13_72.*"; }];
matches = [ { "node.name" = "~bluez_output.41_42_D2_B5_13_72.*"; } ];
actions.update-props = {
"session.suspend-timeout-seconds" = 0;
"dither.method" = "wannamaker3";
@ -39,23 +44,25 @@
extraLayouts.qwerty-fr = {
description = "QWERTY-fr";
languages = [ "fr" ];
symbolsFile = "${pkgs.stdenv.mkDerivation {
name = "qwerty-fr-keypad";
src = pkgs.fetchFromGitHub {
owner = "qwerty-fr";
repo = "qwerty-fr";
rev = "3a4d13089e8ef016aa20baf6b2bf3ea53de674b8";
sha256 = "sha256-wn5n6jJVDrQWJze8xYF2nEY8a7mHI3hVO4xsT4LMo9c=";
};
patches = [ ./qwerty-fr-keypad.diff ];
# TODO This doesn't seem to be applied... it's the whole point of the derivation :(
installPhase = ''
runHook preInstall
mkdir -p $out/linux
cp $src/linux/us_qwerty-fr $out/linux
runHook postInstall
'';
}}/linux/us_qwerty-fr";
symbolsFile = "${
pkgs.stdenv.mkDerivation {
name = "qwerty-fr-keypad";
src = pkgs.fetchFromGitHub {
owner = "qwerty-fr";
repo = "qwerty-fr";
rev = "3a4d13089e8ef016aa20baf6b2bf3ea53de674b8";
sha256 = "sha256-wn5n6jJVDrQWJze8xYF2nEY8a7mHI3hVO4xsT4LMo9c=";
};
patches = [ ./qwerty-fr-keypad.diff ];
# TODO This doesn't seem to be applied... it's the whole point of the derivation :(
installPhase = ''
runHook preInstall
mkdir -p $out/linux
cp $src/linux/us_qwerty-fr $out/linux
runHook postInstall
'';
}
}/linux/us_qwerty-fr";
};
layout = "qwerty-fr";
};

View file

@ -1,4 +1,9 @@
{ pkgs, lib, config, ... }:
{
pkgs,
lib,
config,
...
}:
{
config = lib.mkMerge [
(lib.mkIf config.frogeye.dev.docker {

View file

@ -1,29 +1,33 @@
{ pkgs, lib, config, ... }:
{
config = lib.mkIf config.frogeye.gaming
{
programs.steam.enable = true;
hardware.graphics.enable32Bit = true; # Needed by Steam
services = {
udev.packages = [ pkgs.python3Packages.ds4drv ];
xserver.config = ''
# Disable mouse support for joypad
Section "InputClass"
Identifier "joystick catchall"
MatchIsJoystick "on"
MatchDevicePath "/dev/input/event*"
Driver "joystick"
Option "StartKeysEnabled" "False"
Option "StartMouseEnabled" "False"
EndSection
# Same thing for DualShock 4 touchpad
Section "InputClass"
Identifier "ds4-touchpad"
Driver "libinput"
MatchProduct "Wireless Controller Touchpad"
Option "Ignore" "True"
EndSection
'';
};
pkgs,
lib,
config,
...
}:
{
config = lib.mkIf config.frogeye.gaming {
programs.steam.enable = true;
hardware.graphics.enable32Bit = true; # Needed by Steam
services = {
udev.packages = [ pkgs.python3Packages.ds4drv ];
xserver.config = ''
# Disable mouse support for joypad
Section "InputClass"
Identifier "joystick catchall"
MatchIsJoystick "on"
MatchDevicePath "/dev/input/event*"
Driver "joystick"
Option "StartKeysEnabled" "False"
Option "StartMouseEnabled" "False"
EndSection
# Same thing for DualShock 4 touchpad
Section "InputClass"
Identifier "ds4-touchpad"
Driver "libinput"
MatchProduct "Wireless Controller Touchpad"
Option "Ignore" "True"
EndSection
'';
};
};
}

View file

@ -1,11 +1,20 @@
{ pkgs, lib, config, home-manager, ... }:
{
pkgs,
lib,
config,
home-manager,
...
}:
{
config = {
users.users.root.initialHashedPassword = "$y$j9T$e64bjL7iyVlniEKwKbM9g0$cCn74za0r6L9QMO20Fdxz3/SX0yvhz3Xd6.2BhtbRL1"; # Not a real password
users.users.geoffrey = {
isNormalUser = true;
extraGroups = [ "adbusers" "wheel" ];
extraGroups = [
"adbusers"
"wheel"
];
shell = pkgs.zsh;
initialHashedPassword = "$y$j9T$e64bjL7iyVlniEKwKbM9g0$cCn74za0r6L9QMO20Fdxz3/SX0yvhz3Xd6.2BhtbRL1"; # Not a real password
@ -21,11 +30,13 @@
nix.settings.trusted-users = [ "geoffrey" ];
home-manager = {
users.geoffrey = { pkgs, ... }: {
frogeye = lib.mkDefault config.frogeye;
# Propagating options that way doesn't seem to conserve priority info,
# this is not great. Hopefully mkDefault resolve conflicts.
};
users.geoffrey =
{ pkgs, ... }:
{
frogeye = lib.mkDefault config.frogeye;
# Propagating options that way doesn't seem to conserve priority info,
# this is not great. Hopefully mkDefault resolve conflicts.
};
# Makes VMs able to re-run
useUserPackages = true;
# Adds consistency

View file

@ -1,9 +1,18 @@
{ pkgs, lib, config, ... }:
{
pkgs,
lib,
config,
...
}:
let
passwordStoreDir = "/etc/passwords";
passwordHash = password: builtins.hashString "sha256" "${password.path}\n${builtins.toString password.selector}\n${builtins.toString password.transform}";
passwordHash =
password:
builtins.hashString "sha256" "${password.path}\n${builtins.toString password.selector}\n${builtins.toString password.transform}";
passwordStorePath = password: "${passwordStoreDir}/${passwordHash password}";
describePassword = password: password.path
describePassword =
password:
password.path
+ (if password.selector != null then " -> ${password.selector}" else "")
+ (if password.transform != null then " | (${password.transform})" else "");
passwordFiles = builtins.attrValues config.vivarium.passwordFiles;
@ -12,16 +21,23 @@ in
config = {
system = {
activationScripts.secrets = {
deps = [ "users" "groups" ];
deps = [
"users"
"groups"
];
supportsDryActivation = false; # TODO
text =
let
readPassword = password: "cat ${lib.strings.escapeShellArg (passwordStorePath password)}";
# Using awk's ENVIRON so it should resist any input?
pipeSubstitute = k: v: ''K=${lib.strings.escapeShellArg k} V="$(${v})" awk '{ gsub (ENVIRON["K"], ENVIRON["V"]); print }' '';
pipeSubstitute =
k: v:
''K=${lib.strings.escapeShellArg k} V="$(${v})" awk '{ gsub (ENVIRON["K"], ENVIRON["V"]); print }' '';
subsitutePassword = variable: password: pipeSubstitute variable (readPassword password);
subsitutePasswordFile = passwordFile: lib.mapAttrsToList subsitutePassword passwordFile.passwords;
renderPasswordFile = passwordFile: "${lib.strings.concatStringsSep "| " (subsitutePasswordFile passwordFile)} < ${passwordFile.template}";
renderPasswordFile =
passwordFile:
"${lib.strings.concatStringsSep "| " (subsitutePasswordFile passwordFile)} < ${passwordFile.template}";
installPasswordFile = passwordFile: ''
install -C -o ${passwordFile.owner} -g ${passwordFile.group} -m ${passwordFile.mode} -d ${builtins.dirOf passwordFile.path}
temp="$(mktemp)"
@ -31,12 +47,15 @@ in
rm "$temp"
trap - ERR
'';
installPasswordFileApp = passwordFile: pkgs.writeShellApplication {
name = builtins.replaceStrings ["/"] ["_"] passwordFile.path;
runtimeInputs = with pkgs; [ gawk ];
text = installPasswordFile passwordFile;
};
installPasswordFileSandboxed = passwordFile:
installPasswordFileApp =
passwordFile:
pkgs.writeShellApplication {
name = builtins.replaceStrings [ "/" ] [ "_" ] passwordFile.path;
runtimeInputs = with pkgs; [ gawk ];
text = installPasswordFile passwordFile;
};
installPasswordFileSandboxed =
passwordFile:
''${lib.getExe (installPasswordFileApp passwordFile)} || echo Failed to install ${lib.strings.escapeShellArg passwordFile.path}'';
in
''
@ -47,22 +66,38 @@ in
extraSystemBuilderCmds =
let
passwords = builtins.attrValues config.vivarium.passwords;
readPasswordClear = password: "pass show ${lib.strings.escapeShellArg password.path}" + (
if password.selector == null
then " | head -n1"
else
(if password.selector == "@"
then ""
else " | tail -n +2 | yq -r '.${password.selector}'")
);
readPassword = password: (readPasswordClear password) + (lib.strings.optionalString (password.transform != null) " | ${password.transform}");
readPasswordClear =
password:
"pass show ${lib.strings.escapeShellArg password.path}"
+ (
if password.selector == null then
" | head -n1"
else
(if password.selector == "@" then "" else " | tail -n +2 | yq -r '.${password.selector}'")
);
readPassword =
password:
(readPasswordClear password)
+ (lib.strings.optionalString (password.transform != null) " | ${password.transform}");
gitPath = password: ''"$PASSWORD_STORE_DIR"/${lib.strings.escapeShellArg password.path}.gpg'';
isGeneratedPassword = password: ''test -f ${gitPath password}'';
dateGit = password: " " + ''(cd "$(dirname ${gitPath password})"; git log -n1 --format='format:%ct' "$(basename ${gitPath password})")'' + " ";
dateGit =
password:
" "
+ ''(cd "$(dirname ${gitPath password})"; git log -n1 --format='format:%ct' "$(basename ${gitPath password})")''
+ " ";
dateStore = password: ''sudo stat -c '%Y' ${passwordStorePath password}'';
isInStore = password: ''sudo test -f ${passwordStorePath password}'';
testCanGenerate = password: lib.asserts.assertMsg (builtins.elem password.selector [ "@" null ]) "Unimplemented: generator + selector ${describePassword password}";
generatePassword = password: assert testCanGenerate password; ''${password.generator} | pass insert -m ${lib.strings.escapeShellArg password.path}'';
testCanGenerate =
password:
lib.asserts.assertMsg (builtins.elem password.selector [
"@"
null
]) "Unimplemented: generator + selector ${describePassword password}";
generatePassword =
password:
assert testCanGenerate password;
''${password.generator} | pass insert -m ${lib.strings.escapeShellArg password.path}'';
raiseCantGenerate = password: ''echo "Error: no generator" ; exit 1'';
syncPasswordStore = password: ''
# ${describePassword password}
@ -112,23 +147,27 @@ in
allFilenames = builtins.map (password: "${passwordStoreDir}/${passwordHash password}") passwords;
in
''
ln -s ${lib.getExe (pkgs.writeShellApplication {
name = "update-password-store";
text = ''
test -d "$PASSWORD_STORE_DIR"
sudo install -C -o root -g root -m u=rwx -d "${passwordStoreDir}"
ln -s ${
lib.getExe (
pkgs.writeShellApplication {
name = "update-password-store";
text = ''
test -d "$PASSWORD_STORE_DIR"
sudo install -C -o root -g root -m u=rwx -d "${passwordStoreDir}"
${lib.strings.concatLines (builtins.map syncPasswordStore passwords)}
${lib.strings.concatLines (builtins.map syncPasswordStore passwords)}
comm -23 <(sudo find ${passwordStoreDir} -type f -ctime +60 | sort) <(echo ${lib.strings.escapeShellArg (lib.strings.concatLines allFilenames)} | sort) | while read -r file
do
echo Removing "$file" from password store
sudo rm "$file"
done
'';
# -ctime +60 is so it is possible to boot from previous nixpkgs without missing transform hashes
# TODO Find a better mechanism, maybe à la bootspec, or something compatible with cross-arch
})} $out/bin/
comm -23 <(sudo find ${passwordStoreDir} -type f -ctime +60 | sort) <(echo ${lib.strings.escapeShellArg (lib.strings.concatLines allFilenames)} | sort) | while read -r file
do
echo Removing "$file" from password store
sudo rm "$file"
done
'';
# -ctime +60 is so it is possible to boot from previous nixpkgs without missing transform hashes
# TODO Find a better mechanism, maybe à la bootspec, or something compatible with cross-arch
}
)
} $out/bin/
'';
};
vivarium.passwords =
@ -144,82 +183,89 @@ in
vivarium =
let
defaultvar = "@PASSWORD@";
passwordSubmodule = lib.types.submodule ({ ... }: {
options = {
path = lib.mkOption {
type = lib.types.str;
description = "Path to the password store entry";
passwordSubmodule = lib.types.submodule (
{ ... }:
{
options = {
path = lib.mkOption {
type = lib.types.str;
description = "Path to the password store entry";
};
selector = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = "If unset, selects the first line. If '@', select everything. If any other value, will parse the password metadata as YML and use selector (yq).";
};
generator = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = "${lib.getExe pkgs.pwgen} -s 32";
description = "Command to generate the password. Won't work when selector is set to read metadata.";
};
transform = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = "Shell command to transform the password with before substitution";
};
};
selector = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = "If unset, selects the first line. If '@', select everything. If any other value, will parse the password metadata as YML and use selector (yq).";
};
generator = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = "${lib.getExe pkgs.pwgen} -s 32";
description = "Command to generate the password. Won't work when selector is set to read metadata.";
};
transform = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = "Shell command to transform the password with before substitution";
};
};
});
}
);
in
{
passwords = lib.mkOption {
default = { };
type = lib.types.attrsOf passwordSubmodule;
};
passwordFiles =
lib.mkOption {
default = { };
type = lib.types.attrsOf (lib.types.submodule ({ name, config, ... }: {
options = {
path = lib.mkOption {
type = lib.types.str;
default = name;
description = "Where to place the file.";
passwordFiles = lib.mkOption {
default = { };
type = lib.types.attrsOf (
lib.types.submodule (
{ name, config, ... }:
{
options = {
path = lib.mkOption {
type = lib.types.str;
default = name;
description = "Where to place the file.";
};
mode = lib.mkOption {
type = lib.types.str;
default = "0400";
description = "Unix permission";
};
owner = lib.mkOption {
type = lib.types.str;
default = "root";
description = "Owner of the secret file";
};
group = lib.mkOption {
type = lib.types.str;
default = "root";
description = "Group of the secret file";
};
text = lib.mkOption {
type = lib.types.str;
default = defaultvar;
description = "Content of the template used to make the file. Exclusive with `template`.";
};
template = lib.mkOption {
type = lib.types.path;
default = pkgs.writeText "password-template" config.text;
description = "Content of the template used to make the file. Exclusive with `text`.";
};
passwords = lib.mkOption {
default = lib.optionalAttrs (config.password != null) { ${defaultvar} = config.password; };
type = lib.types.attrsOf passwordSubmodule;
description = "Paths to passwords that will substitute the variables in the template. Exclusive with `password`";
};
password = lib.mkOption {
type = passwordSubmodule;
description = "Path to password that will substitute '@PASSWORD@' in the template. Exclusive with `passwords`.";
};
};
mode = lib.mkOption {
type = lib.types.str;
default = "0400";
description = "Unix permission";
};
owner = lib.mkOption {
type = lib.types.str;
default = "root";
description = "Owner of the secret file";
};
group = lib.mkOption {
type = lib.types.str;
default = "root";
description = "Group of the secret file";
};
text = lib.mkOption {
type = lib.types.str;
default = defaultvar;
description = "Content of the template used to make the file. Exclusive with `template`.";
};
template = lib.mkOption {
type = lib.types.path;
default = pkgs.writeText "password-template" config.text;
description = "Content of the template used to make the file. Exclusive with `text`.";
};
passwords = lib.mkOption {
default = lib.optionalAttrs (config.password != null) { ${defaultvar} = config.password; };
type = lib.types.attrsOf passwordSubmodule;
description = "Paths to passwords that will substitute the variables in the template. Exclusive with `password`";
};
password = lib.mkOption {
type = passwordSubmodule;
description = "Path to password that will substitute '@PASSWORD@' in the template. Exclusive with `passwords`.";
};
};
}));
};
}
)
);
};
};
};
}

View file

@ -1,7 +1,15 @@
{ pkgs, lib, config, ... }:
{
pkgs,
lib,
config,
...
}:
let
vivariumBuilderDefault = {
systems = [ "x86_64-linux" "aarch64-linux" ];
systems = [
"x86_64-linux"
"aarch64-linux"
];
protocol = "ssh-ng";
sshUser = "nixremote";
# sshKey doesn't work
@ -11,7 +19,12 @@ let
{
hostName = "abavorana.frogeye.fr";
publicHostKey = "c3NoLWVkMjU1MTkgQUFBQUMzTnphQzFsWkRJMU5URTVBQUFBSU5iNzcrS01tRHI0MVhZdmZITXQvK3NHMkJCSEIzYUl4M045WDNVejhFaUogZ2VvZmZyZXlAY3VyYWNhbwo=";
supportedFeatures = [ "nixos-test" "benchmark" "big-parallel" "kvm" ];
supportedFeatures = [
"nixos-test"
"benchmark"
"big-parallel"
"kvm"
];
maxJobs = 8;
}
{
@ -32,21 +45,31 @@ in
supportsDryActivation = true;
text = ''
mkdir -p /root/.ssh
cat ${pkgs.writeText "root-ssh-config" (lib.strings.concatLines (builtins.map (builder: ''
Host ${builder.hostName}
ControlMaster auto
ControlPath ~/.ssh/master-%r@%n:%p
ControlPersist 60s
'') vivariumBuilders)) } > /root/.ssh/config
cat ${
pkgs.writeText "root-ssh-config" (
lib.strings.concatLines (
builtins.map (builder: ''
Host ${builder.hostName}
ControlMaster auto
ControlPath ~/.ssh/master-%r@%n:%p
ControlPersist 60s
'') vivariumBuilders
)
)
} > /root/.ssh/config
'';
};
nix = {
buildMachines = builtins.map (vivariumBuilder: vivariumBuilderDefault // vivariumBuilder) vivariumBuilders;
buildMachines = builtins.map (
vivariumBuilder: vivariumBuilderDefault // vivariumBuilder
) vivariumBuilders;
distributedBuilds = false;
settings = {
builders-use-substitutes = true;
trusted-public-keys = publicKeys;
trusted-substituters = builtins.map (builder: "${builder.protocol}://${builder.sshUser}@${builder.hostName}") config.nix.buildMachines;
trusted-substituters = builtins.map (
builder: "${builder.protocol}://${builder.sshUser}@${builder.hostName}"
) config.nix.buildMachines;
};
};
};

View file

@ -1,4 +1,10 @@
{ pkgs, lib, config, stylix, ... }:
{
pkgs,
lib,
config,
stylix,
...
}:
{
config = {
boot = {
@ -6,13 +12,17 @@
initrd.systemd.enable = true;
};
stylix = {
enable = true;
enable = true;
homeManagerIntegration.autoImport = false; # Makes config reuse easier
polarity = "dark";
targets.plymouth.logo = pkgs.runCommand "flower.png" { } "${pkgs.inkscape}/bin/inkscape ${pkgs.substituteAll {
src = ./flower.svg;
color = config.lib.stylix.colors.withHashtag.base07;
}} -w 256 -o $out";
targets.plymouth.logo =
pkgs.runCommand "flower.png" { }
"${pkgs.inkscape}/bin/inkscape ${
pkgs.substituteAll {
src = ./flower.svg;
color = config.lib.stylix.colors.withHashtag.base07;
}
} -w 256 -o $out";
# UPST Default grub font is sansSerif, which doesn't work.
# Maybe because people patch mono with nerdfonts and that isn't compatible?
};

View file

@ -1,4 +1,9 @@
{ pkgs, lib, config, ... }:
{
pkgs,
lib,
config,
...
}:
let
cfg = config.services.syncthing;
service = "syncthing";
@ -9,9 +14,14 @@ let
generator = ''(t="$(mktemp -d)" && ${lib.getExe pkgs.syncthing} generate --home="$t" &> /dev/null && cat "$t"/{cert,key}.pem && rm -rf "$t")'';
};
capitalizeFirstLetter = str: (lib.strings.toUpper (builtins.substring 0 1 str)) + (builtins.substring 1 (builtins.stringLength str) str);
capitalizeFirstLetter =
str:
(lib.strings.toUpper (builtins.substring 0 1 str))
+ (builtins.substring 1 (builtins.stringLength str) str);
nixosDevices = builtins.map (system: system.config.frogeye) (builtins.attrValues config.frogeye.toplevel.nixosConfigurations);
nixosDevices = builtins.map (system: system.config.frogeye) (
builtins.attrValues config.frogeye.toplevel.nixosConfigurations
);
allDevices = nixosDevices;
syncingDevices = builtins.filter (device: device.syncthing.id != null) allDevices;
peerDevices = builtins.filter (device: device.name != config.frogeye.name) syncingDevices;
@ -20,7 +30,10 @@ let
allFolders = builtins.attrValues config.frogeye.folders;
syncedFolders = builtins.filter (folder: folder.syncthing.enable) allFolders;
folderShouldSyncWith = folder: device: (lib.hasAttrByPath [ folder.name ] device.folders) && device.folders.${folder.name}.syncthing.enable;
folderShouldSyncWith =
folder: device:
(lib.hasAttrByPath [ folder.name ] device.folders)
&& device.folders.${folder.name}.syncthing.enable;
folderDeviceEntry = folder: device: { deviceID = device.syncthing.id; };
enable = (builtins.length syncedFolders) > 0;
@ -38,29 +51,38 @@ in
cert = "${secretsDir}/cert.pem";
settings = {
devices = builtins.listToAttrs (builtins.map (device: { inherit (device) name; value = device.syncthing; }) syncingDevices);
folders = builtins.listToAttrs (builtins.map
(folder: {
devices = builtins.listToAttrs (
builtins.map (device: {
inherit (device) name;
value = device.syncthing;
}) syncingDevices
);
folders = builtins.listToAttrs (
builtins.map (folder: {
inherit (folder) name;
value =
{
label = "${capitalizeFirstLetter folder.user} ${folder.label}";
path = "${config.users.users.${folder.user}.home}/${folder.path}";
# Despite further in the code indicating this is possible, it is, actually not
# devices = builtins.map (folderDeviceEntry folder) (builtins.filter (folderShouldSyncWith folder) peerDevices);
devices = builtins.map (device: device.name) (builtins.filter (folderShouldSyncWith folder) peerDevices);
versioning =
if (config.frogeye.storageSize == "big" && folder.versionsMaxDays != null) then {
value = {
label = "${capitalizeFirstLetter folder.user} ${folder.label}";
path = "${config.users.users.${folder.user}.home}/${folder.path}";
# Despite further in the code indicating this is possible, it is, actually not
# devices = builtins.map (folderDeviceEntry folder) (builtins.filter (folderShouldSyncWith folder) peerDevices);
devices = builtins.map (device: device.name) (
builtins.filter (folderShouldSyncWith folder) peerDevices
);
versioning =
if (config.frogeye.storageSize == "big" && folder.versionsMaxDays != null) then
{
type = "staggered";
params.maxAge = builtins.toString (folder.versionsMaxDays * 24 * 3600);
# TODO Increase cleanupIntervalS to 1 day or so
} else null;
rescanIntervalS = 10 * 3600; # Using watcher, should be good enough
copyRangeMethod = "all"; # Prevents duplication
copyOwnershipFromParent = true;
} // folder.syncthing;
})
syncedFolders);
}
else
null;
rescanIntervalS = 10 * 3600; # Using watcher, should be good enough
copyRangeMethod = "all"; # Prevents duplication
copyOwnershipFromParent = true;
} // folder.syncthing;
}) syncedFolders
);
options = rec {
urAccepted = 3;
urSeen = urAccepted;
@ -75,7 +97,11 @@ in
''}"
];
PrivateUsers = lib.mkForce false;
AmbientCapabilities = ["CAP_CHOWN" "CAP_DAC_OVERRIDE" "CAP_FOWNER"];
AmbientCapabilities = [
"CAP_CHOWN"
"CAP_DAC_OVERRIDE"
"CAP_FOWNER"
];
};
vivarium.passwordFiles = {
${cfg.key}.password = password // {

View file

@ -1,17 +1,23 @@
{ pkgs, lib, config, ... }:
{
pkgs,
lib,
config,
...
}:
let
importScript = pkgs.writers.writePython3 "install-wifi-import"
{
libraries = [ pkgs.python3Packages.pyaml ];
}
(builtins.readFile ./import.py);
importScript = pkgs.writers.writePython3 "install-wifi-import" {
libraries = [ pkgs.python3Packages.pyaml ];
} (builtins.readFile ./import.py);
applyScript = pkgs.writers.writePython3 "install-wifi-apply" { } (builtins.readFile ./apply.py);
in
{
environment.systemPackages = [
(pkgs.writeShellApplication {
name = "install-wifi";
runtimeInputs = with pkgs; [ wpa_supplicant diffutils ];
runtimeInputs = with pkgs; [
wpa_supplicant
diffutils
];
text = ''
temp="$(mktemp --directory --suffix="-install-wifi")"
cd "$temp"
@ -61,8 +67,7 @@ in
"WiFi in de trein"
"_WIFI_LYRIA"
"WIFIonICE"
]
(ssid: { });
] (ssid: { });
userControlled.enable = true; # Allow some control with wpa_cli
};
services.chrony.serverOption = "offline";
@ -71,8 +76,8 @@ in
wantedBy = [ "wpa_supplicant.service" ];
path = with pkgs; [ wpa_supplicant ];
script = ''
for i in {1..50}; do wpa_cli status &> /dev/null && break; sleep 0.1; done
${applyScript}
for i in {1..50}; do wpa_cli status &> /dev/null && break; sleep 0.1; done
${applyScript}
'';
};
}