128 lines
4.3 KiB
Nix
128 lines
4.3 KiB
Nix
{ config, lib, pkgs, ... }:
|
||
|
||
let
|
||
cfg = config.nixosWorkstations.homedUser;
|
||
|
||
# LAB : le mot de passe initial est volontairement un mot de passe par défaut
|
||
# connu. Il ne constitue pas un secret durable : l’utilisateur doit le remplacer
|
||
# lors de sa première session. Pour une future version production, ce credential
|
||
# devra venir d'une source chiffrée/externe et non du Nix store.
|
||
initialPasswordCredential = pkgs.writeText
|
||
"nixos-workstations-${cfg.user}-initial-password"
|
||
cfg.initialPassword;
|
||
|
||
provisionService = "nixos-workstations-provision-${cfg.user}";
|
||
in
|
||
{
|
||
options.nixosWorkstations.homedUser = {
|
||
enable = lib.mkEnableOption "précréation d'un utilisateur systemd-homed chiffré";
|
||
|
||
user = lib.mkOption {
|
||
type = lib.types.str;
|
||
description = "Compte systemd-homed à préparer automatiquement.";
|
||
};
|
||
|
||
realName = lib.mkOption {
|
||
type = lib.types.str;
|
||
description = "Nom complet de l'utilisateur systemd-homed.";
|
||
};
|
||
|
||
initialPassword = lib.mkOption {
|
||
type = lib.types.str;
|
||
description = "Mot de passe temporaire utilisé uniquement pour le premier accès LAB.";
|
||
};
|
||
|
||
diskSize = lib.mkOption {
|
||
type = lib.types.str;
|
||
description = "Taille initiale du conteneur LUKS2 de l’espace personnel.";
|
||
};
|
||
};
|
||
|
||
config = lib.mkIf cfg.enable {
|
||
services.homed.enable = true;
|
||
|
||
# Les comptes nixbld NixOS ont des UID > 1000. Nous n'utilisons pas le
|
||
# workflow first-boot de homed : les comptes sont créés explicitement par
|
||
# le service ci-dessous.
|
||
services.userdbd.silenceHighSystemUsers = true;
|
||
|
||
# SDDM doit accepter la plage d'UID systemd-homed et son greeter doit
|
||
# charger libnss_systemd directement. Cette configuration a été validée en
|
||
# LAB : sans ce LD_LIBRARY_PATH, getpwent() n’énumère pas les comptes homed sous NixOS.
|
||
services.displayManager.sddm.settings = {
|
||
Users = {
|
||
MinimumUid = 1000;
|
||
MaximumUid = 60513;
|
||
};
|
||
|
||
General = {
|
||
GreeterEnvironment =
|
||
"QT_WAYLAND_SHELL_INTEGRATION=layer-shell,LD_LIBRARY_PATH=${config.system.nssModules.path}";
|
||
};
|
||
};
|
||
|
||
# Précréation automatique de l’utilisateur prévu pour le poste. localadm ne lance qu’un
|
||
# nixos-rebuild switch : ce service est démarré automatiquement et ne fait
|
||
# rien si le compte homed existe déjà.
|
||
#
|
||
# RemainAfterExit est volontairement conservé : SDDM dépend de la réussite
|
||
# de ce service au démarrage. Le script lui-même reste idempotent.
|
||
systemd.services.${provisionService} = {
|
||
description = "Prépare le compte systemd-homed ${cfg.user}";
|
||
wantedBy = [ "multi-user.target" ];
|
||
before = [ "display-manager.service" ];
|
||
after = [ "systemd-homed.service" ];
|
||
requires = [ "systemd-homed.service" ];
|
||
|
||
serviceConfig = {
|
||
Type = "oneshot";
|
||
RemainAfterExit = true;
|
||
LoadCredential = [
|
||
"home.new-password:${initialPasswordCredential}"
|
||
];
|
||
};
|
||
|
||
path = [
|
||
pkgs.coreutils
|
||
pkgs.getent
|
||
pkgs.systemd
|
||
];
|
||
|
||
script = ''
|
||
set -eu
|
||
|
||
user=${lib.escapeShellArg cfg.user}
|
||
|
||
if ${pkgs.systemd}/bin/homectl inspect "$user" >/dev/null 2>&1; then
|
||
echo "Compte homed $user déjà présent : aucune modification."
|
||
exit 0
|
||
fi
|
||
|
||
# Refuser une collision avec un compte UNIX classique du même nom.
|
||
if ${pkgs.getent}/bin/getent passwd "$user" >/dev/null 2>&1; then
|
||
echo "ERREUR : $user existe déjà mais n'est pas un compte systemd-homed." >&2
|
||
exit 1
|
||
fi
|
||
|
||
echo "Création du compte systemd-homed $user et de son home LUKS2..."
|
||
|
||
${pkgs.systemd}/bin/homectl --no-ask-password create "$user" \
|
||
--real-name=${lib.escapeShellArg cfg.realName} \
|
||
--storage=luks \
|
||
--fs-type=ext4 \
|
||
--disk-size=${lib.escapeShellArg cfg.diskSize} \
|
||
--access-mode=0700 \
|
||
--shell=/run/current-system/sw/bin/bash \
|
||
--password-change-now=no \
|
||
--recovery-key=no
|
||
'';
|
||
};
|
||
|
||
# Au boot, le compte doit exister avant le lancement du greeter SDDM.
|
||
systemd.services.display-manager = {
|
||
after = [ "${provisionService}.service" ];
|
||
requires = [ "${provisionService}.service" ];
|
||
};
|
||
};
|
||
}
|