Troubleshooting
Camera not detected
Symptom: facelock devices shows no cameras, or facelock enroll fails with "no camera found".
Steps:
- Check that your camera is recognized by the kernel:
ls /dev/video* v4l2-ctl --list-devices - Verify your user has access to the video device:
groups # should include "video" sudo usermod -aG video $USER # add yourself, then log out and back in - If
/dev/video*exists but Facelock skips it, set the device explicitly:[device] path = "/dev/video0" - Some cameras expose multiple
/dev/video*nodes (capture + metadata). Try each one.
"No IR camera" error when IR camera is available
Symptom: security.require_ir = true (the default) rejects your camera even though it supports IR.
Steps:
- Check what Facelock detects:
facelock devices - IR detection looks for keywords like "ir" or "infrared" in the device name and checks for grayscale formats (GREY, Y16). Some cameras do not advertise IR in their name.
- If you are certain your camera is IR, check its V4L2 capabilities:
v4l2-ctl -d /dev/video2 --list-formats-ext - As a workaround, you can set
security.require_ir = false-- but understand this weakens spoofing resistance. Only do this for testing.
Auth too slow
First-start latency (~700ms -- 2s)
The first authentication after boot (or after the daemon starts) is slow because ONNX models must be loaded into memory. This is normal. Subsequent auths in daemon mode typically take ~600ms (or ~150ms if the camera is still warm from a recent auth).
Consistently slow (~700ms+ every time)
You may be running in oneshot mode. Check your config:
[daemon]
mode = "daemon" # default; uses persistent daemon
With daemon mode, enable D-Bus activation:
sudo facelock setup --systemd
Inference slow on CPU
Try reducing frame resolution or switching to the smaller model set:
[device]
max_height = 320
[recognition]
detector_model = "scrfd_2.5g_bnkps.onnx"
embedder_model = "w600k_r50.onnx"
threads = 4 # increase if you have more cores
PAM lockout recovery
A broken PAM module can lock you out of your system. Always keep a root shell open when testing PAM changes.
If you are locked out
- Boot into single-user/recovery mode (GRUB: edit the boot entry, add
singleorinit=/bin/bashto the kernel line). - Remount the filesystem read-write:
mount -o remount,rw / - Restore the PAM backup:
Or remove the Facelock line fromcp /etc/pam.d/sudo.facelock-backup /etc/pam.d/sudo/etc/pam.d/sudo:sed -i '/pam_facelock/d' /etc/pam.d/sudo - Reboot normally.
If you still have a root shell open
# From your root shell:
cp /etc/pam.d/sudo.facelock-backup /etc/pam.d/sudo
Prevention
- Always test in containers first (
just test-pam). - Keep a root shell open during PAM testing.
- Start with
sudoonly -- do not add Facelock tologinorsddmuntilsudoworks reliably. - Set
security.disabled = trueas an emergency kill switch (PAM returns IGNORE).
systemd unit not starting
Symptom: systemctl status facelock-daemon.service shows failed or inactive.
Steps:
- Check the journal:
journalctl -u facelock-daemon.service -n 50 --no-pager - Verify the service unit is enabled:
systemctl status facelock-daemon.service systemctl enable --now facelock-daemon.service - Check that the binary exists:
which facelock ls -la /usr/bin/facelock - Check model files exist:
ls -la /var/lib/facelock/models/ - Manual test run (should print errors to stderr):
sudo /usr/bin/facelock daemon
Known issue: ONNX runtime crashes under restrictive systemd sandboxing
The ONNX runtime requires access to /dev/null, /dev/urandom, and /proc/sys. If you have customized the systemd unit with DevicePolicy=closed, ProtectKernelTunables=yes, or ProtectProc=invisible, the daemon may crash before main() with no stderr output. Use the default unit file or add restrictions incrementally, testing each one.
Model download failures
Symptom: facelock setup fails to download models.
Steps:
- Check network connectivity.
- Try downloading manually:
curl -L -o /var/lib/facelock/models/scrfd_2.5g_bnkps.onnx \ "https://github.com/visomaster/visomaster-assets/releases/download/v0.1.0/scrfd_2.5g_bnkps.onnx" curl -L -o /var/lib/facelock/models/w600k_r50.onnx \ "https://github.com/visomaster/visomaster-assets/releases/download/v0.1.0/w600k_r50.onnx" - Verify SHA256 checksums match (Facelock checks these at model load time and rejects tampered files).
- Ensure the model directory exists and has correct permissions:
sudo mkdir -p /var/lib/facelock/models sudo chown root:root /var/lib/facelock/models sudo chmod 755 /var/lib/facelock/models
Permission issues
"Permission denied" when running facelock commands
Ensure your user is in the facelock group:
groups # check current groups
sudo usermod -aG facelock $USER
# Log out and back in for group changes to take effect
Database permission errors
The SQLite database requires specific permissions:
sudo chown root:facelock /var/lib/facelock/facelock.db
sudo chmod 640 /var/lib/facelock/facelock.db
# The directory needs group write for SQLite WAL files:
sudo chmod 770 /var/lib/facelock
PAM module cannot reach daemon
The daemon is activated via D-Bus. Verify:
busctl status org.facelock.Daemon
systemctl status facelock-daemon.service
Debugging with RUST_LOG
Facelock uses the tracing crate with RUST_LOG env-filter syntax.
# Verbose output for all facelock crates:
RUST_LOG=debug facelock test
# Trace a specific crate:
RUST_LOG=facelock_camera=trace facelock devices
# Multiple filters:
RUST_LOG=facelock_daemon=debug,facelock_face=trace facelock daemon
sudo strips environment variables
sudo sanitizes the environment by default. Use env to preserve RUST_LOG:
sudo env RUST_LOG=debug facelock test
sudo env RUST_LOG=facelock_daemon=trace facelock daemon
Useful log targets
| Target | What it shows |
|---|---|
facelock_camera | Camera detection, format negotiation, frame capture |
facelock_face | Model loading, inference timing, similarity scores |
facelock_daemon | IPC handling, rate limiting, auth flow |
facelock_store | Database operations, embedding storage |
pam_facelock | PAM module decisions (logged to syslog) |