265 lines
12 KiB
Markdown
265 lines
12 KiB
Markdown
---
|
|
title: SDDM KWallet PAM Setup for Hyprland
|
|
type: note
|
|
permalink: dotfiles/research/sddm-kwallet-pam-setup-for-hyprland
|
|
tags:
|
|
- sddm
|
|
- kwallet
|
|
- pam
|
|
- hyprland
|
|
- arch
|
|
- research
|
|
- authoritative
|
|
---
|
|
|
|
# SDDM KWallet PAM Setup for Hyprland
|
|
|
|
## Summary
|
|
|
|
Complete, source-verified setup for automatic KWallet unlock on SDDM password login, for a non-Plasma (Hyprland) Arch Linux system.
|
|
|
|
## Freshness
|
|
- confidence: high
|
|
- last_validated: 2026-03-11
|
|
- volatility: low (KDE Plasma 6 PAM module is stable; Arch Wiki last edited 2026-03-10)
|
|
- review_after_days: 90
|
|
- validation_count: 1
|
|
- contradiction_count: 0
|
|
|
|
## Sources consulted
|
|
- [source] Arch Wiki "KDE Wallet" — https://wiki.archlinux.org/title/KDE_Wallet (last edited 2026-03-10)
|
|
- [source] Arch Wiki "SDDM" — https://wiki.archlinux.org/title/SDDM (last edited 2026-03-04)
|
|
- [source] Arch package database `kwallet-pam` 6.6.2-1 file listing — https://archlinux.org/packages/extra/x86_64/kwallet-pam/files/
|
|
- [source] Arch package database `kwallet` 6.23.0-1 file listing — https://archlinux.org/packages/extra/x86_64/kwallet/files/
|
|
- [source] Real-world Hyprland dotfiles from GitHub (wayblueorg/wayblue, AhmedAmrNabil/nix-config)
|
|
|
|
## (1) Package to install
|
|
|
|
- [fact] Package: **`kwallet-pam`** — in the official **`extra`** repository (NOT AUR)
|
|
- [fact] Install command: `sudo pacman -S kwallet-pam`
|
|
- [fact] Current version: **6.6.2-1** (as of 2026-03-03)
|
|
- [fact] Dependencies: `kwallet`, `pam`, `libgcrypt`, `socat` (all already present or auto-resolved)
|
|
- [fact] Files installed:
|
|
- `/usr/lib/security/pam_kwallet5.so` — the PAM module
|
|
- `/usr/lib/pam_kwallet_init` — session-start helper script
|
|
- `/etc/xdg/autostart/pam_kwallet_init.desktop` — XDG autostart for Plasma/DE environments
|
|
- `/usr/lib/systemd/user/plasma-kwallet-pam.service` — systemd user service
|
|
|
|
### Critical naming fact
|
|
- [fact] **The PAM module is `pam_kwallet5.so` even for KDE Frameworks 6 / Plasma 6.** There is no `pam_kwallet6.so`. The "5" in the name is a legacy artifact. The previous discovery note incorrectly stated `pam_kwallet6.so` would be provided — this was wrong.
|
|
- [fact] The existing `/etc/pam.d/sddm` and `/etc/pam.d/sddm-autologin` files already reference `pam_kwallet5.so` — they just need the package installed; **no module name changes are needed**.
|
|
|
|
## (2) PAM configuration
|
|
|
|
### Plasma 6 / ksecretd consideration
|
|
|
|
The Arch Wiki (section "Configure PAM on Plasma 6 (KF6)", updated 2026-03-10) says Plasma 6 uses `ksecretd` as the secret service daemon. The PAM session line should include `kwalletd=/usr/bin/ksecretd` to point to the new daemon.
|
|
|
|
- [fact] `ksecretd` binary is at `/usr/bin/ksecretd` and is shipped by the `kwallet` package (6.23.0-1)
|
|
- [fact] `kwalletd6` binary is at `/usr/bin/kwalletd6` and is also in the `kwallet` package
|
|
- [decision] For a non-Plasma Hyprland setup, the question is which daemon to target. The Arch Wiki recommends `kwalletd=/usr/bin/ksecretd` for KF6. Since the user has `kwalletd6` and `ksecretd` both installed via the `kwallet` package, and the Arch Wiki explicitly documents this parameter for KF6, the documentation should use the `kwalletd=/usr/bin/ksecretd` parameter.
|
|
|
|
### Recommended `/etc/pam.d/sddm` (password login)
|
|
|
|
The file already has the right structure. After installing `kwallet-pam`, the existing lines become functional. However, for Plasma 6 / KF6 compatibility, the session line should add the `kwalletd=` parameter:
|
|
|
|
```
|
|
#%PAM-1.0
|
|
|
|
auth sufficient pam_u2f.so cue
|
|
auth include system-login
|
|
-auth optional pam_gnome_keyring.so
|
|
-auth optional pam_kwallet5.so
|
|
|
|
account include system-login
|
|
|
|
password include system-login
|
|
|
|
session optional pam_keyinit.so force revoke
|
|
session include system-login
|
|
-session optional pam_gnome_keyring.so auto_start
|
|
-session optional pam_kwallet5.so auto_start kwalletd=/usr/bin/ksecretd
|
|
```
|
|
|
|
Key points:
|
|
- [fact] The `-` prefix on `-auth` and `-session` lines means "skip silently if module is missing" — this is already present in the default SDDM PAM files
|
|
- [fact] The `auth` line captures the user password for later use by the session line
|
|
- [fact] The `session` line with `auto_start` tells the module to start kwalletd/ksecretd and unlock the wallet
|
|
- [fact] `kwalletd=/usr/bin/ksecretd` directs the module to use KF6's ksecretd daemon instead of the legacy kwalletd5
|
|
|
|
### Recommended `/etc/pam.d/sddm-autologin`
|
|
|
|
This file is for SDDM autologin ONLY. Since the chosen model is password login, this file is informational but should still be kept correct:
|
|
|
|
```
|
|
#%PAM-1.0
|
|
|
|
auth sufficient pam_u2f.so cue
|
|
auth required pam_permit.so
|
|
-auth optional pam_kwallet5.so
|
|
|
|
account include system-local-login
|
|
|
|
password include system-local-login
|
|
|
|
session include system-local-login
|
|
-session optional pam_kwallet5.so auto_start kwalletd=/usr/bin/ksecretd
|
|
```
|
|
|
|
- [caveat] Autologin skips password entry → PAM has no password to pass to `pam_kwallet5.so` → wallet cannot be unlocked unless LUKS passphrase forwarding is used (see section 5)
|
|
|
|
### Minimal edit needed for existing system
|
|
|
|
Since the existing `/etc/pam.d/sddm` already has `pam_kwallet5.so` lines, the only change needed is:
|
|
|
|
1. Install `kwallet-pam` (makes the module file appear at `/usr/lib/security/pam_kwallet5.so`)
|
|
2. Add `kwalletd=/usr/bin/ksecretd` to the session line for KF6 compatibility
|
|
|
|
The auth line does NOT need the `kwalletd=` parameter — only the session line does.
|
|
|
|
## (3) Wallet initialization for non-Plasma (Hyprland) users
|
|
|
|
### Step A: Create the wallet
|
|
|
|
The wallet **must** be named `kdewallet` (the default name). PAM unlock only works with this specific wallet name.
|
|
|
|
**Option 1 — GUI (recommended if kwalletmanager is available):**
|
|
```bash
|
|
sudo pacman -S kwalletmanager
|
|
kwalletmanager6
|
|
```
|
|
Then: File > New Wallet > name it `kdewallet` > set password to match login password > choose **blowfish** encryption (NOT GPG).
|
|
|
|
**Option 2 — Headless/CLI:**
|
|
No pure-CLI wallet creation tool exists. The wallet is created automatically when:
|
|
1. The PAM module is installed and configured
|
|
2. The user logs in via SDDM with password
|
|
3. `pam_kwallet_init` runs and kwalletd6/ksecretd starts
|
|
4. If no wallet exists, kwalletd6 creates one on first access
|
|
|
|
For a truly headless init, trigger it by running in the session:
|
|
```bash
|
|
# Ensure kwalletd6/ksecretd is running (D-Bus activated)
|
|
dbus-send --session --dest=org.kde.kwalletd6 --print-reply \
|
|
/modules/kwalletd6 org.kde.KWallet.open \
|
|
string:"kdewallet" int64:0 string:"init"
|
|
```
|
|
This prompts for the wallet password interactively (Qt dialog).
|
|
|
|
### Step B: Ensure wallet password matches login password
|
|
|
|
- [requirement] The KWallet password MUST be identical to the Unix user login password. PAM passes the login password to the kwallet module; if they differ, the wallet won't unlock.
|
|
- [requirement] If the user password is changed later, the wallet password must be updated to match. Use `kwalletmanager6` > Change Password, or delete and recreate the wallet.
|
|
|
|
### Step C: kwalletrc configuration
|
|
|
|
Create `~/.config/kwalletrc` if it doesn't exist:
|
|
|
|
```ini
|
|
[Wallet]
|
|
Default Wallet=kdewallet
|
|
Enabled=true
|
|
First Use=false
|
|
|
|
[org.freedesktop.secrets]
|
|
apiEnabled=true
|
|
```
|
|
|
|
The `apiEnabled=true` setting enables the org.freedesktop.secrets D-Bus API, allowing libsecret-based apps (Chromium, VSCode, etc.) to use KWallet.
|
|
|
|
### Step D: Autostart `pam_kwallet_init` in Hyprland
|
|
|
|
The `kwallet-pam` package installs an XDG autostart entry (`/etc/xdg/autostart/pam_kwallet_init.desktop`), but Hyprland does NOT process XDG autostart files by default.
|
|
|
|
Add to `~/.config/hypr/hyprland.conf`:
|
|
```
|
|
exec-once = /usr/lib/pam_kwallet_init
|
|
```
|
|
|
|
This script reads the PAM-cached credentials and passes them to kwalletd6/ksecretd to unlock the wallet.
|
|
|
|
### Step E: D-Bus activation service (optional but recommended)
|
|
|
|
Create `~/.local/share/dbus-1/services/org.freedesktop.secrets.service`:
|
|
```ini
|
|
[D-BUS Service]
|
|
Name=org.freedesktop.secrets
|
|
Exec=/usr/bin/kwalletd6
|
|
```
|
|
|
|
This ensures kwalletd6 auto-starts when any app requests secrets via D-Bus, even before the wallet is explicitly opened.
|
|
|
|
## (4) Verification
|
|
|
|
### Quick verification after login
|
|
|
|
```bash
|
|
# 1. Check the PAM module is installed
|
|
ls -la /usr/lib/security/pam_kwallet5.so
|
|
|
|
# 2. Check kwalletd6 or ksecretd is running
|
|
pgrep -a kwalletd6 || pgrep -a ksecretd
|
|
|
|
# 3. Check the wallet is open
|
|
dbus-send --session --dest=org.kde.kwalletd6 --print-reply \
|
|
/modules/kwalletd6 org.kde.KWallet.isOpen \
|
|
string:"kdewallet"
|
|
|
|
# 4. Check wallet files exist
|
|
ls -la ~/.local/share/kwalletd/
|
|
|
|
# 5. Query the wallet (should return without prompting for password)
|
|
kwallet-query -l kdewallet
|
|
|
|
# 6. Check environment variables set by pam_kwallet_init
|
|
echo $PAM_KWALLET5_LOGIN
|
|
```
|
|
|
|
### Full integration test
|
|
1. Log out of Hyprland
|
|
2. At SDDM greeter, type user password and log in
|
|
3. After Hyprland starts, run `kwallet-query -l kdewallet` — it should list folders without prompting
|
|
4. Open a KWallet-aware app (e.g., Chromium with `--password-store=kwallet5`) and verify it stores/retrieves credentials
|
|
|
|
### Troubleshooting if wallet doesn't auto-unlock
|
|
- Check `journalctl --user -u plasma-kwallet-pam.service` for errors
|
|
- Check `journalctl -b | grep -i kwallet` for PAM-level errors
|
|
- Verify wallet password matches login password exactly
|
|
- Verify wallet is named exactly `kdewallet` (not `default` or any other name)
|
|
- Verify wallet uses blowfish encryption, not GPG
|
|
|
|
## (5) Caveats
|
|
|
|
### U2F / pam_u2f.so interaction
|
|
|
|
- [risk] The existing `/etc/pam.d/sddm` has `auth sufficient pam_u2f.so cue` as the FIRST auth line. When `sufficient` succeeds, PAM skips remaining auth modules — including `pam_kwallet5.so`.
|
|
- [consequence] If the user authenticates via U2F key only (no password typed), the kwallet module never captures a password → wallet cannot be unlocked automatically.
|
|
- [mitigation] This is acceptable if U2F is used as a convenience shortcut and the user accepts that wallet won't auto-unlock in that case. The wallet can be manually unlocked later.
|
|
- [alternative] To make U2F + kwallet work together, change `sufficient` to a two-factor setup where password is always required. But this changes the security model and is out of scope for this documentation.
|
|
|
|
### Autologin caveat
|
|
|
|
- [risk] SDDM autologin (`pam_permit.so`) provides no password → `pam_kwallet5.so` has nothing to unlock the wallet with.
|
|
- [fact] The Arch Wiki documents a workaround using `pam_systemd_loadkey.so` for LUKS-encrypted systems: the LUKS passphrase can be forwarded from the initramfs to the PAM stack, allowing wallet unlock even with autologin.
|
|
- [requirement] This requires: (1) systemd-based initramfs (`sd-encrypt` hook, not classic `encrypt`), (2) `pam_systemd_loadkey.so` line in sddm-autologin, (3) sddm.service override with `KeyringMode=inherit`.
|
|
- [fact] The current system uses classic `encrypt` hook, NOT `sd-encrypt`, so this workaround is NOT available without migrating the initramfs to systemd hooks.
|
|
- [decision] Since password login (not autologin) was chosen, this is informational only.
|
|
|
|
### Fingerprint reader caveat
|
|
- [fact] KWallet cannot be unlocked using a fingerprint reader (per Arch Wiki). Similar to U2F — no password is available.
|
|
|
|
### GPG encryption caveat
|
|
- [fact] `kwallet-pam` does NOT work with GPG-encrypted wallets. The wallet MUST use standard blowfish encryption.
|
|
|
|
### hyprlock caveat
|
|
- [fact] hyprlock uses `auth include login` in `/etc/pam.d/hyprlock`. The login PAM chain does NOT include kwallet PAM modules. Unlocking hyprlock will NOT re-open the wallet if it was closed.
|
|
- [mitigation] Typically the wallet stays open for the session duration. If the wallet is configured with `Leave Open=true` (in kwalletrc or kwalletmanager), it won't close automatically.
|
|
|
|
### Password change caveat
|
|
- [fact] If the user's login password is changed (via `passwd`), the wallet password must be manually updated to match. PAM does not automatically synchronize wallet passwords on password change.
|
|
|
|
## Relations
|
|
- related_to [[LUKS SDDM KWallet discovery]]
|
|
- related_to [[luks-sddm-kwallet-login-integration]]
|
|
- related_to [[LUKS SDDM KWallet documentation targets]]
|