{ pkgs, unstable, inputs, ... }: let tome = pkgs.callPackage ../../pkgs/tome.nix { src = inputs.tome; }; # SUDO_ASKPASS helper: renders sudo's password prompt in the quickshell # shell (HyprChrome/Widgets/Askpass) instead of on the terminal. # # sudo does NOT speak polkit — it is setuid + PAM reading the tty, and no # sudoers option bridges the two — so this is the askpass mechanism, a # separate path that happens to reuse the polkit dialog's look. `run0` is the # polkit-native alternative if you want the agent itself. # # A package rather than a file in dotfiles/quickshell because SUDO_ASKPASS # must point at something EXECUTABLE, and xdg.configFile copies keep their # store mode — which is why open_launcher.sh has to be invoked as # `bash ` rather than run directly. # # The secret comes back over a 0600 fifo, never in argv or the environment, # so it is not visible in /proc to anything. Cancelling closes the fifo # without writing: `cat` reads nothing, this exits non-zero, and sudo aborts # instead of burning a retry on an empty password. qs-askpass = pkgs.writeShellApplication { name = "qs-askpass"; runtimeInputs = [ pkgs.quickshell pkgs.coreutils ]; text = '' runtime="''${XDG_RUNTIME_DIR:-/run/user/$(id -u)}" fifo="$(mktemp -u "$runtime/qs-askpass.XXXXXXXX")" mkfifo -m 600 "$fifo" trap 'rm -f "$fifo"' EXIT # Returns immediately; the dialog is asynchronous and we block on the # fifo, not on the IPC call. if ! qs ipc call askpass prompt "''${1:-Password:}" "$fifo" >/dev/null 2>&1; then echo "qs-askpass: quickshell is not running or has no askpass handler" >&2 exit 1 fi # Bounded, so a prompt nobody answers fails instead of wedging sudo for # good. On timeout take the dialog down too, or it would sit there with # nothing listening. if ! secret="$(timeout 120 cat "$fifo")"; then qs ipc call askpass cancel >/dev/null 2>&1 || true echo "qs-askpass: timed out waiting for the prompt" >&2 exit 1 fi [ -n "$secret" ] || exit 1 printf '%s\n' "$secret" ''; }; in { # home.stateVersion, programs.home-manager.enable, programs.zsh.enable all # come from home/common.nix (shared across every host) via # configuration.nix's home-manager.users.darman.imports. imports = [ ./home/hyprland.nix ./home/theme.nix ]; home.keyboard.layout = "de"; programs.git = { enable = true; settings = { user.name = "Erik Simon"; user.email = "mail@erik-s.dev"; }; }; # direnv + nix-direnv: lets per-repo devShells (e.g. ~/Data/Dev/repos/Tome's # flake.nix) auto-load in the shell AND in Rider via its "direnv # integration" plugin, instead of every dev repo needing its own # jetbrains-toolbox SDK wiring by hand. programs.direnv = { enable = true; nix-direnv.enable = true; }; # Rootless podman: containers run as darman, not root. services/containers.nix # gives us the `docker` CLI shim (dockerCompat), but compose v2 is a separate # binary and talks to a socket rather than the CLI — the NixOS podman module # enables the *user* socket (systemd.user.sockets.podman), so point compose at # it instead of the root /var/run/docker.sock. home.sessionVariables.DOCKER_HOST = "unix:///run/user/1000/podman/podman.sock"; # Only sets WHICH helper sudo uses; it still only calls it when asked with # `sudo -A` (or when there is no tty at all). Plain `sudo` keeps prompting on # the terminal, deliberately: aliasing it wholesale would break every sudo in # a TTY or over ssh, where there is no shell to draw the dialog. home.sessionVariables.SUDO_ASKPASS = "${qs-askpass}/bin/qs-askpass"; xdg.userDirs = { enable = true; }; xdg.mime.enable = true; xdg.configFile."quickshell".source = ../../dotfiles/quickshell; xdg.configFile."scripts".source = ../../dotfiles/scripts; home.packages = [ (pkgs.writeTextDir "share/mime/packages/application-x-ms-sln.xml" (builtins.readFile ../../dotfiles/mime/application-x-ms-sln.xml)) unstable.claude-code unstable.codex pkgs.opencode pkgs.quickshell qs-askpass pkgs.github-cli pkgs.tea pkgs.docker-compose pkgs.hyprcursor pkgs.papirus-icon-theme ]; xdg.desktopEntries.btop = { name = "btop++"; genericName = "System Monitor"; exec = "btop"; icon = "btop"; terminal = true; categories = [ "System" "Monitor" ]; noDisplay = true; }; programs.alacritty = { enable = true; settings = { env.SHELL = "${pkgs.zsh}/bin/zsh"; terminal.shell = { program = "${pkgs.zsh}/bin/zsh"; args = [ "-l" ]; }; window = { padding = { x = 10; y = 10; }; opacity = 0.8; }; font.normal = { family = "DepartureMono Nerd Font"; style = "Regular"; }; colors.primary = { background = "#0F1012"; foreground = "#ffd369"; }; # hints.enabled = [ # { # hyperlinks = true; # regex = "(ipfs:|ipns:|magnet:|mailto:|gemini://|gopher://|https://|http://|news:|file:|git://|ssh:|ftp://)[^\\u0000-\\u001F\\u007F-\\u009F<>\"\\s{-}\\^⟨⟩`]+"; # command = "xdg-open"; # mouse.enabled = true; # } # ]; keyboard.bindings = [ # ESC + CR: nix has no literal escape for the ESC control char, so # fromJSON decodes it from the JSON unicode escape below. { key = "Return"; mods = "Shift"; chars = builtins.fromJSON ''"\u001B\r"''; } ]; }; }; }