An open API service indexing awesome lists of open source software.

https://github.com/koudis/luks-automount

Automount of LUKS encrypted USB devices
https://github.com/koudis/luks-automount

automount automounter automounting-usb-drives luks luks-encryption luks2

Last synced: about 1 month ago
JSON representation

Automount of LUKS encrypted USB devices

Awesome Lists containing this project

README

          

# luks-automount

Automatically unlocks and mounts whole-disk LUKS-encrypted USB SSDs when plugged in, and unmounts and locks them on removal. Passphrases are stored in GNOME Keyring. Privileged operations run through a short-lived worker subprocess invoked via `sudo`.

## Usage

### Register a disk

Plug in the USB drive, then:

```sh
luks-automount add myusb
```

Prompts for device selection, mount point (must exist under `/mnt/`), filesystem type, mount options, and passphrase. The passphrase is stored in GNOME Keyring and never written to disk or logs.

### List registered disks

```sh
luks-automount list
```

### Manually unlock / lock

```sh
luks-automount unlock myusb
luks-automount lock myusb
```

### Run the daemon

```sh
luks-automount run
```

Watches for plug/unplug events and unlocks or locks registered disks automatically. Only one instance may run at a time.

### Install

The user service cannot answer `sudo` password prompts. Run the installer from the built binary before enabling normal daemon use.

```sh
luks-automount install
```

The command can install the binary to `/usr/local/bin/luks-automount`, write the sudoers drop-in, write `~/.config/systemd/user/luks-automount.service`, and enable it immediately. If a busy-mount warning does not appear from the user service, make sure the installed service file is current and restart it with `systemctl --user daemon-reload` and `systemctl --user restart luks-automount.service`.

```sh
luks-automount uninstall
```

The command can disable and remove `~/.config/systemd/user/luks-automount.service`, remove `/etc/sudoers.d/luks-automount`, and remove `/usr/local/bin/luks-automount`.

### Remove a disk registration

```sh
luks-automount lock myusb # unmount first if mounted
luks-automount remove myusb
```

## Requirements

- Linux with device-mapper, `/dev/mapper`, block-device UEvent support, and mount support
- A graphical user session with GNOME Keyring or another compatible Secret Service implementation
- `sudo` installed and configured to allow the user to run `luks-automount worker` as root
- Mount points created under `/mnt/` before registering a disk

### Runtime requirements

- The hidden `worker` subcommand must be executable through `sudo`
- The user session must provide access to the Secret Service API so stored passphrases can be read
- `install` and `uninstall` require a user `systemd` instance
- The program validates mount points under `/mnt/`; bare `/mnt` and paths containing `..` are rejected
- Busy-mount warnings use `zenity` when the graphical session is available

### Build requirements

- Go 1.26 or newer
- A Linux system matching the runtime requirements above

### External tools and services

- Required for normal operation:
- `sudo`
- `cryptsetup`
- `systemctl` for `install` and `uninstall`
- GNOME Keyring or another Secret Service provider
- Required for the integration smoke test:
- `dd`
- `losetup`
- `mkfs.ext4`
- root privileges
- a host or VM with working loop devices

## Build

```sh
go build -o luks-automount ./cmd/luks-automount
```

Install the tool, user service, and sudoers rule:

```sh
./luks-automount install
```

The installer asks for confirmation before each step. Root access is requested through `sudo` only for installing `/usr/local/bin/luks-automount` and `/etc/sudoers.d/luks-automount`.

## sudo configuration

The installer writes this rule so the user service can run the worker without a password prompt:

```
# /etc/sudoers.d/luks-automount
youruser ALL=(root) NOPASSWD: /usr/local/bin/luks-automount worker
```

If you manage sudoers manually, validate changes with `visudo` and keep the path equal to `/usr/local/bin/luks-automount`.

## Maintenance

### Changing requirements

Edit `doc/requirements.md` first. All functional decisions are recorded there. Review for contradictions before touching any code.

### Changing code

The main packages and their responsibilities:

| Package | Responsibility |
|---|---|
| `internal/config` | TOML config, disk struct, validation |
| `internal/keyring` | GNOME Keyring passphrase storage |
| `internal/logging` | slog fan-out: stderr (text) + rotating JSON file |
| `internal/monitor` | Netlink UEvent listener |
| `internal/luks` | LUKS UUID read, unlock, lock |
| `internal/worker` | Privileged worker protocol (server + client) |
| `internal/engine` | Daemon orchestrator, per-disk state machine |
| `cmd/luks-automount` | CLI (cobra subcommands) |

### Running tests

Automated test targets:

- `go test ./...`
- runs the regular unit and package tests
- covers config validation, CLI command behavior, daemon state transitions,
worker protocol handling, logging helpers, monitor logic, and the
mount-point-busy flow
- `go test ./internal/dialog ./cmd/luks-automount`
- useful as a quick focused check when changing the GNOME warning dialog,
service installation, or CLI lock behavior
- `go vet ./...`
- runs static checks across the whole project

Makefile shortcuts:

- `make test` runs `go test ./...`
- `make vet` runs `go vet ./...`
- `make test-integration` runs the privileged worker smoke test

```sh
go test ./...
```

The integration smoke test verifies the real worker path with privileged
operations. It requires root and a kernel with loop-device support (bare metal
or a VM, not a container):

```sh
go test -tags integration -c -o /tmp/worker.test ./internal/worker/
sudo /tmp/worker.test -test.run TestSmoke_WorkerProtocol -test.v
```

For the mount-point-busy behavior, also do a manual graphical smoke test after
changing the dialog or user-service integration:

1. Mount a configured disk.
2. Keep a shell or another app open inside the mount point.
3. Run `luks-automount lock ` or trigger daemon auto-lock.
4. Confirm the unmount is blocked and the GNOME warning appears.
5. Close the blocking app and retry.

## License

This project is licensed under the Apache License 2.0. See `LICENSE`.