refactor: split the TUI and refresh project docs
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).
This commit is contained in:
167
README.md
167
README.md
@@ -1,106 +1,72 @@
|
||||
# latchd
|
||||
|
||||
Want a TUI-based login manager because you are tired of GDM or Plasma Login? Latchd puts a small, keyboard-driven login screen on a Linux virtual terminal. It uses PAM for authentication and can start a TTY shell, an X11 desktop, or a Wayland desktop.
|
||||
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. The old Go prototype remains in `legacy/go/` for reference. It is not part of the release build.
|
||||
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.
|
||||
|
||||

|
||||
|
||||
The image above is the preview screen. It was captured from the Docker test image. See [`docs/ui.md`](docs/ui.md) for the keyboard reference and the second screenshot.
|
||||
This screen comes from the Docker preview capture; the [UI guide](docs/ui.md) has the keyboard map and the help screen.
|
||||
|
||||
## Features
|
||||
## What latchd does
|
||||
|
||||
- Discovers normal login accounts through NSS.
|
||||
- Shows account expiry, locked-account, and faillock status before login.
|
||||
- Lets PAM handle authentication and password changes.
|
||||
- Switches between users and sessions from the same screen.
|
||||
- Finds X11 and Wayland desktop entries from configured directories.
|
||||
- Can offer a TTY shell as a session choice.
|
||||
- Starts the selected session with a restricted environment and the correct user ID.
|
||||
- Passes the selected session, seat, and virtual terminal to PAM and logind.
|
||||
- Imports approved values from PAM into the session environment.
|
||||
- Writes UTMPX records when the platform supports them.
|
||||
- Provides filtering, keyboard help, refresh, notifications, wallpaper, and reduced-motion controls.
|
||||
- Has a preview mode for UI work and configuration checks.
|
||||
- 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
|
||||
|
||||
The service needs Linux PAM and a virtual terminal. X11 and Wayland sessions also need their own display server, compositor, and desktop files. Docker covers the parts that do not require those host services. The remaining checks must run on a prepared machine or VM.
|
||||
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.
|
||||
|
||||
## Requirements
|
||||
## Quick start
|
||||
|
||||
Builds use Rust 1.88 and the system PAM development files. On Debian or Ubuntu:
|
||||
Install the build requirements on Debian or Ubuntu:
|
||||
|
||||
```sh
|
||||
sudo apt-get install build-essential pkg-config libpam0g-dev libpam-modules
|
||||
```
|
||||
|
||||
The repository includes the required `rustfmt` and `clippy` components in `rust-toolchain.toml`.
|
||||
|
||||
## Build and run
|
||||
|
||||
Run the local verification gate and build the release binary:
|
||||
Build the release binary and run the checks:
|
||||
|
||||
```sh
|
||||
make check
|
||||
make build
|
||||
```
|
||||
|
||||
The binary is written to `build/latchd`. To open the non-authenticating preview:
|
||||
The binary is `build/latchd`. Open the preview screen with:
|
||||
|
||||
```sh
|
||||
make run-preview
|
||||
# or
|
||||
./build/latchd --preview --no-log
|
||||
```
|
||||
|
||||
Preview mode does not contact PAM, start a user session, or run power actions. It is safe to use while changing the layout or configuration.
|
||||
|
||||
For terminals with limited character support, set `LATCHD_ASCII=1`. Set `NO_COLOR=1` for plain output. Set `LATCHD_HIGH_CONTRAST=1` for a stronger focus colour.
|
||||
The repository pins Rust 1.88 in [`rust-toolchain.toml`](rust-toolchain.toml).
|
||||
|
||||
## Configuration
|
||||
|
||||
The example file is [`extra/config.toml`](extra/config.toml). Latchd uses separate paths for a system service and a local preview:
|
||||
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.
|
||||
|
||||
- A root service reads `/etc/latchd/config.toml`.
|
||||
- Preview mode first checks `$XDG_CONFIG_HOME/latchd/config.toml`.
|
||||
- If `XDG_CONFIG_HOME` is not set, preview mode checks `~/.config/latchd/config.toml`.
|
||||
- `--config PATH` selects a file explicitly and takes precedence over the defaults.
|
||||
|
||||
Create the user file from the example:
|
||||
Create a user file from the example with:
|
||||
|
||||
```sh
|
||||
make install-user
|
||||
./build/latchd --preview --no-log
|
||||
```
|
||||
|
||||
`make install-user` creates `~/.config/latchd/` with mode `700` and creates `config.toml` with mode `600`. It does not replace an existing file. Set `USER_CONFIG_HOME=/path` or `XDG_CONFIG_HOME=/path` when the file must be stored elsewhere.
|
||||
|
||||
The main sections in the example are:
|
||||
|
||||
- `[accounts]` for NSS discovery, faillock, and account-age checks.
|
||||
- `[x11]` and `[wayland]` for desktop-entry and administrator script directories.
|
||||
- `[environment_switcher]` for session choices and the last-session preference file.
|
||||
- `[visual]` for wallpaper, animation, notification, and reduced-motion settings.
|
||||
- `[power_controls]` for confirmed power commands. Latchd starts these programs directly; it does not use a shell.
|
||||
|
||||
Keep the system file owned by root and unwritable by group or other users. Do not put passwords or other secrets in command-line arguments.
|
||||
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 first. Keep another login path available while changing the display manager.
|
||||
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
|
||||
```
|
||||
|
||||
This installs:
|
||||
|
||||
- `/usr/bin/latchd`
|
||||
- `/etc/latchd/config.toml`
|
||||
- `/etc/pam.d/latchd`
|
||||
- `/usr/lib/systemd/system/latchd.service`
|
||||
|
||||
The supplied service uses `/dev/tty2`. If you choose another VT, change both the `tty` value in the config and `TTYPath` in the systemd unit. Stop or disable the existing display manager before enabling latchd on the same terminal.
|
||||
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
|
||||
|
||||
@@ -110,74 +76,53 @@ The supplied service uses `/dev/tty2`. If you choose another VT, change both the
|
||||
| Up / Down | Move focus or move in a filtered list |
|
||||
| Left / Right | Change the selected session |
|
||||
| `/` | Filter sessions or accounts |
|
||||
| Ctrl-R | Refresh account and session discovery |
|
||||
| Ctrl-R | Refresh accounts and sessions |
|
||||
| Ctrl-N / Ctrl-P | Select the next or previous account |
|
||||
| Ctrl-B | Toggle wallpaper and ambient effects |
|
||||
| Ctrl-B | Toggle the background |
|
||||
| Ctrl-M | Toggle reduced motion |
|
||||
| Enter | Authenticate or submit a PAM password change |
|
||||
| Enter | Authenticate or submit a password change |
|
||||
| Esc | Clear the password or close a popup |
|
||||
| `?` | Show keyboard help |
|
||||
| `?` | Show the key reference |
|
||||
| Ctrl-C | Restore the terminal and quit |
|
||||
| F1–F12 | Confirm a configured power action |
|
||||
|
||||
Lowercase filters ignore case. A filter with an uppercase letter is case-sensitive. The status line can show account and faillock information before login.
|
||||
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).
|
||||
|
||||
## Testing
|
||||
## Checks and releases
|
||||
|
||||
Run the local checks with these commands:
|
||||
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.
|
||||
|
||||
```sh
|
||||
make check
|
||||
make integration-test
|
||||
make docker-test
|
||||
make system-e2e
|
||||
```
|
||||
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.
|
||||
|
||||
Run `make audit` after you install `cargo-audit`. Run `make pam-fixture-test` as root. The PAM fixture command creates temporary policies and removes them when it exits.
|
||||
|
||||
`make system-e2e` checks the PAM library, faillock, virtual terminal, X11, Wayland, and systemd-logind on the current host. It prints `PASS`, `SKIP`, or `FAIL`. A pseudo-terminal does not provide a virtual terminal. The check does not install a PAM policy or start systemd-logind.
|
||||
|
||||
Run the strict check in a disposable VM with a test PAM policy, a real VT, systemd-logind, and the X11 or Wayland stack you want to test:
|
||||
|
||||
```sh
|
||||
make system-e2e-strict
|
||||
```
|
||||
|
||||
See [`docs/e2e-testing.md`](docs/e2e-testing.md) for the test limits and VM setup.
|
||||
|
||||
## Security notes
|
||||
|
||||
- PAM handles stay on one worker thread.
|
||||
- Password buffers are zeroized. Passwords are not written to argv, logs, or the TUI.
|
||||
- Audit records contain the account and a stable result code. They do not contain PAM's free-form error text or password data.
|
||||
- Session environments are rebuilt from an allowlist.
|
||||
- Latchd checks desktop files, scripts, binaries, home directories, logs, and configuration files before use.
|
||||
- Xauthority files and session logs use private permissions and cleanup guards.
|
||||
- Power commands need confirmation and are disabled in preview mode.
|
||||
- Account and faillock checks do not unlock accounts or bypass PAM.
|
||||
|
||||
## Project layout
|
||||
|
||||
```text
|
||||
crates/latchd-core/ configuration, account discovery, sessions, and UTMPX
|
||||
crates/latchd-auth/ PAM FFI, password changes, and the authentication worker
|
||||
crates/latchd-tui/ Ratatui state, rendering, filtering, and effects
|
||||
rust/main.rs command-line entry point and service orchestration
|
||||
extra/ example configuration, PAM policy, and systemd unit
|
||||
scripts/ Docker, CLI, PAM, and system capability tests
|
||||
legacy/go/ non-production Go reference
|
||||
```
|
||||
|
||||
## Releases
|
||||
|
||||
GitLab CI runs formatting, tests, Clippy, rustdoc, RustSec checks, CLI tests, capability checks, and the Docker suite. A SemVer tag runs the package job and publishes a Linux archive with its SHA-256 file. The strict VT, PAM, X11, Wayland, and logind checks are separate because CI containers do not provide those host services.
|
||||
|
||||
Create a local package with:
|
||||
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).
|
||||
|
||||
Reference in New Issue
Block a user