Kyle Isom e9247c720a Add config validation, remove command, status filtering, and unlock method display
config check: validates UUID format, recognized methods, keyfile
consistency and existence. Reports all issues with alias context.

remove: deletes a device from config by alias. Inverse of add.

status: --mounted, --unlocked, --locked flags filter the device table.
Flags combine as OR.

mount/unlock: display which method succeeded and key slot used, e.g.
"(fido2, key slot 1)". cryptsetup Open now runs with -v and parses
"Key slot N unlocked" from stderr via io.MultiWriter.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 10:22:52 -07:00
2026-03-24 08:39:54 -07:00

arca

A CLI tool for mounting and unmounting LUKS-encrypted volumes. Latin for "strongbox."

arca talks to udisks2 over D-Bus for passphrase/keyfile unlock (no root needed) and falls back to cryptsetup for FIDO2/TPM2 token-based unlock (requires doas/sudo). It handles the unlock-then-mount and unmount-then-lock sequences as single commands.

Usage

arca mount backup              # unlock + mount by config alias
arca mount /dev/sda1           # unlock + mount by device path
arca mount backup -m /mnt/usb  # mount at a specific mountpoint
arca unmount backup            # unmount + lock
arca status                    # show all LUKS volumes and their state
arca init                      # generate config from detected devices
arca --version                 # print version

Mount and unmount are idempotent: mounting an already-mounted device prints the existing mount point; unmounting an already-locked device is a no-op.

Configuration

Optional. Without a config file, arca works with device paths directly using passphrase unlock.

Run arca init to auto-generate a config from detected LUKS devices (excludes the root filesystem). Edit the generated file to set aliases, methods, and mount points.

~/.config/arca/config.yaml (respects $XDG_CONFIG_HOME):

devices:
  backup:
    uuid: "b8b2f8e3-4cde-4aca-a96e-df9274019f9f"
    mountpoint: "/mnt/backup"  # optional — udisks2 picks if omitted
    methods:                   # optional — default: [passphrase]
      - fido2
      - passphrase
  media:
    uuid: "a1b2c3d4-5678-9abc-def0-1234567890ab"
    methods:
      - keyfile
      - passphrase
    keyfile: "/path/to/media.key"

Config fields

Field Required Description
uuid yes LUKS partition UUID (stable across device path changes)
mountpoint no Where to mount; udisks2 picks if omitted
methods no Ordered unlock strategies; default: [passphrase]
keyfile no Path to keyfile (required if keyfile is in methods)

Unlock methods

Method Backend Root required Notes
passphrase udisks2 no Prompts on terminal
keyfile udisks2 no Reads file from keyfile config field
fido2 cryptsetup yes (doas) Requires enrolled FIDO2 token
tpm2 cryptsetup yes (doas) Requires enrolled TPM2 key

Methods are tried in order. If the first fails (e.g., FIDO2 key not plugged in), arca tries the next.

Installation

Nix flake

# flake.nix
inputs.arca.url = "git+https://git.wntrmute.dev/kyle/arca";

# in your NixOS config
environment.systemPackages = [ inputs.arca.packages.${system}.default ];

From source

go install git.wntrmute.dev/kyle/arca@latest

Requirements

  • Linux with udisks2 running (standard on most desktop distributions)
  • D-Bus system bus access
  • For FIDO2/TPM2: cryptsetup, doas or sudo
  • For FIDO2/TPM2: token must be enrolled via systemd-cryptenroll

NixOS Notes

cryptsetup loads token handler plugins (FIDO2, TPM2) via dlopen, but NixOS's glibc only searches the binary's baked-in RUNPATH, which doesn't include systemd's plugin directory. arca works around this by setting LD_LIBRARY_PATH to the systemd cryptsetup plugin directory when invoking cryptsetup.

The plugin directory is discovered automatically from /run/current-system/sw/lib/cryptsetup or by resolving the systemd-cryptenroll binary path.

Note: cryptsetup's --external-tokens-path flag does not work on NixOS due to the same RUNPATH limitation — the flag is accepted but the dlopen call still uses the default search path.

Enrolling a FIDO2 key

doas systemd-cryptenroll --fido2-device=auto /dev/sda1

This prompts for the existing passphrase, then enrolls the FIDO2 key. Verify with:

doas cryptsetup luksDump /dev/sda1 | grep -A3 Token

Troubleshooting

"cannot connect to udisks2": The udisks2 service isn't running. Check systemctl status udisks2.

"device not found": The device path or alias doesn't match anything udisks2 knows about. Run arca status to list detected devices, or arca init to regenerate the config.

"No usable token is available": The FIDO2/TPM2 token isn't enrolled on this LUKS device. Enroll with systemd-cryptenroll. Also check that the token plugin is discoverable (see NixOS Notes above).

"Not authorized to perform operation": udisks2 polkit authorization failed. This happens when mounting a device unlocked via cryptsetup (root-owned mapping). Use --mountpoint or set mountpoint in config to use privileged mount instead.

FIDO2 key not detected: Ensure the key is plugged in and /dev/hidraw* devices are accessible. Check doas systemd-cryptenroll --fido2-device=list.

Description
No description provided
Readme 1.7 MiB
Languages
Go 97.8%
Nix 2.2%