Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 8 additions & 16 deletions configuration.nix
Original file line number Diff line number Diff line change
Expand Up @@ -70,21 +70,15 @@

fwupd.enable = true;

# greetd runs a throwaway Hyprland+Quickshell "greeter" session (see
# dotfiles/hypr/greeter.lua and dotfiles/quickshell/greeter) that
# authenticates over greetd's own IPC protocol, then hands off to the
# user's normal session below. The greeter runs as its own system
# user (created automatically by this module), so its files are
# published system-wide via environment.etc below rather than
# home-manager.
# agreety, greetd's own bundled text greeter, replaces a custom
# Hyprland+Quickshell greeter session while Hyprland itself is still
# being brought up on real hardware. On successful login it hands off
# to the user's Hyprland session below via start-hyprland, the same
# target the custom greeter used.
greetd = {
enable = true;
settings.default_session = {
# Preserve compositor and greeter output after their runtime directory
# disappears. Read it with: journalctl -b -t greetd-greeter
command = "${pkgs.systemd}/bin/systemd-cat --identifier=greetd-greeter -- start-hyprland -- --config /etc/greetd/hyprland.lua";
user = "greeter";
};
useTextGreeter = true;
settings.default_session.command = "${pkgs.greetd}/bin/agreety --cmd start-hyprland";
};

udisks2.enable = true;
Expand Down Expand Up @@ -142,10 +136,8 @@
pkgs.quickshell
];
etc = {
# Also read directly by the lock screen; see dotfiles/quickshell/lockscreen.
"wallpaper.jpg".source = ./wallpapers/weic2216b.jpg;
"greetd/hyprland.lua".source = ./dotfiles/hypr/greeter.lua;
# Keep the greeter and its ../shared QML import in one Nix store tree.
"greetd/quickshell".source = ./dotfiles/quickshell;
};
};

Expand Down
32 changes: 14 additions & 18 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ Home Manager owns:
| --- | --- |
| Hyprland and Quickshell files | Installs the user's desktop files |
| Quickshell lock service | Gives every lock request one idempotent service |
| KeePassXC | Starts automatically and provides the Secret Service API |
| KeePassXC | Starts automatically; can provide the Secret Service API once enabled in its settings |
| Ghostty | Provides the configured terminal |
| hypridle | Locks after 5 minutes and blanks displays 30 seconds later |

Expand Down Expand Up @@ -259,27 +259,24 @@ The graphical path is:
flowchart TD
boot["boot"] --> unlock["Plymouth and LUKS unlock"]
unlock --> greetd["greetd"]
greetd --> greeter["temporary Hyprland greeter session"]
greeter --> loginui["Quickshell login UI"]
loginui --> session["normal Hyprland user session"]
greetd --> agreety["agreety text login"]
agreety --> session["normal Hyprland user session"]
session --> bar["Quickshell bar and wallpaper"]
session --> terminal["Ghostty terminal"]
session --> keepassxc["KeePassXC Secret Service"]
session --> hypridle["hypridle"] --> lock["Quickshell lock service"]
```

System-owned greeter files are installed by `configuration.nix` under
`/etc/greetd`. The greeter and its shared QML components remain in one store
tree so relative imports work after Nix resolves `/etc` symlinks. User-owned
session files are installed by Home Manager from `home.nix`.
greetd starts agreety, its own bundled text greeter, directly on the console;
neither needs any custom configuration or QML. Session files for the
Hyprland session itself are installed by Home Manager from `home.nix`.

Both transitions into Hyprland use `start-hyprland`, Hyprland's supported
launcher. It prepares the session environment before starting the compositor;
the greeter additionally passes its small system-owned configuration file.
The greeter's compositor and Quickshell output is retained in the system
journal under the `greetd-greeter` identifier. A failed Quickshell startup
leaves its compositor in place instead of repeatedly restarting it; a
successful authenticated handoff exits it normally.
On successful login, greetd starts the user's session with `start-hyprland`,
Hyprland's supported launcher, which prepares the session environment before
starting the compositor.

agreety stands in for a planned Hyprland+Quickshell greeter, held back until
Hyprland itself has had real-hardware testing (see `docs/recovery.md`).

The lock screen is a systemd user service. Starting an already-running service
is safe, so keyboard, idle, and suspend events can all request a lock without a
Expand Down Expand Up @@ -314,8 +311,8 @@ need a real Wayland compositor and its protocols, while an offscreen Qt process
has no window-system backend. Starting a nested compositor merely to make that
test pass would add infrastructure without reproducing the real login or lock
environment. The native system build already proves that the configured
Quickshell package can be produced; actual bar, greeter, and lock-screen
behavior remains a hardware acceptance test.
Quickshell package can be produced; actual bar and lock-screen behavior
remains a hardware acceptance test.

Another separate job scans the complete Git history for secrets.

Expand Down Expand Up @@ -356,7 +353,6 @@ and full Git history.
| `modules/boot/` | Shared Secure Boot, measured boot, and graphical splash |
| `dotfiles/hypr/` | Hyprland startup and key bindings |
| `dotfiles/quickshell/bar/` | User bar and wallpaper |
| `dotfiles/quickshell/greeter/` | Login screen |
| `dotfiles/quickshell/lockscreen/` | Lock screen |
| `dotfiles/quickshell/shared/` | Reused login and lock components |
| `wallpapers/` | Images installed by the shared system configuration |
Expand Down
19 changes: 8 additions & 11 deletions docs/recovery.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,13 @@

- Use Ctrl+Alt+F3 (or another free VT) if graphical login fails, and log in as
`igor` with the password chosen during installation.
- Greeter runtime directories disappear when a failed greeter session exits,
so `/run/user/<greeter-uid>/hypr/.../hyprland.log` is not a durable log.
Read the retained logs from that VT instead:
- agreety runs directly on the console, so its login prompt and any errors
are visible right there on tty1. greetd's own session decisions (including
failed handoffs to `start-hyprland`) are in the system journal:

```sh
sudo journalctl -b -t greetd-greeter
sudo journalctl -b -u greetd
```

The first command contains Hyprland and Quickshell output; the second
contains greetd's session decisions.
- Select an older NixOS generation from the boot menu after a broken rebuild.
- Press Escape while Plymouth is running to reveal boot details or a text
prompt; press Escape again to return to the graphical splash.
Expand Down Expand Up @@ -49,10 +45,11 @@ with `cryptsetup open --test-passphrase`.

- The committed hardware module is a generic, architecture-correct
placeholder until the first installation commits the real scan.
- The custom Quickshell greeter and lock screen need real-hardware testing.
- The greeter currently targets one interactive surface; multi-monitor
presentation has not been completed.
- QML authentication assumes the default password-only PAM conversation.
- The Hyprland user session and Quickshell lock screen need real-hardware
testing. Login uses agreety, greetd's own bundled text greeter, until a
Hyprland+Quickshell greeter is worth reintroducing.
- Lock screen authentication assumes the default password-only PAM
conversation.
- Audio, a graphical polkit agent, notifications, and complete portal
integration are follow-up workstation work.

Expand Down
20 changes: 11 additions & 9 deletions home.nix
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,6 @@
};

# Hyprland session and Quickshell shells (bar, lock screen, launcher).
# The greeter has its own copy of Quickshell's config, published via
# environment.etc in configuration.nix instead of home-manager, since
# it runs as a separate system user with no home directory here.
file = {
".config/hypr/hyprland.lua".source = ./dotfiles/hypr/hyprland.lua;
".config/quickshell/shell.qml".source = ./dotfiles/quickshell/bar/shell.qml;
Expand All @@ -69,15 +66,20 @@
};

programs = {
# Secret Service integration: lets applications, including
# NetworkManager, store and retrieve secrets through KeePassXC instead
# of gnome-keyring or KWallet. See README.md.
# Stands in for gnome-keyring or KWallet as the Secret Service provider,
# for applications that call that D-Bus API themselves. NetworkManager
# does not: it reaches a Secret Service only through a NetworkManager
# secret agent, which this session deliberately does not run, so Wi-Fi
# passphrases stay in /etc/NetworkManager/system-connections on the
# encrypted root rather than in a vault.
#
# Secret Service is left as a first-run GUI toggle instead of a declared
# setting: home-manager links keepassxc.ini read-only into the store
# whenever `settings` is non-empty, which would also stop KeePassXC from
# recording which database to reopen on autostart.
keepassxc = {
enable = true;
autostart = true;
settings = {
FdoSecrets.Enabled = true;
};
};

ghostty = {
Expand Down