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).
8.7 KiB
Latchd guide
Latchd is a terminal login manager for Linux. It starts on a virtual terminal, gives you a keyboard-first screen, and starts the shell or desktop you select.
The service is small on purpose: systemd gives it the terminal, the login stack checks the account, and latchd handles the screen plus the process handoff. The configuration reference lists every field, while the architecture notes explain the Rust workspace.
What starts when
The service unit starts /usr/bin/latchd as root on /dev/tty2. The default configuration file is /etc/latchd/config.toml.
The screen contains these parts:
- A list of desktop and shell sessions.
- An account field.
- A password field.
- A status line.
Use the screen in this order:
- Select an account.
- Select a desktop or shell.
- Enter the password.
- Press Enter.
- Enter a new password if the login stack requests one.
After login, latchd performs these actions:
- Build an environment for the selected account and session.
- Open the session.
- Start the selected child with the account credentials.
- Wait for the child to exit.
- Close the session.
Session-specific setup works as follows:
- X11 uses a temporary authority file.
- Wayland receives the session values that it needs.
- A TTY session starts the account shell.
Start latchd
|
v
Show accounts and sessions
|
v
Select account, session, and password
|
v
Press Enter
|
v
Check the password and account state
|
+------------------------------+
| |
v v
Login accepted New password required
| |
| v
| Show new password field
| |
| v
| Submit the password change
| |
+--------------+---------------+
|
v
Build the session environment
|
v
Open the session
|
v
Start the child
|
v
Wait for exit
|
v
Close the session
Service mode and preview mode
Service mode needs root, a controlling terminal, and a system configuration file with safe ownership. It can authenticate users and start sessions.
Preview mode is for local work; it draws the screen, discovers the configured entries, and reads the user configuration, but it does not authenticate or start a child process.
make build
./build/latchd --preview --no-log
Use the non-interactive checks when you only need a result:
./build/latchd --preview --show-config --no-log
./build/latchd --preview --no-tui --no-log
--show-config prints the build information plus the selected terminal, service name, and shell. --no-tui validates the configuration and runs session preflight without opening the screen.
Build from source
Install Rust 1.88 and the PAM development files. On Debian or Ubuntu, use:
sudo apt-get install build-essential pkg-config libpam0g-dev libpam-modules
The toolchain file selects Rust 1.88 and the required rustfmt and clippy components. Build the optimized binary with:
make build --release
The output is at build/latchd, make build also embeds the version, commit, and build time.
Run make check for verification and make package to create a tarball with the binary, the system configuration, and the systemd unit. The make install target writes the files to the system.
The commands and the container workflow are in Development and release.
Install and start the service
Use a disposable machine first and keep another way to log in while you change the display manager:
sudo make install
sudo systemctl enable latchd.service
sudo systemctl start latchd.service
The install target writes the binary, the system TOML file, the login policy, the session-script directories, and the systemd unit. It does not disable another display manager, so stop the service that already owns the target VT before you start latchd there.
The supplied unit owns tty2. If you move it, change tty in the TOML file and TTYPath in the unit together; otherwise the values passed to the login stack and the terminal will disagree.
Use sudo systemctl status latchd.service and sudo journalctl -u latchd.service -b --no-pager when the unit fails before the screen appears.
Configuration files
The service default is /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 overrides all of them.
Create the user file with:
make install-user
The target creates the directory with mode 700 and the file with mode 600, and it leaves an existing file unchanged. Read Configuration reference before you add a variable file or change a path used by the service.
The main sections are:
| Section | What it controls |
|---|---|
[accounts] |
NSS account list, shadow status, and faillock display |
[x11] |
X server, authority tool, desktop entries, and scripts |
[wayland] |
Wayland desktop entries and scripts |
[environment_switcher] |
TTY entry and last-session file |
[visual] |
Wallpaper, animation, notices, and motion setting |
[power_controls] |
Confirmed programs bound to F1 through F12 |
Accounts and sessions
Account discovery starts with NSS and then removes entries below minimum_uid, entries in excluded_users, accounts with a no-login shell, and homes with unsafe ownership or write permission. Set enumerate = false when you want a blank list and manual username entry.
The screen can show password expiry, account expiry, lock state, and inactivity from the configured shadow file. It can also call faillock for the selected name; the query has a 750 millisecond limit and a failed query only removes the extra status text.
Session discovery reads .desktop files from the X11 and Wayland directories, then reads executable files from the matching script directories. Files must belong to root and must not be writable by group or other users. A desktop entry with Hidden=true, NoDisplay=true, an invalid Exec, or an unavailable TryExec is skipped.
Latchd stores desktop commands as argument lists, so shell operators and desktop field codes do not run. A script entry uses the file path as its command. The TTY shell appears when include_tty_shell = true, and it also appears when no other session exists.
The session environment
The child starts with an empty environment, then receives terminal locale values, account paths, XDG directories, session type, seat, VT number, and the selected desktop values. The account UID, primary GID, and supplementary groups are set before the child runs.
X11 starts the configured server on the selected VT, waits for its readiness signal, creates a private authority file, and removes that file after the client exits. Wayland starts the selected program but does not start a compositor. TTY mode attaches the shell to the controlling terminal.
The session records a UTMPX user process when the platform supports it. A last-session file can remember the successful choice for each account; the file is bounded and replaced atomically.
Logs and useful paths
The example file uses these paths:
| Path | Use |
|---|---|
/var/log/latchd.log |
Main service and audit output |
/var/log/latchd.client.log |
Graphical session output |
/var/log/latchd.xorg.log |
X server output |
/var/lib/latchd/last-session.toml |
Last session per account |
/etc/latchd/wms/ |
X11 script entries |
/etc/latchd/wayland/ |
Wayland script entries |
The service creates log files with mode 600 and rejects a main log larger than 64 MiB. Audit lines include the action, result, account, and a short reason; passwords and command arguments stay out of the log.
When a session does not start
Check the config and the paths first:
./build/latchd --preview --show-config --no-log
./build/latchd --preview --no-tui --no-log
make system-e2e
Then check the desktop file, the executable named by Exec or TryExec, the account home permissions, and the service log. For X11, check the X server and xauth paths; for Wayland, check the compositor and its user service outside latchd.
Use End-to-end testing when the host is a container or when you need a disposable VM for the terminal and display stack.