Move login state, authentication, discovery, input, rendering, and tests into focused TUI modules. Add detailed CLI error reports with recovery commands, align the build and host-check documentation, and keep the legacy Go tree outside normal builds. Checks: make check; make integration-test; go test ./... (legacy/go).
129 lines
6.3 KiB
Markdown
129 lines
6.3 KiB
Markdown
# latchd
|
||
|
||
Want a TUI-based login manager because you are tired of GDM or Plasma Login? Latchd gives you a small keyboard-first login screen on a Linux virtual terminal, then starts a TTY shell, an X11 desktop, or a Wayland desktop for the account you choose.
|
||
|
||
Latchd is written in Rust and runs as a systemd service. It finds login accounts through NSS, reads desktop entries from the configured directories, The old Go prototype is still in [`legacy/go/`](legacy/go/), but it is not part of the build.
|
||
|
||

|
||
|
||
This screen comes from the Docker preview capture; the [UI guide](docs/ui.md) has the keyboard map and the help screen.
|
||
|
||
## What latchd does
|
||
|
||
- account discovery — reads normal login accounts through NSS; filters low UIDs, excluded names, no-login shells, and unsafe home directories
|
||
- account status — reads shadow aging fields and the configured faillock helper; shows expiry, lock, inactivity, and failure counts in the screen
|
||
- session discovery — reads X11 and Wayland `.desktop` files plus administrator scripts; keeps the program and its arguments separate instead of passing them to a shell
|
||
- login handoff — builds the user environment, opens the configured login session, starts the selected program with the account UID and groups, and closes the session when it exits
|
||
- X11 startup — creates a private Xauthority file, waits for the X server readiness signal, and removes the file after the desktop exits
|
||
- Wayland startup — starts the selected desktop with the session values it needs; it does not start a compositor
|
||
- TTY startup — attaches the selected shell to the virtual terminal and records the user process when UTMPX is available
|
||
- user interface — provides account switching, last-session preferences, filtering, refresh, notifications, wallpapers, reduced motion, and confirmed power actions
|
||
|
||
Preview mode draws the same screen and reads the same TOML structure, but it does not authenticate or start a user program, which makes it useful for layout work and config checks.
|
||
|
||
## Quick start
|
||
|
||
Install the build requirements on Debian or Ubuntu:
|
||
|
||
```sh
|
||
sudo apt-get install build-essential pkg-config libpam0g-dev libpam-modules
|
||
```
|
||
|
||
Build the release binary and run the checks:
|
||
|
||
```sh
|
||
make check
|
||
make build
|
||
```
|
||
|
||
The binary is `build/latchd`. Open the preview screen with:
|
||
|
||
```sh
|
||
./build/latchd --preview --no-log
|
||
```
|
||
|
||
The repository pins Rust 1.88 in [`rust-toolchain.toml`](rust-toolchain.toml).
|
||
|
||
## Configuration
|
||
|
||
The service reads `/etc/latchd/config.toml`. Preview mode first checks `$XDG_CONFIG_HOME/latchd/config.toml`, then `~/.config/latchd/config.toml`, and finally the system file. `--config PATH` selects one file directly.
|
||
|
||
Create a user file from the example with:
|
||
|
||
```sh
|
||
make install-user
|
||
```
|
||
|
||
That command creates `~/.config/latchd/` with mode `700`, writes `config.toml` with mode `600`, and leaves an existing file alone. The full field reference, variable substitution, command-line overrides, desktop entry rules, and permission checks are in [`docs/configuration.md`](docs/configuration.md).
|
||
|
||
## Install on a test machine
|
||
|
||
Use a disposable machine and keep another login path available while you change the display manager:
|
||
|
||
```sh
|
||
sudo make install
|
||
sudo systemctl enable latchd.service
|
||
sudo systemctl start latchd.service
|
||
```
|
||
|
||
The install target writes the binary, `/etc/latchd/config.toml`, `/etc/pam.d/latchd`, the session-script directories, and the systemd unit. The supplied unit uses `/dev/tty2`, so change both `tty` in the TOML file and `TTYPath` in the unit if you use another virtual terminal. The install target does not disable the current display manager for you.
|
||
|
||
## Keyboard controls
|
||
|
||
| Key | Action |
|
||
| --- | --- |
|
||
| Tab / Shift-Tab | Move focus |
|
||
| Up / Down | Move focus or move in a filtered list |
|
||
| Left / Right | Change the selected session |
|
||
| `/` | Filter sessions or accounts |
|
||
| Ctrl-R | Refresh accounts and sessions |
|
||
| Ctrl-N / Ctrl-P | Select the next or previous account |
|
||
| Ctrl-B | Toggle the background |
|
||
| Ctrl-M | Toggle reduced motion |
|
||
| Enter | Authenticate or submit a password change |
|
||
| Esc | Clear the password or close a popup |
|
||
| `?` | Show the key reference |
|
||
| Ctrl-C | Restore the terminal and quit |
|
||
| F1–F12 | Confirm a configured power action |
|
||
|
||
Lowercase filters ignore case, while a filter with an uppercase character is case-sensitive. The preview screen and the capture command are documented in [`docs/ui.md`](docs/ui.md).
|
||
|
||
## Checks and releases
|
||
|
||
Use `make check` for formatting, unit tests, Clippy, and rustdoc; use `make integration-test` for the CLI paths and `make docker-test` for the pinned container build. `make pam-fixture-test` needs root because it installs temporary test policies, while `make system-e2e` checks the services and devices available on the current host.
|
||
|
||
Run `make system-e2e-strict` only in a disposable VM that has a test policy, a real virtual terminal, systemd-logind, and the X11 or Wayland stack you want to test. [`docs/e2e-testing.md`](docs/e2e-testing.md) explains what each check can and cannot cover.
|
||
|
||
Create a local release archive with:
|
||
|
||
```sh
|
||
make package
|
||
```
|
||
|
||
GitLab CI runs the same Rust, CLI, container, and capability checks, then creates an archive and SHA-256 file for a SemVer tag. The release process is described in [`docs/development.md`](docs/development.md).
|
||
|
||
## Read next
|
||
|
||
- [`docs/guide.md`](docs/guide.md) explains the service from startup to session cleanup.
|
||
- [`docs/configuration.md`](docs/configuration.md) explains each configuration field.
|
||
- [`docs/architecture.md`](docs/architecture.md) explains the workspace and the process boundaries.
|
||
- [`docs/development.md`](docs/development.md) explains builds, tests, Docker, and packages.
|
||
- [`docs/ui.md`](docs/ui.md) shows the screen and its controls.
|
||
- [`docs/e2e-testing.md`](docs/e2e-testing.md) explains the VM and container checks.
|
||
|
||
## Project layout
|
||
|
||
```text
|
||
crates/latchd-core/ account discovery, configuration, sessions, and UTMPX
|
||
crates/latchd-auth/ authentication worker and session handoff
|
||
crates/latchd-tui/ terminal state, rendering, input, and effects
|
||
rust/main.rs command-line entry point and service loop
|
||
extra/ example configuration, login policy, and systemd unit
|
||
scripts/ CLI, Docker, fixture, and host checks
|
||
legacy/go/ reference implementation from the early prototype
|
||
```
|
||
|
||
## License
|
||
|
||
Apache-2.0. See [`LICENSE`](LICENSE).
|