commit cbbc749ce296ab9dc4e0020a6faa95d6c4959016 from: ale date: Sat Sep 19 21:09:53 2026 UTC Carga secretos locales desde ~/.config/zsh/secrets.zsh commit - 4cd15b53068761f7ea875c81f706a11b42d1620b commit + cbbc749ce296ab9dc4e0020a6faa95d6c4959016 blob - 28c92d6ad03327f70c9edfa43a2b76184c0da98d blob + b19c762c63942d472a4416a5f12c401687b3d73c --- home/ale/home.nix +++ home/ale/home.nix @@ -342,6 +342,11 @@ in # README, sin necesitar ningún mkOrder manual). syntaxHighlighting.enable = true; initContent = lib.mkMerge [ + '' + # Secrets locales (API keys, tokens): archivo fuera de /nixdots para + # no versionar ni exponer credenciales en el Nix store. + [ -f "$HOME/.config/zsh/secrets.zsh" ] && source "$HOME/.config/zsh/secrets.zsh" + '' # zsh-autosuggestions -- sourceado a mano (NO con la opción nativa # programs.zsh.autosuggestion.enable) porque esa opción fija su propio # mkOrder en 700, es decir ANTES del compinit de oh-my-zsh (800) y @@ -784,6 +789,8 @@ in zed-editor # editor -- paquete directo de nixpkgs (el binario se llama # `zeditor`, no `zed`; el .desktop instalado sí queda como "Zed" en el # launcher) + tor-browser # paquete directo de nixpkgs -- sin módulo declarativo + # propio como zen-browser (programs.zen-browser) ]; # --- LibrePods: autostart en segundo plano --- blob - /dev/null blob + 1ee66264286f65a298ad85527e80247978f20e7d (mode 644) --- /dev/null +++ modules/dms-greeter-fixed.nix @@ -0,0 +1,396 @@ +{ + config, + lib, + pkgs, + ... +}: +let + inherit (lib) + types + mkEnableOption + mkOption + mkIf + mkDefault + literalExpression + getExe + makeBinPath + optionalString + escapeShellArgs + ; + + cfg = config.services.displayManager.dms-greeter; + cfgDms = config.programs.dms-shell; + cfgAutoLogin = config.services.displayManager.autoLogin; + sessionData = config.services.displayManager.sessionData; + + # Miracle WM is nested under `programs.wayland.miracle-wm` unlike the rest + compositorOption = + if cfg.compositor.name == "miracle-wm" then "wayland.miracle-wm" else "${cfg.compositor.name}"; + cacheDir = "/var/lib/dms-greeter"; + + # Not all compositor packages match the name they use and Miracle does not have a package option + compositorPkg = + if cfg.compositor.name == "miracle-wm" then + pkgs.miracle-wm + else + lib.attrByPath [ + "programs" + cfg.compositor.name + "package" + ] null config; + + # PARCHE (ale, 2026-09-15, ver NOTES.md): el módulo upstream + # (nixos/modules/services/display-managers/dms-greeter.nix) invoca + # "${cfg.package}/bin/dms-greeter", asumiendo el layout de dms-shell >=1.6 + # (donde el CLI Go `dms` embebe los assets de quickshell y ya no expone un + # bin/dms-greeter suelto -- confirmado: ni siquiera pkgs.dms-shell 1.6.1 de + # nixpkgs lo genera, ver `cmd/` upstream: solo dms y dankinstall). Este repo + # pinea dank-material-shell a v1.5.3 a propósito (flake.nix), cuyo layout + # SÍ instala el launcher como archivo suelto en + # share/quickshell/dms/Modules/Greetd/assets/dms-greeter, junto con el flag + # -p que le indica qué config de quickshell cargar (sin esto, busca la + # config nombrada "dms-greeter" en las rutas de búsqueda de quickshell en + # vez de la ruta absoluta del paquete). greetd fallaba en boot-loop + # ("No existe el fichero o el directorio") en cuanto nixpkgs actualizó el + # módulo (nix flake update, sep-2026) sin que este repo hubiera cambiado de + # versión de dms-shell. Bug real de nixpkgs, no arreglado río arriba a esta + # fecha (nixpkgs#546897 es uno distinto, sobre configHome). Todo lo demás + # de este archivo es una copia literal del módulo upstream -- si algún día + # se actualiza dank-material-shell a >=1.6 con un launcher equivalente, + # basta con quitar este archivo + el disabledModules en desktop.nix. + greeterScript = pkgs.writeShellScriptBin "dms-greeter-start" '' + export PATH=$PATH:${ + makeBinPath [ + cfg.quickshell.package + compositorPkg + pkgs.glib # provides gdbus, used by the fprintd hardware probe and portal reads + ] + } + ${ + escapeShellArgs ( + [ + "${cfg.package}/share/quickshell/dms/Modules/Greetd/assets/dms-greeter" + "--cache-dir" + cacheDir + "--command" + cfg.compositor.name + "-p" + "${cfg.package}/share/quickshell/dms" + ] + ++ lib.optionals (cfg.compositor.customConfig != "") [ + "-C" + "${pkgs.writeText "dmsgreeter-compositor-config" cfg.compositor.customConfig}" + ] + ) + } ${optionalString cfg.logs.save "> ${cfg.logs.path} 2>&1"} + ''; + + autoLoginCommand = + pkgs.runCommand "dms-greeter-autologin-command" + { + nativeBuildInputs = [ + pkgs.gnugrep + pkgs.coreutils + ]; + } + '' + set -euo pipefail + + session="${sessionData.autologinSession}" + desktops="${sessionData.desktops}" + + for sessionFile in \ + "$desktops/share/wayland-sessions/$session.desktop" \ + "$desktops/share/xsessions/$session.desktop" + do + if [ -f "$sessionFile" ]; then + command="$(grep -m1 '^Exec=' "$sessionFile" | cut -d= -f2- || true)" + + if [ -n "$command" ]; then + printf '%s\n' "$command" > "$out" + exit 0 + fi + fi + done + + echo "dms-greeter autologin: could not resolve Exec for session '$session'" >&2 + exit 1 + ''; + + jq = getExe pkgs.jq; + + configFilesFromHome = + if cfg.configHome != null then + [ + "${cfg.configHome}/.config/DankMaterialShell/settings.json" + "${cfg.configHome}/.local/state/DankMaterialShell/session.json" + "${cfg.configHome}/.cache/DankMaterialShell/dms-colors.json" + ] + else + [ ]; +in +{ + options.services.displayManager.dms-greeter = { + enable = mkEnableOption "DankMaterialShell greeter"; + + package = lib.mkPackageOption pkgs "dms-greeter" { }; + + compositor = { + name = mkOption { + type = types.enum [ + "niri" + "hyprland" + "sway" + "mangowc" + "miracle-wm" + "labwc" + ]; + example = "niri"; + description = '' + The Wayland compositor to run the greeter in. + + The specified compositor must be enabled via its corresponding + `programs..enable` option. + + Supported compositors: + - niri: A scrollable-tiling Wayland compositor + - hyprland: A dynamic tiling Wayland compositor + - sway: An i3-compatible Wayland compositor + - mango: A dwm-inspired Wayland compositor with modern config options and multiple layouts + - miracle-wm: A keyboard-driven Wayland compositor with smooth animations and extensibility + - labwc: Lightweight stacking Wayland compositor inspired by Openbox + ''; + }; + + customConfig = mkOption { + type = types.lines; + default = ""; + example = '' + # Niri example + input { + keyboard { + xkb { + layout "us" + } + } + } + ''; + description = '' + Custom compositor configuration to use for the greeter session. + + This configuration is written to a file and passed to the compositor + when launching the greeter. The format and available options depend + on the selected compositor. + + Leave empty to use the system's default compositor configuration. + ''; + }; + }; + + configFiles = mkOption { + type = types.listOf types.path; + default = [ ]; + example = literalExpression '' + [ + "/home/user/.config/DankMaterialShell/settings.json" + "/home/user/.local/state/DankMaterialShell/session.json" + ] + ''; + description = '' + List of DankMaterialShell configuration files to copy into the greeter + data directory at `/var/lib/dms-greeter`. + + This is useful for preserving user preferences like wallpapers, themes, + and other settings in the greeter screen. + + ::: {.tip} + Use {option}`configHome` instead if your configuration files are in + standard XDG locations. + ::: + ''; + }; + + configHome = mkOption { + type = types.nullOr types.str; + default = null; + example = "/home/alice"; + description = '' + Path to a user's home directory from which to copy DankMaterialShell + configuration files. + + When set, the following files will be automatically copied to the greeter: + - `~/.config/DankMaterialShell/settings.json` + - `~/.local/state/DankMaterialShell/session.json` + - `~/.cache/DankMaterialShell/dms-colors.json` + + If your configuration files are in non-standard locations, use the + {option}`configFiles` option instead. + ''; + }; + + quickshell = { + package = mkOption { + type = types.package; + default = if cfgDms.enable then cfgDms.quickshell.package else pkgs.quickshell; + defaultText = literalExpression '' + if config.programs.dms-shell.enable + then config.programs.dms-shell.quickshell.package + else pkgs.quickshell; + ''; + description = '' + The Quickshell package to use for the greeter. + + Defaults to the quickshell package from `programs.dms-shell` if it is enabled, + otherwise defaults to `pkgs.quickshell`. + ''; + }; + }; + + logs = { + save = mkEnableOption "saving logs from the DMS greeter to a file"; + + path = mkOption { + type = types.path; + default = "/tmp/dms-greeter.log"; + example = "/var/log/dms-greeter.log"; + description = '' + File path where DMS greeter logs will be saved. + + This is useful for debugging greeter issues. Logs will include + output from both the greeter and the compositor. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + { + assertion = + # Assemble the full attribute structure because miracle-wm is not nested in the same location as the others + lib.attrByPath ( + [ "programs" ] ++ lib.splitString "." compositorOption ++ [ "enable" ] + ) false config; + message = '' + DankMaterialShell greeter: The compositor "${cfg.compositor.name}" is not enabled. + + Please enable the compositor via: + programs.${compositorOption}.enable = true; + ''; + } + { + assertion = cfgAutoLogin.enable -> sessionData.autologinSession != null; + message = '' + dms-greeter auto-login requires services.displayManager.defaultSession to be set, + or at least one session in services.displayManager.sessionPackages. + ''; + } + ]; + + services.greetd = { + enable = mkDefault true; + settings = { + default_session = { + user = "dms-greeter"; + command = getExe greeterScript; + }; + initial_session = mkIf (cfgAutoLogin.enable && (cfgAutoLogin.user != null)) { + inherit (cfgAutoLogin) user; + command = ''${getExe pkgs.bash} -lc "${config.systemd.package}/bin/systemd-cat $(<${autoLoginCommand})"''; + }; + }; + }; + + environment.systemPackages = [ cfg.package ]; + + fonts.packages = with pkgs; [ + fira-code + inter + material-symbols + ]; + + systemd.tmpfiles.settings."10-dms-greeter".${cacheDir}.d = { + user = "dms-greeter"; + group = "dms-greeter"; + mode = "0750"; + }; + + systemd.services.greetd.preStart = + let + allConfigFiles = cfg.configFiles ++ configFilesFromHome; + in + '' + cd ${cacheDir} + ${lib.concatStringsSep "\n" ( + lib.map (f: '' + if [ -f "${f}" ]; then + cp "${f}" . + fi + '') allConfigFiles + )} + + if [ -f session.json ]; then + copy_wallpaper() { + local path=$(${jq} -r ".$1 // empty" session.json) + if [ -f "$path" ]; then + cp "$path" "$2" + ${jq} ".$1 = \"${cacheDir}/$2\"" session.json > session.tmp + mv session.tmp session.json + fi + } + + copy_monitor_wallpapers() { + ${jq} -r ".$1 // {} | to_entries[] | .key + \":\" + .value" session.json 2>/dev/null | while IFS=: read monitor path; do + local dest="$2-$(echo "$monitor" | tr -c '[:alnum:]' '-')" + if [ -f "$path" ]; then + cp "$path" "$dest" + ${jq} --arg m "$monitor" --arg p "${cacheDir}/$dest" ".$1[\$m] = \$p" session.json > session.tmp + mv session.tmp session.json + fi + done + } + + copy_wallpaper "wallpaperPath" "wallpaper" + copy_wallpaper "wallpaperPathLight" "wallpaper-light" + copy_wallpaper "wallpaperPathDark" "wallpaper-dark" + copy_monitor_wallpapers "monitorWallpapers" "wallpaper-monitor" + copy_monitor_wallpapers "monitorWallpapersLight" "wallpaper-monitor-light" + copy_monitor_wallpapers "monitorWallpapersDark" "wallpaper-monitor-dark" + fi + + if [ -f settings.json ]; then + theme_file="$(${jq} -r '.customThemeFile // empty' settings.json)" + if [ -f "$theme_file" ] && [ -r "$theme_file" ]; then + cp "$theme_file" custom-theme.json + mv settings.json settings.orig.json + ${jq} '.customThemeFile = "${cacheDir}/custom-theme.json"' settings.orig.json > settings.json + fi + fi + + mv dms-colors.json colors.json || : + chown dms-greeter:dms-greeter * || : + ''; + + services.displayManager.dms-greeter.configFiles = lib.mkIf ( + cfg.configHome != null + ) configFilesFromHome; + + users.groups.dms-greeter = { }; + users.users.dms-greeter = { + description = "DankMaterialShell greeter user"; + isSystemUser = true; + home = cacheDir; + homeMode = "0750"; + createHome = true; + group = "dms-greeter"; + extraGroups = [ "video" ]; + }; + + security.pam.services.dms-greeter = { }; + + hardware.graphics.enable = mkDefault true; + services.libinput.enable = mkDefault true; + }; + + meta.teams = [ lib.teams.danklinux ]; +}