treewide: reformat
This commit is contained in:
@@ -19,11 +19,10 @@
|
|||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
dependencies =
|
dependencies = [
|
||||||
[
|
pkgs.stdenv.drvPath
|
||||||
pkgs.stdenv.drvPath
|
]
|
||||||
]
|
++ builtins.map (i: i.outPath) (builtins.attrValues (builtins.removeAttrs self.inputs [ "self" ]));
|
||||||
++ builtins.map (i: i.outPath) (builtins.attrValues (builtins.removeAttrs self.inputs [ "self" ]));
|
|
||||||
closureInfo = pkgs.closureInfo { rootPaths = dependencies; };
|
closureInfo = pkgs.closureInfo { rootPaths = dependencies; };
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
@@ -154,13 +153,12 @@
|
|||||||
nixos-test-backups = self.clanLib.test.containerTest {
|
nixos-test-backups = self.clanLib.test.containerTest {
|
||||||
name = "nixos-test-backups";
|
name = "nixos-test-backups";
|
||||||
nodes.machine = {
|
nodes.machine = {
|
||||||
imports =
|
imports = [
|
||||||
[
|
self.nixosModules.clanCore
|
||||||
self.nixosModules.clanCore
|
# Some custom overrides for the backup tests
|
||||||
# Some custom overrides for the backup tests
|
self.nixosModules.test-backup
|
||||||
self.nixosModules.test-backup
|
]
|
||||||
]
|
++
|
||||||
++
|
|
||||||
# import the inventory generated nixosModules
|
# import the inventory generated nixosModules
|
||||||
self.clan.clanInternals.inventoryClass.machines.test-backup.machineImports;
|
self.clan.clanInternals.inventoryClass.machines.test-backup.machineImports;
|
||||||
clan.core.settings.directory = ./.;
|
clan.core.settings.directory = ./.;
|
||||||
|
|||||||
@@ -50,7 +50,8 @@
|
|||||||
self.nixosConfigurations."test-flash-machine-${pkgs.hostPlatform.system}".config.system.build.toplevel
|
self.nixosConfigurations."test-flash-machine-${pkgs.hostPlatform.system}".config.system.build.toplevel
|
||||||
self.nixosConfigurations."test-flash-machine-${pkgs.hostPlatform.system}".config.system.build.diskoScript
|
self.nixosConfigurations."test-flash-machine-${pkgs.hostPlatform.system}".config.system.build.diskoScript
|
||||||
self.nixosConfigurations."test-flash-machine-${pkgs.hostPlatform.system}".config.system.build.diskoScript.drvPath
|
self.nixosConfigurations."test-flash-machine-${pkgs.hostPlatform.system}".config.system.build.diskoScript.drvPath
|
||||||
] ++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs);
|
]
|
||||||
|
++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs);
|
||||||
closureInfo = pkgs.closureInfo { rootPaths = dependencies; };
|
closureInfo = pkgs.closureInfo { rootPaths = dependencies; };
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -158,7 +158,8 @@
|
|||||||
pkgs.stdenv.drvPath
|
pkgs.stdenv.drvPath
|
||||||
pkgs.bash.drvPath
|
pkgs.bash.drvPath
|
||||||
pkgs.buildPackages.xorg.lndir
|
pkgs.buildPackages.xorg.lndir
|
||||||
] ++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs);
|
]
|
||||||
|
++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs);
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
pkgs.lib.mkIf (pkgs.stdenv.isLinux && !pkgs.stdenv.isAarch64) {
|
pkgs.lib.mkIf (pkgs.stdenv.isLinux && !pkgs.stdenv.isAarch64) {
|
||||||
|
|||||||
@@ -159,7 +159,8 @@ let
|
|||||||
pkgs.stdenv.drvPath
|
pkgs.stdenv.drvPath
|
||||||
pkgs.bash.drvPath
|
pkgs.bash.drvPath
|
||||||
pkgs.buildPackages.xorg.lndir
|
pkgs.buildPackages.xorg.lndir
|
||||||
] ++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs);
|
]
|
||||||
|
++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs);
|
||||||
};
|
};
|
||||||
|
|
||||||
in
|
in
|
||||||
|
|||||||
@@ -35,7 +35,8 @@
|
|||||||
pkgs.stdenv.drvPath
|
pkgs.stdenv.drvPath
|
||||||
pkgs.stdenvNoCC
|
pkgs.stdenvNoCC
|
||||||
self.nixosConfigurations.test-morph-machine.config.system.build.toplevel
|
self.nixosConfigurations.test-morph-machine.config.system.build.toplevel
|
||||||
] ++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs);
|
]
|
||||||
|
++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs);
|
||||||
closureInfo = pkgs.closureInfo { rootPaths = dependencies; };
|
closureInfo = pkgs.closureInfo { rootPaths = dependencies; };
|
||||||
in
|
in
|
||||||
|
|
||||||
|
|||||||
@@ -112,7 +112,8 @@
|
|||||||
pkgs.stdenv.drvPath
|
pkgs.stdenv.drvPath
|
||||||
pkgs.bash.drvPath
|
pkgs.bash.drvPath
|
||||||
pkgs.buildPackages.xorg.lndir
|
pkgs.buildPackages.xorg.lndir
|
||||||
] ++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs);
|
]
|
||||||
|
++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs);
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
self.clanLib.test.containerTest {
|
self.clanLib.test.containerTest {
|
||||||
|
|||||||
@@ -112,125 +112,124 @@ in
|
|||||||
'';
|
'';
|
||||||
in
|
in
|
||||||
lib.mkIf (cfg.targets != { }) {
|
lib.mkIf (cfg.targets != { }) {
|
||||||
environment.systemPackages =
|
environment.systemPackages = [
|
||||||
[
|
(pkgs.writeShellScriptBin "localbackup-create" ''
|
||||||
(pkgs.writeShellScriptBin "localbackup-create" ''
|
set -efu -o pipefail
|
||||||
set -efu -o pipefail
|
export PATH=${
|
||||||
export PATH=${
|
lib.makeBinPath [
|
||||||
lib.makeBinPath [
|
pkgs.rsnapshot
|
||||||
pkgs.rsnapshot
|
pkgs.coreutils
|
||||||
pkgs.coreutils
|
pkgs.util-linux
|
||||||
pkgs.util-linux
|
]
|
||||||
]
|
}
|
||||||
}
|
${lib.concatMapStringsSep "\n" (target: ''
|
||||||
${lib.concatMapStringsSep "\n" (target: ''
|
${mountHook target}
|
||||||
${mountHook target}
|
echo "Creating backup '${target.name}'"
|
||||||
echo "Creating backup '${target.name}'"
|
|
||||||
|
|
||||||
${lib.optionalString (target.preBackupHook != null) ''
|
${lib.optionalString (target.preBackupHook != null) ''
|
||||||
(
|
(
|
||||||
${target.preBackupHook}
|
${target.preBackupHook}
|
||||||
)
|
)
|
||||||
''}
|
|
||||||
|
|
||||||
declare -A preCommandErrors
|
|
||||||
${lib.concatMapStringsSep "\n" (
|
|
||||||
state:
|
|
||||||
lib.optionalString (state.preBackupCommand != null) ''
|
|
||||||
echo "Running pre-backup command for ${state.name}"
|
|
||||||
if ! /run/current-system/sw/bin/${state.preBackupCommand}; then
|
|
||||||
preCommandErrors["${state.name}"]=1
|
|
||||||
fi
|
|
||||||
''
|
|
||||||
) (builtins.attrValues config.clan.core.state)}
|
|
||||||
|
|
||||||
rsnapshot -c "${pkgs.writeText "rsnapshot.conf" (rsnapshotConfig target)}" sync
|
|
||||||
rsnapshot -c "${pkgs.writeText "rsnapshot.conf" (rsnapshotConfig target)}" snapshot
|
|
||||||
'') (builtins.attrValues cfg.targets)}'')
|
|
||||||
(pkgs.writeShellScriptBin "localbackup-list" ''
|
|
||||||
set -efu -o pipefail
|
|
||||||
export PATH=${
|
|
||||||
lib.makeBinPath [
|
|
||||||
pkgs.jq
|
|
||||||
pkgs.findutils
|
|
||||||
pkgs.coreutils
|
|
||||||
pkgs.util-linux
|
|
||||||
]
|
|
||||||
}
|
|
||||||
(${
|
|
||||||
lib.concatMapStringsSep "\n" (target: ''
|
|
||||||
(
|
|
||||||
${mountHook target}
|
|
||||||
find ${lib.escapeShellArg target.directory} -mindepth 1 -maxdepth 1 -name "snapshot.*" -print0 -type d \
|
|
||||||
| jq -Rs 'split("\u0000") | .[] | select(. != "") | { "name": ("${target.name}::" + .)}'
|
|
||||||
)
|
|
||||||
'') (builtins.attrValues cfg.targets)
|
|
||||||
}) | jq -s .
|
|
||||||
'')
|
|
||||||
(pkgs.writeShellScriptBin "localbackup-restore" ''
|
|
||||||
set -efu -o pipefail
|
|
||||||
export PATH=${
|
|
||||||
lib.makeBinPath [
|
|
||||||
pkgs.rsync
|
|
||||||
pkgs.coreutils
|
|
||||||
pkgs.util-linux
|
|
||||||
pkgs.gawk
|
|
||||||
]
|
|
||||||
}
|
|
||||||
if [[ "''${NAME:-}" == "" ]]; then
|
|
||||||
echo "No backup name given via NAME environment variable"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
if [[ "''${FOLDERS:-}" == "" ]]; then
|
|
||||||
echo "No folders given via FOLDERS environment variable"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
name=$(awk -F'::' '{print $1}' <<< $NAME)
|
|
||||||
backupname=''${NAME#$name::}
|
|
||||||
|
|
||||||
if command -v localbackup-mount-$name; then
|
|
||||||
localbackup-mount-$name
|
|
||||||
fi
|
|
||||||
if command -v localbackup-unmount-$name; then
|
|
||||||
trap "localbackup-unmount-$name" EXIT
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ! -d $backupname ]]; then
|
|
||||||
echo "No backup found $backupname"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
IFS=':' read -ra FOLDER <<< "''$FOLDERS"
|
|
||||||
for folder in "''${FOLDER[@]}"; do
|
|
||||||
mkdir -p "$folder"
|
|
||||||
rsync -a "$backupname/${config.networking.hostName}$folder/" "$folder"
|
|
||||||
done
|
|
||||||
'')
|
|
||||||
]
|
|
||||||
++ (lib.mapAttrsToList (
|
|
||||||
name: target:
|
|
||||||
pkgs.writeShellScriptBin ("localbackup-mount-" + name) ''
|
|
||||||
set -efu -o pipefail
|
|
||||||
${lib.optionalString (target.preMountHook != null) target.preMountHook}
|
|
||||||
${lib.optionalString (target.mountpoint != null) ''
|
|
||||||
if ! ${pkgs.util-linux}/bin/mountpoint -q ${lib.escapeShellArg target.mountpoint}; then
|
|
||||||
${pkgs.util-linux}/bin/mount -o X-mount.mkdir ${lib.escapeShellArg target.mountpoint}
|
|
||||||
fi
|
|
||||||
''}
|
''}
|
||||||
${lib.optionalString (target.postMountHook != null) target.postMountHook}
|
|
||||||
''
|
declare -A preCommandErrors
|
||||||
) cfg.targets)
|
${lib.concatMapStringsSep "\n" (
|
||||||
++ lib.mapAttrsToList (
|
state:
|
||||||
name: target:
|
lib.optionalString (state.preBackupCommand != null) ''
|
||||||
pkgs.writeShellScriptBin ("localbackup-unmount-" + name) ''
|
echo "Running pre-backup command for ${state.name}"
|
||||||
set -efu -o pipefail
|
if ! /run/current-system/sw/bin/${state.preBackupCommand}; then
|
||||||
${lib.optionalString (target.preUnmountHook != null) target.preUnmountHook}
|
preCommandErrors["${state.name}"]=1
|
||||||
${lib.optionalString (
|
fi
|
||||||
target.mountpoint != null
|
''
|
||||||
) "${pkgs.util-linux}/bin/umount ${lib.escapeShellArg target.mountpoint}"}
|
) (builtins.attrValues config.clan.core.state)}
|
||||||
${lib.optionalString (target.postUnmountHook != null) target.postUnmountHook}
|
|
||||||
''
|
rsnapshot -c "${pkgs.writeText "rsnapshot.conf" (rsnapshotConfig target)}" sync
|
||||||
) cfg.targets;
|
rsnapshot -c "${pkgs.writeText "rsnapshot.conf" (rsnapshotConfig target)}" snapshot
|
||||||
|
'') (builtins.attrValues cfg.targets)}'')
|
||||||
|
(pkgs.writeShellScriptBin "localbackup-list" ''
|
||||||
|
set -efu -o pipefail
|
||||||
|
export PATH=${
|
||||||
|
lib.makeBinPath [
|
||||||
|
pkgs.jq
|
||||||
|
pkgs.findutils
|
||||||
|
pkgs.coreutils
|
||||||
|
pkgs.util-linux
|
||||||
|
]
|
||||||
|
}
|
||||||
|
(${
|
||||||
|
lib.concatMapStringsSep "\n" (target: ''
|
||||||
|
(
|
||||||
|
${mountHook target}
|
||||||
|
find ${lib.escapeShellArg target.directory} -mindepth 1 -maxdepth 1 -name "snapshot.*" -print0 -type d \
|
||||||
|
| jq -Rs 'split("\u0000") | .[] | select(. != "") | { "name": ("${target.name}::" + .)}'
|
||||||
|
)
|
||||||
|
'') (builtins.attrValues cfg.targets)
|
||||||
|
}) | jq -s .
|
||||||
|
'')
|
||||||
|
(pkgs.writeShellScriptBin "localbackup-restore" ''
|
||||||
|
set -efu -o pipefail
|
||||||
|
export PATH=${
|
||||||
|
lib.makeBinPath [
|
||||||
|
pkgs.rsync
|
||||||
|
pkgs.coreutils
|
||||||
|
pkgs.util-linux
|
||||||
|
pkgs.gawk
|
||||||
|
]
|
||||||
|
}
|
||||||
|
if [[ "''${NAME:-}" == "" ]]; then
|
||||||
|
echo "No backup name given via NAME environment variable"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ "''${FOLDERS:-}" == "" ]]; then
|
||||||
|
echo "No folders given via FOLDERS environment variable"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
name=$(awk -F'::' '{print $1}' <<< $NAME)
|
||||||
|
backupname=''${NAME#$name::}
|
||||||
|
|
||||||
|
if command -v localbackup-mount-$name; then
|
||||||
|
localbackup-mount-$name
|
||||||
|
fi
|
||||||
|
if command -v localbackup-unmount-$name; then
|
||||||
|
trap "localbackup-unmount-$name" EXIT
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -d $backupname ]]; then
|
||||||
|
echo "No backup found $backupname"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
IFS=':' read -ra FOLDER <<< "''$FOLDERS"
|
||||||
|
for folder in "''${FOLDER[@]}"; do
|
||||||
|
mkdir -p "$folder"
|
||||||
|
rsync -a "$backupname/${config.networking.hostName}$folder/" "$folder"
|
||||||
|
done
|
||||||
|
'')
|
||||||
|
]
|
||||||
|
++ (lib.mapAttrsToList (
|
||||||
|
name: target:
|
||||||
|
pkgs.writeShellScriptBin ("localbackup-mount-" + name) ''
|
||||||
|
set -efu -o pipefail
|
||||||
|
${lib.optionalString (target.preMountHook != null) target.preMountHook}
|
||||||
|
${lib.optionalString (target.mountpoint != null) ''
|
||||||
|
if ! ${pkgs.util-linux}/bin/mountpoint -q ${lib.escapeShellArg target.mountpoint}; then
|
||||||
|
${pkgs.util-linux}/bin/mount -o X-mount.mkdir ${lib.escapeShellArg target.mountpoint}
|
||||||
|
fi
|
||||||
|
''}
|
||||||
|
${lib.optionalString (target.postMountHook != null) target.postMountHook}
|
||||||
|
''
|
||||||
|
) cfg.targets)
|
||||||
|
++ lib.mapAttrsToList (
|
||||||
|
name: target:
|
||||||
|
pkgs.writeShellScriptBin ("localbackup-unmount-" + name) ''
|
||||||
|
set -efu -o pipefail
|
||||||
|
${lib.optionalString (target.preUnmountHook != null) target.preUnmountHook}
|
||||||
|
${lib.optionalString (
|
||||||
|
target.mountpoint != null
|
||||||
|
) "${pkgs.util-linux}/bin/umount ${lib.escapeShellArg target.mountpoint}"}
|
||||||
|
${lib.optionalString (target.postUnmountHook != null) target.postUnmountHook}
|
||||||
|
''
|
||||||
|
) cfg.targets;
|
||||||
|
|
||||||
clan.core.backups.providers.localbackup = {
|
clan.core.backups.providers.localbackup = {
|
||||||
# TODO list needs to run locally or on the remote machine
|
# TODO list needs to run locally or on the remote machine
|
||||||
|
|||||||
@@ -116,47 +116,45 @@ in
|
|||||||
};
|
};
|
||||||
clan.core.postgresql.databases.matrix-synapse.restore.stopOnRestore = [ "matrix-synapse" ];
|
clan.core.postgresql.databases.matrix-synapse.restore.stopOnRestore = [ "matrix-synapse" ];
|
||||||
|
|
||||||
clan.core.vars.generators =
|
clan.core.vars.generators = {
|
||||||
{
|
"matrix-synapse" = {
|
||||||
"matrix-synapse" = {
|
files."synapse-registration_shared_secret" = { };
|
||||||
files."synapse-registration_shared_secret" = { };
|
runtimeInputs = with pkgs; [
|
||||||
runtimeInputs = with pkgs; [
|
coreutils
|
||||||
coreutils
|
pwgen
|
||||||
pwgen
|
];
|
||||||
];
|
migrateFact = "matrix-synapse";
|
||||||
migrateFact = "matrix-synapse";
|
script = ''
|
||||||
script = ''
|
echo -n "$(pwgen -s 32 1)" > "$out"/synapse-registration_shared_secret
|
||||||
echo -n "$(pwgen -s 32 1)" > "$out"/synapse-registration_shared_secret
|
'';
|
||||||
'';
|
};
|
||||||
};
|
}
|
||||||
|
// lib.mapAttrs' (
|
||||||
|
name: user:
|
||||||
|
lib.nameValuePair "matrix-password-${user.name}" {
|
||||||
|
files."matrix-password-${user.name}" = { };
|
||||||
|
migrateFact = "matrix-password-${user.name}";
|
||||||
|
runtimeInputs = with pkgs; [ xkcdpass ];
|
||||||
|
script = ''
|
||||||
|
xkcdpass -n 4 -d - > "$out"/${lib.escapeShellArg "matrix-password-${user.name}"}
|
||||||
|
'';
|
||||||
}
|
}
|
||||||
// lib.mapAttrs' (
|
) cfg.users;
|
||||||
name: user:
|
|
||||||
lib.nameValuePair "matrix-password-${user.name}" {
|
|
||||||
files."matrix-password-${user.name}" = { };
|
|
||||||
migrateFact = "matrix-password-${user.name}";
|
|
||||||
runtimeInputs = with pkgs; [ xkcdpass ];
|
|
||||||
script = ''
|
|
||||||
xkcdpass -n 4 -d - > "$out"/${lib.escapeShellArg "matrix-password-${user.name}"}
|
|
||||||
'';
|
|
||||||
}
|
|
||||||
) cfg.users;
|
|
||||||
|
|
||||||
systemd.services.matrix-synapse =
|
systemd.services.matrix-synapse =
|
||||||
let
|
let
|
||||||
usersScript =
|
usersScript = ''
|
||||||
''
|
while ! ${pkgs.netcat}/bin/nc -z -v ::1 8008; do
|
||||||
while ! ${pkgs.netcat}/bin/nc -z -v ::1 8008; do
|
if ! kill -0 "$MAINPID"; then exit 1; fi
|
||||||
if ! kill -0 "$MAINPID"; then exit 1; fi
|
sleep 1;
|
||||||
sleep 1;
|
done
|
||||||
done
|
''
|
||||||
''
|
+ lib.concatMapStringsSep "\n" (user: ''
|
||||||
+ lib.concatMapStringsSep "\n" (user: ''
|
# only create user if it doesn't exist
|
||||||
# only create user if it doesn't exist
|
/run/current-system/sw/bin/matrix-synapse-register_new_matrix_user --exists-ok --password-file ${
|
||||||
/run/current-system/sw/bin/matrix-synapse-register_new_matrix_user --exists-ok --password-file ${
|
config.clan.core.vars.generators."matrix-password-${user.name}".files."matrix-password-${user.name}".path
|
||||||
config.clan.core.vars.generators."matrix-password-${user.name}".files."matrix-password-${user.name}".path
|
} --user "${user.name}" ${if user.admin then "--admin" else "--no-admin"}
|
||||||
} --user "${user.name}" ${if user.admin then "--admin" else "--no-admin"}
|
'') (lib.attrValues cfg.users);
|
||||||
'') (lib.attrValues cfg.users);
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
path = [ pkgs.curl ];
|
path = [ pkgs.curl ];
|
||||||
|
|||||||
@@ -18,13 +18,12 @@
|
|||||||
config.clan.core.vars.generators.root-password.files.password-hash.path;
|
config.clan.core.vars.generators.root-password.files.password-hash.path;
|
||||||
|
|
||||||
clan.core.vars.generators.root-password = {
|
clan.core.vars.generators.root-password = {
|
||||||
files.password-hash =
|
files.password-hash = {
|
||||||
{
|
neededFor = "users";
|
||||||
neededFor = "users";
|
}
|
||||||
}
|
// (lib.optionalAttrs (_class == "nixos") {
|
||||||
// (lib.optionalAttrs (_class == "nixos") {
|
restartUnits = lib.optional (config.services.userborn.enable) "userborn.service";
|
||||||
restartUnits = lib.optional (config.services.userborn.enable) "userborn.service";
|
});
|
||||||
});
|
|
||||||
files.password = {
|
files.password = {
|
||||||
deploy = false;
|
deploy = false;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -32,17 +32,16 @@ in
|
|||||||
cfg.certificate.searchDomains != [ ]
|
cfg.certificate.searchDomains != [ ]
|
||||||
) config.clan.core.vars.generators.openssh-cert.files."ssh.id_ed25519-cert.pub".path;
|
) config.clan.core.vars.generators.openssh-cert.files."ssh.id_ed25519-cert.pub".path;
|
||||||
|
|
||||||
hostKeys =
|
hostKeys = [
|
||||||
[
|
{
|
||||||
{
|
path = config.clan.core.vars.generators.openssh.files."ssh.id_ed25519".path;
|
||||||
path = config.clan.core.vars.generators.openssh.files."ssh.id_ed25519".path;
|
type = "ed25519";
|
||||||
type = "ed25519";
|
}
|
||||||
}
|
]
|
||||||
]
|
++ lib.optional cfg.hostKeys.rsa.enable {
|
||||||
++ lib.optional cfg.hostKeys.rsa.enable {
|
path = config.clan.core.vars.generators.openssh-rsa.files."ssh.id_rsa".path;
|
||||||
path = config.clan.core.vars.generators.openssh-rsa.files."ssh.id_rsa".path;
|
type = "rsa";
|
||||||
type = "rsa";
|
};
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
clan.core.vars.generators.openssh = {
|
clan.core.vars.generators.openssh = {
|
||||||
@@ -62,7 +61,8 @@ in
|
|||||||
hostNames = [
|
hostNames = [
|
||||||
"localhost"
|
"localhost"
|
||||||
config.networking.hostName
|
config.networking.hostName
|
||||||
] ++ (lib.optional (config.networking.domain != null) config.networking.fqdn);
|
]
|
||||||
|
++ (lib.optional (config.networking.domain != null) config.networking.fqdn);
|
||||||
publicKey = config.clan.core.vars.generators.openssh.files."ssh.id_ed25519.pub".value;
|
publicKey = config.clan.core.vars.generators.openssh.files."ssh.id_ed25519.pub".value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -34,14 +34,15 @@ let
|
|||||||
value = {
|
value = {
|
||||||
name = machine;
|
name = machine;
|
||||||
id = (lib.removeSuffix "\n" (builtins.readFile (syncthingPublicKeyPath machine)));
|
id = (lib.removeSuffix "\n" (builtins.readFile (syncthingPublicKeyPath machine)));
|
||||||
addresses =
|
addresses = [
|
||||||
[ "dynamic" ]
|
"dynamic"
|
||||||
++ (
|
]
|
||||||
if (lib.elem machine networkIpMachines) then
|
++ (
|
||||||
[ "tcp://[${(lib.removeSuffix "\n" (builtins.readFile (zerotierIpMachinePath machine)))}]:22000" ]
|
if (lib.elem machine networkIpMachines) then
|
||||||
else
|
[ "tcp://[${(lib.removeSuffix "\n" (builtins.readFile (zerotierIpMachinePath machine)))}]:22000" ]
|
||||||
[ ]
|
else
|
||||||
);
|
[ ]
|
||||||
|
);
|
||||||
};
|
};
|
||||||
}) syncthingPublicKeyMachines;
|
}) syncthingPublicKeyMachines;
|
||||||
in
|
in
|
||||||
|
|||||||
@@ -21,17 +21,16 @@ in
|
|||||||
settings.certificateSearchDomains != [ ]
|
settings.certificateSearchDomains != [ ]
|
||||||
) config.clan.core.vars.generators.openssh-cert.files."ssh.id_ed25519-cert.pub".path;
|
) config.clan.core.vars.generators.openssh-cert.files."ssh.id_ed25519-cert.pub".path;
|
||||||
|
|
||||||
hostKeys =
|
hostKeys = [
|
||||||
[
|
{
|
||||||
{
|
path = config.clan.core.vars.generators.openssh.files."ssh.id_ed25519".path;
|
||||||
path = config.clan.core.vars.generators.openssh.files."ssh.id_ed25519".path;
|
type = "ed25519";
|
||||||
type = "ed25519";
|
}
|
||||||
}
|
]
|
||||||
]
|
++ lib.optional settings.rsaHostKey.enable {
|
||||||
++ lib.optional settings.rsaHostKey.enable {
|
path = config.clan.core.vars.generators.openssh-rsa.files."ssh.id_rsa".path;
|
||||||
path = config.clan.core.vars.generators.openssh-rsa.files."ssh.id_rsa".path;
|
type = "rsa";
|
||||||
type = "rsa";
|
};
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
clan.core.vars.generators.openssh = {
|
clan.core.vars.generators.openssh = {
|
||||||
@@ -51,7 +50,8 @@ in
|
|||||||
hostNames = [
|
hostNames = [
|
||||||
"localhost"
|
"localhost"
|
||||||
config.networking.hostName
|
config.networking.hostName
|
||||||
] ++ (lib.optional (config.networking.domain != null) config.networking.fqdn);
|
]
|
||||||
|
++ (lib.optional (config.networking.domain != null) config.networking.fqdn);
|
||||||
publicKey = config.clan.core.vars.generators.openssh.files."ssh.id_ed25519.pub".value;
|
publicKey = config.clan.core.vars.generators.openssh.files."ssh.id_ed25519.pub".value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -184,24 +184,24 @@
|
|||||||
settings.certificate.searchDomains != [ ]
|
settings.certificate.searchDomains != [ ]
|
||||||
) config.clan.core.vars.generators.openssh-cert.files."ssh.id_ed25519-cert.pub".path;
|
) config.clan.core.vars.generators.openssh-cert.files."ssh.id_ed25519-cert.pub".path;
|
||||||
|
|
||||||
hostKeys =
|
hostKeys = [
|
||||||
[
|
{
|
||||||
{
|
path = config.clan.core.vars.generators.openssh.files."ssh.id_ed25519".path;
|
||||||
path = config.clan.core.vars.generators.openssh.files."ssh.id_ed25519".path;
|
type = "ed25519";
|
||||||
type = "ed25519";
|
}
|
||||||
}
|
]
|
||||||
]
|
++ lib.optional settings.hostKeys.rsa.enable {
|
||||||
++ lib.optional settings.hostKeys.rsa.enable {
|
path = config.clan.core.vars.generators.openssh-rsa.files."ssh.id_rsa".path;
|
||||||
path = config.clan.core.vars.generators.openssh-rsa.files."ssh.id_rsa".path;
|
type = "rsa";
|
||||||
type = "rsa";
|
};
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
programs.ssh.knownHosts.clan-sshd-self-ed25519 = {
|
programs.ssh.knownHosts.clan-sshd-self-ed25519 = {
|
||||||
hostNames = [
|
hostNames = [
|
||||||
"localhost"
|
"localhost"
|
||||||
config.networking.hostName
|
config.networking.hostName
|
||||||
] ++ (lib.optional (config.networking.domain != null) config.networking.fqdn);
|
]
|
||||||
|
++ (lib.optional (config.networking.domain != null) config.networking.fqdn);
|
||||||
publicKey = config.clan.core.vars.generators.openssh.files."ssh.id_ed25519.pub".value;
|
publicKey = config.clan.core.vars.generators.openssh.files."ssh.id_ed25519.pub".value;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -157,11 +157,11 @@
|
|||||||
value = {
|
value = {
|
||||||
name = machine;
|
name = machine;
|
||||||
id = readMachineVar machine "syncthing/id/value" "";
|
id = readMachineVar machine "syncthing/id/value" "";
|
||||||
addresses =
|
addresses = [
|
||||||
[
|
"dynamic"
|
||||||
"dynamic"
|
]
|
||||||
]
|
++
|
||||||
++ lib.optional (readMachineVar machine "zerotier/zerotier-ip/value" null != null)
|
lib.optional (readMachineVar machine "zerotier/zerotier-ip/value" null != null)
|
||||||
"tcp://[${readMachineVar machine "zerotier/zerotier-ip/value" ""}]:22000";
|
"tcp://[${readMachineVar machine "zerotier/zerotier-ip/value" ""}]:22000";
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -30,18 +30,17 @@ pkgs.stdenv.mkDerivation {
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
nativeBuildInputs =
|
nativeBuildInputs = [
|
||||||
[
|
pkgs.python3
|
||||||
pkgs.python3
|
uml-c4
|
||||||
uml-c4
|
]
|
||||||
]
|
++ (with pkgs.python3Packages; [
|
||||||
++ (with pkgs.python3Packages; [
|
mkdocs
|
||||||
mkdocs
|
mkdocs-material
|
||||||
mkdocs-material
|
mkdocs-macros
|
||||||
mkdocs-macros
|
mkdocs-redoc-tag
|
||||||
mkdocs-redoc-tag
|
mkdocs-redirects
|
||||||
mkdocs-redirects
|
]);
|
||||||
]);
|
|
||||||
configurePhase = ''
|
configurePhase = ''
|
||||||
pushd docs
|
pushd docs
|
||||||
|
|
||||||
|
|||||||
@@ -156,7 +156,8 @@
|
|||||||
type = types.submoduleWith {
|
type = types.submoduleWith {
|
||||||
modules = [
|
modules = [
|
||||||
{ noInstanceOptions = true; }
|
{ noInstanceOptions = true; }
|
||||||
] ++ mapAttrsToList fakeInstanceOptions serviceModules;
|
]
|
||||||
|
++ mapAttrsToList fakeInstanceOptions serviceModules;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
55
flake.nix
55
flake.nix
@@ -87,34 +87,35 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
systems = import systems;
|
systems = import systems;
|
||||||
imports =
|
imports = [
|
||||||
[ flake-parts.flakeModules.modules ]
|
flake-parts.flakeModules.modules
|
||||||
++
|
]
|
||||||
# only importing existing paths allows to minimize the flake for test
|
++
|
||||||
# by removing files
|
# only importing existing paths allows to minimize the flake for test
|
||||||
filter pathExists [
|
# by removing files
|
||||||
./checks/flake-module.nix
|
filter pathExists [
|
||||||
./clanModules/flake-module.nix
|
./checks/flake-module.nix
|
||||||
./clanServices/flake-module.nix
|
./clanModules/flake-module.nix
|
||||||
./devShell.nix
|
./clanServices/flake-module.nix
|
||||||
./docs/nix/flake-module.nix
|
./devShell.nix
|
||||||
./flakeModules/flake-module.nix
|
./docs/nix/flake-module.nix
|
||||||
./flakeModules/demo_iso.nix
|
./flakeModules/flake-module.nix
|
||||||
./lib/filter-clan-core/flake-module.nix
|
./flakeModules/demo_iso.nix
|
||||||
./lib/flake-module.nix
|
./lib/filter-clan-core/flake-module.nix
|
||||||
./lib/flake-parts/clan-nixos-test.nix
|
./lib/flake-module.nix
|
||||||
./nixosModules/clanCore/vars/flake-module.nix
|
./lib/flake-parts/clan-nixos-test.nix
|
||||||
./nixosModules/flake-module.nix
|
./nixosModules/clanCore/vars/flake-module.nix
|
||||||
./pkgs/flake-module.nix
|
./nixosModules/flake-module.nix
|
||||||
./templates/flake-module.nix
|
./pkgs/flake-module.nix
|
||||||
]
|
./templates/flake-module.nix
|
||||||
++ [
|
|
||||||
(if pathExists ./flakeModules/clan.nix then import ./flakeModules/clan.nix inputs.self else { })
|
|
||||||
]
|
]
|
||||||
# Make treefmt-nix optional
|
++ [
|
||||||
# This only works if you set inputs.clan-core.inputs.treefmt-nix.follows
|
(if pathExists ./flakeModules/clan.nix then import ./flakeModules/clan.nix inputs.self else { })
|
||||||
# to a non-empty input that doesn't export a flakeModule
|
]
|
||||||
++ optional (pathExists ./formatter.nix && inputs.treefmt-nix ? flakeModule) ./formatter.nix;
|
# Make treefmt-nix optional
|
||||||
|
# This only works if you set inputs.clan-core.inputs.treefmt-nix.follows
|
||||||
|
# to a non-empty input that doesn't export a flakeModule
|
||||||
|
++ optional (pathExists ./formatter.nix && inputs.treefmt-nix ? flakeModule) ./formatter.nix;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,39 +95,38 @@
|
|||||||
"*/asciinema-player/*"
|
"*/asciinema-player/*"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
treefmt.programs.mypy.directories =
|
treefmt.programs.mypy.directories = {
|
||||||
{
|
"clan-cli" = {
|
||||||
"clan-cli" = {
|
directory = "pkgs/clan-cli";
|
||||||
directory = "pkgs/clan-cli";
|
extraPythonPackages = (self'.packages.clan-cli.devshellPyDeps pkgs.python3Packages);
|
||||||
extraPythonPackages = (self'.packages.clan-cli.devshellPyDeps pkgs.python3Packages);
|
};
|
||||||
};
|
"clan-app" = {
|
||||||
"clan-app" = {
|
directory = "pkgs/ui/clan-app";
|
||||||
directory = "pkgs/ui/clan-app";
|
extraPythonPackages = (self'.packages.clan-app.devshellPyDeps pkgs.python3Packages);
|
||||||
extraPythonPackages = (self'.packages.clan-app.devshellPyDeps pkgs.python3Packages);
|
extraPythonPaths = [ "../../clan-cli" ];
|
||||||
extraPythonPaths = [ "../../clan-cli" ];
|
};
|
||||||
};
|
"generate-test-vars" = {
|
||||||
"generate-test-vars" = {
|
directory = "pkgs/generate-test-vars";
|
||||||
directory = "pkgs/generate-test-vars";
|
extraPythonPackages = [
|
||||||
extraPythonPackages = [
|
(pkgs.python3.withPackages (ps: self'.packages.clan-cli.devshellPyDeps ps))
|
||||||
(pkgs.python3.withPackages (ps: self'.packages.clan-cli.devshellPyDeps ps))
|
];
|
||||||
];
|
extraPythonPaths = [ "../clan-cli" ];
|
||||||
extraPythonPaths = [ "../clan-cli" ];
|
};
|
||||||
};
|
}
|
||||||
}
|
// (
|
||||||
// (
|
if pkgs.stdenv.isLinux then
|
||||||
if pkgs.stdenv.isLinux then
|
{
|
||||||
{
|
"clan-vm-manager" = {
|
||||||
"clan-vm-manager" = {
|
directory = "pkgs/clan-vm-manager";
|
||||||
directory = "pkgs/clan-vm-manager";
|
extraPythonPackages = self'.packages.clan-vm-manager.externalTestDeps ++ [
|
||||||
extraPythonPackages = self'.packages.clan-vm-manager.externalTestDeps ++ [
|
(pkgs.python3.withPackages (ps: self'.packages.clan-cli.devshellPyDeps ps))
|
||||||
(pkgs.python3.withPackages (ps: self'.packages.clan-cli.devshellPyDeps ps))
|
];
|
||||||
];
|
extraPythonPaths = [ "../clan-cli" ];
|
||||||
extraPythonPaths = [ "../clan-cli" ];
|
};
|
||||||
};
|
}
|
||||||
}
|
else
|
||||||
else
|
{ }
|
||||||
{ }
|
);
|
||||||
);
|
|
||||||
treefmt.programs.ruff.check = true;
|
treefmt.programs.ruff.check = true;
|
||||||
treefmt.programs.ruff.format = true;
|
treefmt.programs.ruff.format = true;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -252,7 +252,8 @@ rec {
|
|||||||
// {
|
// {
|
||||||
oneOf = [
|
oneOf = [
|
||||||
{ type = "null"; }
|
{ type = "null"; }
|
||||||
] ++ (lib.optional (!isExcludedOption nestedOption) (parseOption nestedOption));
|
]
|
||||||
|
++ (lib.optional (!isExcludedOption nestedOption) (parseOption nestedOption));
|
||||||
}
|
}
|
||||||
# parse bool
|
# parse bool
|
||||||
else if
|
else if
|
||||||
|
|||||||
@@ -61,7 +61,8 @@ let
|
|||||||
modules = [ (config.outputs.moduleForMachine.${name} or { }) ];
|
modules = [ (config.outputs.moduleForMachine.${name} or { }) ];
|
||||||
specialArgs = {
|
specialArgs = {
|
||||||
inherit clan-core;
|
inherit clan-core;
|
||||||
} // specialArgs;
|
}
|
||||||
|
// specialArgs;
|
||||||
}
|
}
|
||||||
) allMachines;
|
) allMachines;
|
||||||
|
|
||||||
@@ -193,7 +194,8 @@ in
|
|||||||
# - nixosModules (_class = nixos)
|
# - nixosModules (_class = nixos)
|
||||||
# - darwinModules (_class = darwin)
|
# - darwinModules (_class = darwin)
|
||||||
(lib.optionalAttrs (clan-core ? "${_class}Modules") clan-core."${_class}Modules".clanCore)
|
(lib.optionalAttrs (clan-core ? "${_class}Modules") clan-core."${_class}Modules".clanCore)
|
||||||
] ++ lib.optionals (_class == "nixos") (v.machineImports or [ ]);
|
]
|
||||||
|
++ lib.optionals (_class == "nixos") (v.machineImports or [ ]);
|
||||||
|
|
||||||
# default hostname
|
# default hostname
|
||||||
networking.hostName = lib.mkDefault name;
|
networking.hostName = lib.mkDefault name;
|
||||||
|
|||||||
@@ -73,7 +73,8 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
] ++ lib.mapAttrsToList (_: service: service.exports) config.mappedServices;
|
]
|
||||||
|
++ lib.mapAttrsToList (_: service: service.exports) config.mappedServices;
|
||||||
};
|
};
|
||||||
default = { };
|
default = { };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -15,16 +15,15 @@
|
|||||||
lib.evalModules {
|
lib.evalModules {
|
||||||
class = "clan.service";
|
class = "clan.service";
|
||||||
specialArgs._ctx = prefix;
|
specialArgs._ctx = prefix;
|
||||||
modules =
|
modules = [
|
||||||
[
|
# Base module
|
||||||
# Base module
|
./service-module.nix
|
||||||
./service-module.nix
|
# Feature modules
|
||||||
# Feature modules
|
(lib.modules.importApply ./api-feature.nix {
|
||||||
(lib.modules.importApply ./api-feature.nix {
|
inherit clanLib prefix;
|
||||||
inherit clanLib prefix;
|
})
|
||||||
})
|
]
|
||||||
]
|
++
|
||||||
++
|
|
||||||
# Modules of caller
|
# Modules of caller
|
||||||
modules;
|
modules;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,7 +130,8 @@ in
|
|||||||
};
|
};
|
||||||
modules = [
|
modules = [
|
||||||
(import ./all-services-wrapper.nix { inherit directory; })
|
(import ./all-services-wrapper.nix { inherit directory; })
|
||||||
] ++ modules;
|
]
|
||||||
|
++ modules;
|
||||||
};
|
};
|
||||||
|
|
||||||
servicesEval = evalServices {
|
servicesEval = evalServices {
|
||||||
@@ -139,15 +140,14 @@ in
|
|||||||
{
|
{
|
||||||
inherit exportsModule;
|
inherit exportsModule;
|
||||||
mappedServices = lib.mapAttrs (_module_ident: instances: {
|
mappedServices = lib.mapAttrs (_module_ident: instances: {
|
||||||
imports =
|
imports = [
|
||||||
[
|
# Import the resolved module.
|
||||||
# Import the resolved module.
|
# i.e. clan.modules.admin
|
||||||
# i.e. clan.modules.admin
|
(builtins.head instances).instance.resolvedModule
|
||||||
(builtins.head instances).instance.resolvedModule
|
] # Include all the instances that correlate to the resolved module
|
||||||
] # Include all the instances that correlate to the resolved module
|
++ (builtins.map (v: {
|
||||||
++ (builtins.map (v: {
|
instances.${v.instanceName}.roles = v.instance.instanceRoles;
|
||||||
instances.${v.instanceName}.roles = v.instance.instanceRoles;
|
}) instances);
|
||||||
}) instances);
|
|
||||||
}) grouped;
|
}) grouped;
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -756,14 +756,13 @@ in
|
|||||||
instanceRes
|
instanceRes
|
||||||
// {
|
// {
|
||||||
nixosModule = {
|
nixosModule = {
|
||||||
imports =
|
imports = [
|
||||||
[
|
# Result of the applied 'perInstance = {...}: { nixosModule = { ... }; }'
|
||||||
# Result of the applied 'perInstance = {...}: { nixosModule = { ... }; }'
|
instanceRes.nixosModule
|
||||||
instanceRes.nixosModule
|
]
|
||||||
]
|
++ (map (
|
||||||
++ (map (
|
s: if builtins.typeOf s == "string" then "${directory}/${s}" else s
|
||||||
s: if builtins.typeOf s == "string" then "${directory}/${s}" else s
|
) instanceCfg.roles.${roleName}.extraModules);
|
||||||
) instanceCfg.roles.${roleName}.extraModules);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -877,7 +876,8 @@ in
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
(lib.setDefaultModuleLocation "Via ${config.manifest.name}.perMachine - machine='${machineName}';" machineResult.nixosModule)
|
(lib.setDefaultModuleLocation "Via ${config.manifest.name}.perMachine - machine='${machineName}';" machineResult.nixosModule)
|
||||||
] ++ instanceResults.nixosModules;
|
]
|
||||||
|
++ instanceResults.nixosModules;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
) config.result.allMachines;
|
) config.result.allMachines;
|
||||||
|
|||||||
@@ -35,7 +35,8 @@ let
|
|||||||
clan.core.settings.directory = clan-core;
|
clan.core.settings.directory = clan-core;
|
||||||
}
|
}
|
||||||
clan-core.nixosModules.clanCore
|
clan-core.nixosModules.clanCore
|
||||||
] ++ modules;
|
]
|
||||||
|
++ modules;
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
# lib.warn ''
|
# lib.warn ''
|
||||||
|
|||||||
@@ -45,7 +45,8 @@ lib.mkIf (config.clan.test.useContainers or true) {
|
|||||||
{
|
{
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
hostPkgs.makeWrapper
|
hostPkgs.makeWrapper
|
||||||
] ++ lib.optionals (!config.skipTypeCheck) [ hostPkgs.mypy ];
|
]
|
||||||
|
++ lib.optionals (!config.skipTypeCheck) [ hostPkgs.mypy ];
|
||||||
buildInputs = [ testDriver ];
|
buildInputs = [ testDriver ];
|
||||||
testScript = config.testScriptString;
|
testScript = config.testScriptString;
|
||||||
preferLocalBuild = true;
|
preferLocalBuild = true;
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ let
|
|||||||
colorama
|
colorama
|
||||||
junit-xml
|
junit-xml
|
||||||
nix
|
nix
|
||||||
] ++ extraPythonPackages python3Packages;
|
]
|
||||||
|
++ extraPythonPackages python3Packages;
|
||||||
nativeBuildInputs = [ setuptools ];
|
nativeBuildInputs = [ setuptools ];
|
||||||
format = "pyproject";
|
format = "pyproject";
|
||||||
src = ./.;
|
src = ./.;
|
||||||
|
|||||||
@@ -1,28 +1,27 @@
|
|||||||
{ _class, lib, ... }:
|
{ _class, lib, ... }:
|
||||||
{
|
{
|
||||||
imports =
|
imports = [
|
||||||
[
|
./backups.nix
|
||||||
./backups.nix
|
./defaults.nix
|
||||||
./defaults.nix
|
./facts
|
||||||
./facts
|
./inventory
|
||||||
./inventory
|
./meta/interface.nix
|
||||||
./meta/interface.nix
|
./metadata.nix
|
||||||
./metadata.nix
|
./networking.nix
|
||||||
./networking.nix
|
./nix-settings.nix
|
||||||
./nix-settings.nix
|
./options.nix
|
||||||
./options.nix
|
./outputs.nix
|
||||||
./outputs.nix
|
./sops.nix
|
||||||
./sops.nix
|
./vars
|
||||||
./vars
|
]
|
||||||
]
|
++ lib.optionals (_class == "nixos") [
|
||||||
++ lib.optionals (_class == "nixos") [
|
./nixos-facter.nix
|
||||||
./nixos-facter.nix
|
./vm.nix
|
||||||
./vm.nix
|
./postgresql
|
||||||
./postgresql
|
./machine-id
|
||||||
./machine-id
|
./state-version
|
||||||
./state-version
|
./wayland-proxy-virtwl.nix
|
||||||
./wayland-proxy-virtwl.nix
|
./zerotier
|
||||||
./zerotier
|
./zfs.nix
|
||||||
./zfs.nix
|
];
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,35 +90,34 @@
|
|||||||
default = { };
|
default = { };
|
||||||
type = lib.types.attrsOf (
|
type = lib.types.attrsOf (
|
||||||
lib.types.submodule (secret: {
|
lib.types.submodule (secret: {
|
||||||
options =
|
options = {
|
||||||
{
|
name = lib.mkOption {
|
||||||
name = lib.mkOption {
|
type = lib.types.str;
|
||||||
type = lib.types.str;
|
description = ''
|
||||||
description = ''
|
name of the secret
|
||||||
name of the secret
|
'';
|
||||||
'';
|
default = secret.config._module.args.name;
|
||||||
default = secret.config._module.args.name;
|
defaultText = "attribute name of the secret";
|
||||||
defaultText = "attribute name of the secret";
|
|
||||||
};
|
|
||||||
path = lib.mkOption {
|
|
||||||
type = lib.types.path;
|
|
||||||
description = ''
|
|
||||||
path to a secret which is generated by the generator
|
|
||||||
'';
|
|
||||||
default = config.clan.core.facts.secretPathFunction secret;
|
|
||||||
defaultText = lib.literalExpression "config.clan.core.facts.secretPathFunction secret";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// lib.optionalAttrs (config.clan.core.facts.secretStore == "sops") {
|
|
||||||
groups = lib.mkOption {
|
|
||||||
type = lib.types.listOf lib.types.str;
|
|
||||||
default = config.clan.core.sops.defaultGroups;
|
|
||||||
defaultText = lib.literalExpression "config.clan.core.sops.defaultGroups";
|
|
||||||
description = ''
|
|
||||||
Groups to decrypt the secret for. By default we always use the user's key.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
path = lib.mkOption {
|
||||||
|
type = lib.types.path;
|
||||||
|
description = ''
|
||||||
|
path to a secret which is generated by the generator
|
||||||
|
'';
|
||||||
|
default = config.clan.core.facts.secretPathFunction secret;
|
||||||
|
defaultText = lib.literalExpression "config.clan.core.facts.secretPathFunction secret";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// lib.optionalAttrs (config.clan.core.facts.secretStore == "sops") {
|
||||||
|
groups = lib.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.str;
|
||||||
|
default = config.clan.core.sops.defaultGroups;
|
||||||
|
defaultText = lib.literalExpression "config.clan.core.sops.defaultGroups";
|
||||||
|
description = ''
|
||||||
|
Groups to decrypt the secret for. By default we always use the user's key.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
description = ''
|
description = ''
|
||||||
|
|||||||
@@ -175,35 +175,34 @@
|
|||||||
default = { };
|
default = { };
|
||||||
type = lib.types.attrsOf (
|
type = lib.types.attrsOf (
|
||||||
lib.types.submodule (secret: {
|
lib.types.submodule (secret: {
|
||||||
options =
|
options = {
|
||||||
{
|
name = lib.mkOption {
|
||||||
name = lib.mkOption {
|
type = lib.types.str;
|
||||||
type = lib.types.str;
|
description = ''
|
||||||
description = ''
|
name of the secret
|
||||||
name of the secret
|
'';
|
||||||
'';
|
default = secret.config._module.args.name;
|
||||||
default = secret.config._module.args.name;
|
defaultText = "attribute name of the secret";
|
||||||
defaultText = "attribute name of the secret";
|
|
||||||
};
|
|
||||||
path = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
description = ''
|
|
||||||
path to a secret which is generated by the generator
|
|
||||||
'';
|
|
||||||
default = config.clan.core.facts.secretPathFunction secret;
|
|
||||||
defaultText = lib.literalExpression "config.clan.core.facts.secretPathFunction secret";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// lib.optionalAttrs (config.clan.core.facts.secretModule == "clan_cli.facts.secret_modules.sops") {
|
|
||||||
groups = lib.mkOption {
|
|
||||||
type = lib.types.listOf lib.types.str;
|
|
||||||
default = config.clan.core.sops.defaultGroups;
|
|
||||||
defaultText = lib.literalExpression "config.clan.core.sops.defaultGroups";
|
|
||||||
description = ''
|
|
||||||
Groups to decrypt the secret for. By default we always use the user's key.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
path = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = ''
|
||||||
|
path to a secret which is generated by the generator
|
||||||
|
'';
|
||||||
|
default = config.clan.core.facts.secretPathFunction secret;
|
||||||
|
defaultText = lib.literalExpression "config.clan.core.facts.secretPathFunction secret";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// lib.optionalAttrs (config.clan.core.facts.secretModule == "clan_cli.facts.secret_modules.sops") {
|
||||||
|
groups = lib.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.str;
|
||||||
|
default = config.clan.core.sops.defaultGroups;
|
||||||
|
defaultText = lib.literalExpression "config.clan.core.sops.defaultGroups";
|
||||||
|
description = ''
|
||||||
|
Groups to decrypt the secret for. By default we always use the user's key.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,16 +16,15 @@ let
|
|||||||
};
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
imports =
|
imports = [
|
||||||
[
|
./public/in_repo.nix
|
||||||
./public/in_repo.nix
|
./secret/fs.nix
|
||||||
./secret/fs.nix
|
./secret/sops
|
||||||
./secret/sops
|
./secret/vm.nix
|
||||||
./secret/vm.nix
|
]
|
||||||
]
|
++ lib.optionals (_class == "nixos") [
|
||||||
++ lib.optionals (_class == "nixos") [
|
./secret/password-store.nix
|
||||||
./secret/password-store.nix
|
];
|
||||||
];
|
|
||||||
|
|
||||||
options.clan.core.vars = lib.mkOption {
|
options.clan.core.vars = lib.mkOption {
|
||||||
description = ''
|
description = ''
|
||||||
|
|||||||
@@ -198,136 +198,135 @@ in
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
];
|
];
|
||||||
options =
|
options = {
|
||||||
{
|
name = mkOption {
|
||||||
name = mkOption {
|
type = str;
|
||||||
type = str;
|
description = ''
|
||||||
description = ''
|
name of the public fact
|
||||||
name of the public fact
|
'';
|
||||||
'';
|
readOnly = true;
|
||||||
readOnly = true;
|
default = file.config._module.args.name;
|
||||||
default = file.config._module.args.name;
|
defaultText = "Name of the file";
|
||||||
defaultText = "Name of the file";
|
};
|
||||||
};
|
generatorName = mkOption {
|
||||||
generatorName = mkOption {
|
type = str;
|
||||||
type = str;
|
description = ''
|
||||||
description = ''
|
name of the generator
|
||||||
name of the generator
|
'';
|
||||||
'';
|
readOnly = true;
|
||||||
readOnly = true;
|
default = generator.config._module.args.name;
|
||||||
default = generator.config._module.args.name;
|
defaultText = "Name of the generator that generates this file";
|
||||||
defaultText = "Name of the generator that generates this file";
|
};
|
||||||
};
|
share = mkOption {
|
||||||
share = mkOption {
|
type = bool;
|
||||||
type = bool;
|
description = ''
|
||||||
description = ''
|
Whether the generated vars should be shared between machines.
|
||||||
Whether the generated vars should be shared between machines.
|
Shared vars are only generated once, when the first machine using it is deployed.
|
||||||
Shared vars are only generated once, when the first machine using it is deployed.
|
Subsequent machines will re-use the already generated values.
|
||||||
Subsequent machines will re-use the already generated values.
|
'';
|
||||||
'';
|
readOnly = true;
|
||||||
readOnly = true;
|
internal = true;
|
||||||
internal = true;
|
default = generator.config.share;
|
||||||
default = generator.config.share;
|
defaultText = "Mirror of the share flag of the generator";
|
||||||
defaultText = "Mirror of the share flag of the generator";
|
};
|
||||||
};
|
deploy = mkOption {
|
||||||
deploy = mkOption {
|
description = ''
|
||||||
description = ''
|
Whether the file should be deployed to the target machine.
|
||||||
Whether the file should be deployed to the target machine.
|
|
||||||
|
|
||||||
Disable this if the generated file is only used as an input to other generators.
|
Disable this if the generated file is only used as an input to other generators.
|
||||||
'';
|
'';
|
||||||
type = bool;
|
type = bool;
|
||||||
default = true;
|
default = true;
|
||||||
};
|
};
|
||||||
secret = mkOption {
|
secret = mkOption {
|
||||||
description = ''
|
description = ''
|
||||||
Whether the file should be treated as a secret.
|
Whether the file should be treated as a secret.
|
||||||
'';
|
'';
|
||||||
type = bool;
|
type = bool;
|
||||||
default = true;
|
default = true;
|
||||||
};
|
};
|
||||||
flakePath = mkOption {
|
flakePath = mkOption {
|
||||||
description = ''
|
description = ''
|
||||||
The path to the file containing the content of the generated value.
|
The path to the file containing the content of the generated value.
|
||||||
This will be set automatically
|
This will be set automatically
|
||||||
'';
|
'';
|
||||||
type = nullOr path;
|
type = nullOr path;
|
||||||
default = null;
|
default = null;
|
||||||
};
|
};
|
||||||
path = mkOption {
|
path = mkOption {
|
||||||
description = ''
|
description = ''
|
||||||
The path to the file containing the content of the generated value.
|
The path to the file containing the content of the generated value.
|
||||||
This will be set automatically
|
This will be set automatically
|
||||||
'';
|
'';
|
||||||
type = str;
|
type = str;
|
||||||
defaultText = ''
|
defaultText = ''
|
||||||
builtins.path {
|
builtins.path {
|
||||||
name = "$${generator.config._module.args.name}_$${file.config._module.args.name}";
|
name = "$${generator.config._module.args.name}_$${file.config._module.args.name}";
|
||||||
path = file.config.flakePath;
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
default = builtins.path {
|
|
||||||
name = "${generator.config._module.args.name}_${file.config._module.args.name}";
|
|
||||||
path = file.config.flakePath;
|
path = file.config.flakePath;
|
||||||
};
|
|
||||||
};
|
|
||||||
neededFor = mkOption {
|
|
||||||
description = ''
|
|
||||||
This option determines when the secret will be decrypted and deployed to the target machine.
|
|
||||||
|
|
||||||
By setting this to `partitioning`, the secret will be deployed prior to running `disko` allowing
|
|
||||||
you to manage filesystem encryption keys. These will only be deployed when installing the system.
|
|
||||||
By setting this to `activation`, the secret will be deployed prior to running `nixos-rebuild` or `nixos-install`.
|
|
||||||
By setting this to `user`, the secret will be deployed prior to users and groups are created, allowing
|
|
||||||
users' passwords to be managed by vars. The secret will be stored in `/run/secrets-for-users` and `owner` and `group` must be `root`.
|
|
||||||
'';
|
|
||||||
type = enum [
|
|
||||||
"partitioning"
|
|
||||||
"activation"
|
|
||||||
"users"
|
|
||||||
"services"
|
|
||||||
];
|
|
||||||
default = "services";
|
|
||||||
};
|
|
||||||
owner = mkOption {
|
|
||||||
description = "The user name or id that will own the file.";
|
|
||||||
default = "root";
|
|
||||||
};
|
|
||||||
group = mkOption {
|
|
||||||
description = "The group name or id that will own the file.";
|
|
||||||
default = if _class == "darwin" then "wheel" else "root";
|
|
||||||
defaultText = lib.literalExpression ''if _class == "darwin" then "wheel" else "root"'';
|
|
||||||
};
|
|
||||||
mode = mkOption {
|
|
||||||
type = strMatching "^[0-7]{4}$";
|
|
||||||
description = "The unix file mode of the file. Must be a 4-digit octal number.";
|
|
||||||
default = "0400";
|
|
||||||
};
|
|
||||||
value =
|
|
||||||
mkOption {
|
|
||||||
description = ''
|
|
||||||
The content of the generated value.
|
|
||||||
Only available if the file is not secret.
|
|
||||||
'';
|
|
||||||
type = str;
|
|
||||||
defaultText = "Throws error because the value of a secret file is not accessible";
|
|
||||||
}
|
}
|
||||||
// lib.optionalAttrs file.config.secret {
|
'';
|
||||||
default = throw "Cannot access value of secret file";
|
default = builtins.path {
|
||||||
};
|
name = "${generator.config._module.args.name}_${file.config._module.args.name}";
|
||||||
}
|
path = file.config.flakePath;
|
||||||
// (lib.optionalAttrs (_class == "nixos") {
|
|
||||||
restartUnits = mkOption {
|
|
||||||
description = ''
|
|
||||||
A list of systemd units that should be restarted after the file is deployed.
|
|
||||||
This is useful for services that need to reload their configuration after the file is updated.
|
|
||||||
|
|
||||||
WARNING: currently only sops-nix implements this option.
|
|
||||||
'';
|
|
||||||
type = listOf str;
|
|
||||||
default = [ ];
|
|
||||||
};
|
};
|
||||||
});
|
};
|
||||||
|
neededFor = mkOption {
|
||||||
|
description = ''
|
||||||
|
This option determines when the secret will be decrypted and deployed to the target machine.
|
||||||
|
|
||||||
|
By setting this to `partitioning`, the secret will be deployed prior to running `disko` allowing
|
||||||
|
you to manage filesystem encryption keys. These will only be deployed when installing the system.
|
||||||
|
By setting this to `activation`, the secret will be deployed prior to running `nixos-rebuild` or `nixos-install`.
|
||||||
|
By setting this to `user`, the secret will be deployed prior to users and groups are created, allowing
|
||||||
|
users' passwords to be managed by vars. The secret will be stored in `/run/secrets-for-users` and `owner` and `group` must be `root`.
|
||||||
|
'';
|
||||||
|
type = enum [
|
||||||
|
"partitioning"
|
||||||
|
"activation"
|
||||||
|
"users"
|
||||||
|
"services"
|
||||||
|
];
|
||||||
|
default = "services";
|
||||||
|
};
|
||||||
|
owner = mkOption {
|
||||||
|
description = "The user name or id that will own the file.";
|
||||||
|
default = "root";
|
||||||
|
};
|
||||||
|
group = mkOption {
|
||||||
|
description = "The group name or id that will own the file.";
|
||||||
|
default = if _class == "darwin" then "wheel" else "root";
|
||||||
|
defaultText = lib.literalExpression ''if _class == "darwin" then "wheel" else "root"'';
|
||||||
|
};
|
||||||
|
mode = mkOption {
|
||||||
|
type = strMatching "^[0-7]{4}$";
|
||||||
|
description = "The unix file mode of the file. Must be a 4-digit octal number.";
|
||||||
|
default = "0400";
|
||||||
|
};
|
||||||
|
value =
|
||||||
|
mkOption {
|
||||||
|
description = ''
|
||||||
|
The content of the generated value.
|
||||||
|
Only available if the file is not secret.
|
||||||
|
'';
|
||||||
|
type = str;
|
||||||
|
defaultText = "Throws error because the value of a secret file is not accessible";
|
||||||
|
}
|
||||||
|
// lib.optionalAttrs file.config.secret {
|
||||||
|
default = throw "Cannot access value of secret file";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// (lib.optionalAttrs (_class == "nixos") {
|
||||||
|
restartUnits = mkOption {
|
||||||
|
description = ''
|
||||||
|
A list of systemd units that should be restarted after the file is deployed.
|
||||||
|
This is useful for services that need to reload their configuration after the file is updated.
|
||||||
|
|
||||||
|
WARNING: currently only sops-nix implements this option.
|
||||||
|
'';
|
||||||
|
type = listOf str;
|
||||||
|
default = [ ];
|
||||||
|
};
|
||||||
|
});
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -43,23 +43,22 @@ in
|
|||||||
secrets = lib.listToAttrs (
|
secrets = lib.listToAttrs (
|
||||||
map (secret: {
|
map (secret: {
|
||||||
name = "vars/${secret.generator}/${secret.name}";
|
name = "vars/${secret.generator}/${secret.name}";
|
||||||
value =
|
value = {
|
||||||
{
|
inherit (secret)
|
||||||
inherit (secret)
|
owner
|
||||||
owner
|
group
|
||||||
group
|
mode
|
||||||
mode
|
neededForUsers
|
||||||
neededForUsers
|
;
|
||||||
;
|
sopsFile = builtins.path {
|
||||||
sopsFile = builtins.path {
|
name = "${secret.generator}_${secret.name}";
|
||||||
name = "${secret.generator}_${secret.name}";
|
path = secretPath secret;
|
||||||
path = secretPath secret;
|
};
|
||||||
};
|
format = "binary";
|
||||||
format = "binary";
|
}
|
||||||
}
|
// (lib.optionalAttrs (_class == "nixos") {
|
||||||
// (lib.optionalAttrs (_class == "nixos") {
|
inherit (secret) restartUnits;
|
||||||
inherit (secret) restartUnits;
|
});
|
||||||
});
|
|
||||||
}) (builtins.filter (x: builtins.pathExists (secretPath x)) vars)
|
}) (builtins.filter (x: builtins.pathExists (secretPath x)) vars)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -8,16 +8,15 @@ let
|
|||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
{
|
{
|
||||||
imports =
|
imports = [
|
||||||
[
|
./clanCore
|
||||||
./clanCore
|
inputs.sops-nix."${_class}Modules".sops
|
||||||
inputs.sops-nix."${_class}Modules".sops
|
]
|
||||||
]
|
++ lib.optionals (_class == "nixos") [
|
||||||
++ lib.optionals (_class == "nixos") [
|
inputs.nixos-facter-modules.nixosModules.facter
|
||||||
inputs.nixos-facter-modules.nixosModules.facter
|
inputs.disko.nixosModules.default
|
||||||
inputs.disko.nixosModules.default
|
inputs.data-mesher.nixosModules.data-mesher
|
||||||
inputs.data-mesher.nixosModules.data-mesher
|
];
|
||||||
];
|
|
||||||
config = {
|
config = {
|
||||||
clan.core.clanPkgs = lib.mkDefault self.packages.${pkgs.hostPlatform.system};
|
clan.core.clanPkgs = lib.mkDefault self.packages.${pkgs.hostPlatform.system};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -90,7 +90,8 @@ pythonRuntime.pkgs.buildPythonApplication {
|
|||||||
|
|
||||||
# gtk4 deps
|
# gtk4 deps
|
||||||
wrapGAppsHook4
|
wrapGAppsHook4
|
||||||
] ++ runtimeDependencies;
|
]
|
||||||
|
++ runtimeDependencies;
|
||||||
|
|
||||||
# The necessity of setting buildInputs and propagatedBuildInputs to the
|
# The necessity of setting buildInputs and propagatedBuildInputs to the
|
||||||
# same values for your Python package within Nix largely stems from ensuring
|
# same values for your Python package within Nix largely stems from ensuring
|
||||||
@@ -98,7 +99,8 @@ pythonRuntime.pkgs.buildPythonApplication {
|
|||||||
# at build time and runtime,
|
# at build time and runtime,
|
||||||
propagatedBuildInputs = [
|
propagatedBuildInputs = [
|
||||||
(pythonRuntime.withPackages (ps: clan-cli-module ++ (pyDeps ps)))
|
(pythonRuntime.withPackages (ps: clan-cli-module ++ (pyDeps ps)))
|
||||||
] ++ runtimeDependencies;
|
]
|
||||||
|
++ runtimeDependencies;
|
||||||
|
|
||||||
# also re-expose dependencies so we test them in CI
|
# also re-expose dependencies so we test them in CI
|
||||||
passthru = {
|
passthru = {
|
||||||
|
|||||||
@@ -35,15 +35,14 @@ mkShell {
|
|||||||
clan-app-ui
|
clan-app-ui
|
||||||
];
|
];
|
||||||
|
|
||||||
packages =
|
packages = [
|
||||||
[
|
# required for reload-python-api.sh script
|
||||||
# required for reload-python-api.sh script
|
json2ts
|
||||||
json2ts
|
]
|
||||||
]
|
++ (lib.optionals stdenv.hostPlatform.isLinux [
|
||||||
++ (lib.optionals stdenv.hostPlatform.isLinux [
|
# for viewing the storybook in a webkit-based browser to match webview
|
||||||
# for viewing the storybook in a webkit-based browser to match webview
|
luakit
|
||||||
luakit
|
]);
|
||||||
]);
|
|
||||||
|
|
||||||
inherit (clan-app) propagatedBuildInputs;
|
inherit (clan-app) propagatedBuildInputs;
|
||||||
|
|
||||||
@@ -63,64 +62,64 @@ mkShell {
|
|||||||
++ (clan-app.devshellPyDeps ps)
|
++ (clan-app.devshellPyDeps ps)
|
||||||
))
|
))
|
||||||
ruff
|
ruff
|
||||||
] ++ clan-app.runtimeDeps;
|
]
|
||||||
|
++ clan-app.runtimeDeps;
|
||||||
|
|
||||||
shellHook =
|
shellHook = ''
|
||||||
''
|
export CLAN_CORE_PATH=$(git rev-parse --show-toplevel)
|
||||||
export CLAN_CORE_PATH=$(git rev-parse --show-toplevel)
|
|
||||||
|
|
||||||
## Clan app
|
## Clan app
|
||||||
pushd "$CLAN_CORE_PATH/pkgs/clan-app"
|
pushd "$CLAN_CORE_PATH/pkgs/clan-app"
|
||||||
|
|
||||||
# Add clan-app command to PATH
|
# Add clan-app command to PATH
|
||||||
export PATH="$(pwd)/bin":"$PATH"
|
export PATH="$(pwd)/bin":"$PATH"
|
||||||
|
|
||||||
# Add current package to PYTHONPATH
|
# Add current package to PYTHONPATH
|
||||||
export PYTHONPATH="$(pwd)''${PYTHONPATH:+:$PYTHONPATH:}"
|
export PYTHONPATH="$(pwd)''${PYTHONPATH:+:$PYTHONPATH:}"
|
||||||
popd
|
popd
|
||||||
|
|
||||||
# Add clan-cli to the python path so that we can import it without building it in nix first
|
# Add clan-cli to the python path so that we can import it without building it in nix first
|
||||||
export PYTHONPATH="$CLAN_CORE_PATH/pkgs/clan-cli":"$PYTHONPATH"
|
export PYTHONPATH="$CLAN_CORE_PATH/pkgs/clan-cli":"$PYTHONPATH"
|
||||||
|
|
||||||
export XDG_DATA_DIRS=$GSETTINGS_SCHEMAS_PATH:$XDG_DATA_DIRS
|
export XDG_DATA_DIRS=$GSETTINGS_SCHEMAS_PATH:$XDG_DATA_DIRS
|
||||||
export WEBVIEW_LIB_DIR=${webview-lib}/lib
|
export WEBVIEW_LIB_DIR=${webview-lib}/lib
|
||||||
export OPENAPI_FILE="${clan-lib-openapi}"
|
export OPENAPI_FILE="${clan-lib-openapi}"
|
||||||
export SWAGGER_UI_DIST="${swagger-ui-dist}/dist"
|
export SWAGGER_UI_DIST="${swagger-ui-dist}/dist"
|
||||||
|
|
||||||
## Webview UI
|
## Webview UI
|
||||||
# Add clan-app-ui scripts to PATH
|
# Add clan-app-ui scripts to PATH
|
||||||
pushd "$CLAN_CORE_PATH/pkgs/clan-app/ui"
|
pushd "$CLAN_CORE_PATH/pkgs/clan-app/ui"
|
||||||
export NODE_PATH="$(pwd)/node_modules"
|
export NODE_PATH="$(pwd)/node_modules"
|
||||||
export PATH="$NODE_PATH/.bin:$(pwd)/bin:$PATH"
|
export PATH="$NODE_PATH/.bin:$(pwd)/bin:$PATH"
|
||||||
cp -r ${self'.packages.fonts} .fonts
|
cp -r ${self'.packages.fonts} .fonts
|
||||||
chmod -R +w .fonts
|
chmod -R +w .fonts
|
||||||
mkdir -p api
|
mkdir -p api
|
||||||
cp -r ${clan-ts-api}/* api
|
cp -r ${clan-ts-api}/* api
|
||||||
chmod -R +w api
|
chmod -R +w api
|
||||||
popd
|
popd
|
||||||
|
|
||||||
# configure process-compose
|
# configure process-compose
|
||||||
if test -f "$CLAN_CORE_PATH/pkgs/clan-app/.local.env"; then
|
if test -f "$CLAN_CORE_PATH/pkgs/clan-app/.local.env"; then
|
||||||
source "$CLAN_CORE_PATH/pkgs/clan-app/.local.env"
|
source "$CLAN_CORE_PATH/pkgs/clan-app/.local.env"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
export PC_CONFIG_FILES="$CLAN_CORE_PATH/pkgs/clan-app/process-compose.yaml"
|
export PC_CONFIG_FILES="$CLAN_CORE_PATH/pkgs/clan-app/process-compose.yaml"
|
||||||
|
|
||||||
echo -e "${GREEN}To launch a qemu VM for testing, run:\n start-vm <number of VMs>${NC}"
|
echo -e "${GREEN}To launch a qemu VM for testing, run:\n start-vm <number of VMs>${NC}"
|
||||||
''
|
''
|
||||||
+
|
+
|
||||||
# todo darwin support needs some work
|
# todo darwin support needs some work
|
||||||
(lib.optionalString stdenv.hostPlatform.isLinux ''
|
(lib.optionalString stdenv.hostPlatform.isLinux ''
|
||||||
# configure playwright for storybook snapshot testing
|
# configure playwright for storybook snapshot testing
|
||||||
export PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1
|
export PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1
|
||||||
export PLAYWRIGHT_BROWSERS_PATH=${
|
export PLAYWRIGHT_BROWSERS_PATH=${
|
||||||
playwright-driver.browsers.override {
|
playwright-driver.browsers.override {
|
||||||
withFfmpeg = false;
|
withFfmpeg = false;
|
||||||
withFirefox = false;
|
withFirefox = false;
|
||||||
withChromium = false;
|
withChromium = false;
|
||||||
withChromiumHeadlessShell = true;
|
withChromiumHeadlessShell = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
export PLAYWRIGHT_HOST_PLATFORM_OVERRIDE="ubuntu-24.04"
|
}
|
||||||
'');
|
export PLAYWRIGHT_HOST_PLATFORM_OVERRIDE="ubuntu-24.04"
|
||||||
|
'');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -156,93 +156,92 @@ pythonRuntime.pkgs.buildPythonApplication {
|
|||||||
|
|
||||||
propagatedBuildInputs = [ pythonRuntimeWithDeps ] ++ bundledRuntimeDependencies;
|
propagatedBuildInputs = [ pythonRuntimeWithDeps ] ++ bundledRuntimeDependencies;
|
||||||
|
|
||||||
passthru.tests =
|
passthru.tests = {
|
||||||
{
|
clan-deps = pkgs.runCommand "clan-deps" { } ''
|
||||||
clan-deps = pkgs.runCommand "clan-deps" { } ''
|
# ${builtins.toString (builtins.attrValues testRuntimeDependenciesMap)}
|
||||||
# ${builtins.toString (builtins.attrValues testRuntimeDependenciesMap)}
|
touch $out
|
||||||
touch $out
|
'';
|
||||||
'';
|
clan-pytest-without-core =
|
||||||
clan-pytest-without-core =
|
runCommand "clan-pytest-without-core"
|
||||||
runCommand "clan-pytest-without-core"
|
{
|
||||||
{
|
nativeBuildInputs = testDependencies;
|
||||||
nativeBuildInputs = testDependencies;
|
closureInfo = pkgs.closureInfo {
|
||||||
closureInfo = pkgs.closureInfo {
|
rootPaths = [
|
||||||
rootPaths = [
|
templateDerivation
|
||||||
templateDerivation
|
];
|
||||||
];
|
};
|
||||||
};
|
}
|
||||||
}
|
''
|
||||||
''
|
set -euo pipefail
|
||||||
set -euo pipefail
|
cp -r ${sourceWithTests} ./src
|
||||||
cp -r ${sourceWithTests} ./src
|
chmod +w -R ./src
|
||||||
chmod +w -R ./src
|
cd ./src
|
||||||
cd ./src
|
|
||||||
|
|
||||||
export NIX_STATE_DIR=$TMPDIR/nix IN_NIX_SANDBOX=1 PYTHONWARNINGS=error
|
export NIX_STATE_DIR=$TMPDIR/nix IN_NIX_SANDBOX=1 PYTHONWARNINGS=error
|
||||||
|
|
||||||
# required to prevent concurrent 'nix flake lock' operations
|
# required to prevent concurrent 'nix flake lock' operations
|
||||||
export CLAN_TEST_STORE=$TMPDIR/store
|
export CLAN_TEST_STORE=$TMPDIR/store
|
||||||
export LOCK_NIX=$TMPDIR/nix_lock
|
export LOCK_NIX=$TMPDIR/nix_lock
|
||||||
mkdir -p "$CLAN_TEST_STORE/nix/store"
|
mkdir -p "$CLAN_TEST_STORE/nix/store"
|
||||||
|
|
||||||
# limit build cores to 16
|
# limit build cores to 16
|
||||||
jobs="$((NIX_BUILD_CORES>16 ? 16 : NIX_BUILD_CORES))"
|
jobs="$((NIX_BUILD_CORES>16 ? 16 : NIX_BUILD_CORES))"
|
||||||
|
|
||||||
python -m pytest -m "not impure and not with_core" -n $jobs ./clan_cli ./clan_lib
|
python -m pytest -m "not impure and not with_core" -n $jobs ./clan_cli ./clan_lib
|
||||||
touch $out
|
touch $out
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
// lib.optionalAttrs (!stdenv.isDarwin) {
|
// lib.optionalAttrs (!stdenv.isDarwin) {
|
||||||
# disabled on macOS until we fix all remaining issues
|
# disabled on macOS until we fix all remaining issues
|
||||||
clan-pytest-with-core =
|
clan-pytest-with-core =
|
||||||
runCommand "clan-pytest-with-core"
|
runCommand "clan-pytest-with-core"
|
||||||
{
|
{
|
||||||
nativeBuildInputs = testDependencies;
|
nativeBuildInputs = testDependencies;
|
||||||
buildInputs = [
|
buildInputs = [
|
||||||
|
pkgs.bash
|
||||||
|
pkgs.coreutils
|
||||||
|
pkgs.nix
|
||||||
|
];
|
||||||
|
closureInfo = pkgs.closureInfo {
|
||||||
|
rootPaths = [
|
||||||
|
templateDerivation
|
||||||
pkgs.bash
|
pkgs.bash
|
||||||
pkgs.coreutils
|
pkgs.coreutils
|
||||||
pkgs.nix
|
pkgs.jq.dev
|
||||||
|
pkgs.stdenv
|
||||||
|
pkgs.stdenvNoCC
|
||||||
|
pkgs.openssh
|
||||||
|
pkgs.shellcheck-minimal
|
||||||
|
pkgs.mkpasswd
|
||||||
|
pkgs.xkcdpass
|
||||||
|
pkgs.pass
|
||||||
|
nix-select
|
||||||
];
|
];
|
||||||
closureInfo = pkgs.closureInfo {
|
};
|
||||||
rootPaths = [
|
}
|
||||||
templateDerivation
|
''
|
||||||
pkgs.bash
|
set -euo pipefail
|
||||||
pkgs.coreutils
|
cp -r ${sourceWithTests} ./src
|
||||||
pkgs.jq.dev
|
chmod +w -R ./src
|
||||||
pkgs.stdenv
|
cd ./src
|
||||||
pkgs.stdenvNoCC
|
|
||||||
pkgs.openssh
|
|
||||||
pkgs.shellcheck-minimal
|
|
||||||
pkgs.mkpasswd
|
|
||||||
pkgs.xkcdpass
|
|
||||||
pkgs.pass
|
|
||||||
nix-select
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
''
|
|
||||||
set -euo pipefail
|
|
||||||
cp -r ${sourceWithTests} ./src
|
|
||||||
chmod +w -R ./src
|
|
||||||
cd ./src
|
|
||||||
|
|
||||||
${setupNixInNix}
|
${setupNixInNix}
|
||||||
|
|
||||||
export CLAN_CORE_PATH=${clan-core-path}
|
export CLAN_CORE_PATH=${clan-core-path}
|
||||||
export PYTHONWARNINGS=error
|
export PYTHONWARNINGS=error
|
||||||
|
|
||||||
# used for tests without flakes
|
# used for tests without flakes
|
||||||
export NIXPKGS=${nixpkgs}
|
export NIXPKGS=${nixpkgs}
|
||||||
export NIX_SELECT=${nix-select}
|
export NIX_SELECT=${nix-select}
|
||||||
|
|
||||||
# limit build cores to 16
|
# limit build cores to 16
|
||||||
jobs="$((NIX_BUILD_CORES>16 ? 16 : NIX_BUILD_CORES))"
|
jobs="$((NIX_BUILD_CORES>16 ? 16 : NIX_BUILD_CORES))"
|
||||||
|
|
||||||
# Run all tests with core marker
|
# Run all tests with core marker
|
||||||
python -m pytest -m "not impure and with_core" -n $jobs ./clan_cli ./clan_lib
|
python -m pytest -m "not impure and with_core" -n $jobs ./clan_cli ./clan_lib
|
||||||
touch $out
|
touch $out
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
passthru.nixpkgs = nixpkgs';
|
passthru.nixpkgs = nixpkgs';
|
||||||
passthru.devshellPyDeps = ps: (pyTestDeps ps) ++ (pyDeps ps) ++ (devDeps ps);
|
passthru.devshellPyDeps = ps: (pyTestDeps ps) ++ (pyDeps ps) ++ (devDeps ps);
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ mkShell {
|
|||||||
))
|
))
|
||||||
ruff
|
ruff
|
||||||
nix-unit
|
nix-unit
|
||||||
] ++ clan-cli.runtimeDependencies;
|
]
|
||||||
|
++ clan-cli.runtimeDependencies;
|
||||||
|
|
||||||
inputsFrom = [ self'.devShells.default ];
|
inputsFrom = [ self'.devShells.default ];
|
||||||
|
|
||||||
|
|||||||
@@ -34,18 +34,17 @@ let
|
|||||||
};
|
};
|
||||||
|
|
||||||
# Dependencies that are directly used in the project but nor from internal python packages
|
# Dependencies that are directly used in the project but nor from internal python packages
|
||||||
externalPythonDeps =
|
externalPythonDeps = [
|
||||||
[
|
pygobject3
|
||||||
pygobject3
|
pygobject-stubs
|
||||||
pygobject-stubs
|
gtk4
|
||||||
gtk4
|
libadwaita
|
||||||
libadwaita
|
adwaita-icon-theme
|
||||||
adwaita-icon-theme
|
]
|
||||||
]
|
++ clan-cli.propagatedBuildInputs
|
||||||
++ clan-cli.propagatedBuildInputs
|
++ lib.optionals (!stdenv.isDarwin) [
|
||||||
++ lib.optionals (!stdenv.isDarwin) [
|
webkitgtk_6_0
|
||||||
webkitgtk_6_0
|
];
|
||||||
];
|
|
||||||
|
|
||||||
# Deps including python packages from the local project
|
# Deps including python packages from the local project
|
||||||
allPythonDeps = [ (python.pkgs.toPythonModule clan-cli) ] ++ externalPythonDeps;
|
allPythonDeps = [ (python.pkgs.toPythonModule clan-cli) ] ++ externalPythonDeps;
|
||||||
|
|||||||
@@ -27,19 +27,18 @@ in
|
|||||||
mkShell {
|
mkShell {
|
||||||
inherit (clan-vm-manager) nativeBuildInputs;
|
inherit (clan-vm-manager) nativeBuildInputs;
|
||||||
name = "clan-vm-manager";
|
name = "clan-vm-manager";
|
||||||
buildInputs =
|
buildInputs = [
|
||||||
[
|
ruff
|
||||||
ruff
|
gtk4.dev # has the demo called 'gtk4-widget-factory'
|
||||||
gtk4.dev # has the demo called 'gtk4-widget-factory'
|
libadwaita.devdoc # has the demo called 'adwaita-1-demo'
|
||||||
libadwaita.devdoc # has the demo called 'adwaita-1-demo'
|
]
|
||||||
]
|
++ devshellTestDeps
|
||||||
++ devshellTestDeps
|
|
||||||
|
|
||||||
# Dependencies for testing for linux hosts
|
# Dependencies for testing for linux hosts
|
||||||
++ (lib.optionals stdenv.isLinux [
|
++ (lib.optionals stdenv.isLinux [
|
||||||
xdg-utils # install desktop files
|
xdg-utils # install desktop files
|
||||||
desktop-file-utils # verify desktop files
|
desktop-file-utils # verify desktop files
|
||||||
]);
|
]);
|
||||||
|
|
||||||
shellHook = ''
|
shellHook = ''
|
||||||
export GIT_ROOT=$(git rev-parse --show-toplevel)
|
export GIT_ROOT=$(git rev-parse --show-toplevel)
|
||||||
|
|||||||
Reference in New Issue
Block a user