Open Source / MIT + Apache 2.0

Facelock

Face unlock for Linux that earns root.
IR-enforced anti-spoofing, sub-second daemon auth, optional TPM-sealed encryption. 100% local — your face never leaves the machine.

Arch · Debian/Ubuntu · Fedora · NixOS · MIT/Apache 2.0 · No telemetry
facelock
$ sudo facelock setup
 
Facelock v0.1.4
Linux face authentication
 
# 9 interactive steps: camera, models, encryption,
# enrollment, recognition test, daemon, PAM ...
 
--- Setup Complete ---
 
Camera: /dev/video2
Models: /var/lib/facelock/models (standard)
Inference: CPU
Database: /var/lib/facelock/facelock.db
Encryption: AES-256-GCM (TPM-sealed key)
Daemon: enabled (D-Bus activation)
PAM: sudo, hyprlock
Face: enrolled
 
$ sudo facelock test
Testing face recognition for user 'ty'...
Look at the camera.
Matched model #1 '2026-05-30-1' (similarity: 0.92) in 0.19s

Three-stage recognition pipeline

SCRFD detection finds faces, affine alignment normalizes geometry, and ArcFace produces a 512-dimensional embedding for cosine similarity matching.

Camera Capture

V4L2 frame acquisition with auto-detection. Prefers IR cameras for anti-spoofing. CLAHE enhancement for consistent lighting.

Face Detection

SCRFD neural network locates faces and extracts 5-point landmarks. Affine alignment produces a normalized 112x112 crop.

Embedding Match

ArcFace produces a 512-dim L2-normalized vector. Cosine similarity against stored embeddings determines match or reject.

Defense in depth, on by default

Multiple independent layers protect against spoofing, tampering, and unauthorized access — without any configuration after install.

IR

IR Camera Enforcement

Enabled by default. Rejects RGB cameras that are trivially spoofed with a printed photo. IR captures skin texture invisible to screens.

FV

Frame Variance

Requires micro-movement between consecutive frames. Static photos produce near-identical embeddings and are rejected automatically.

RL

Rate Limiting

5 attempts per user per 60 seconds by default. Prevents brute-force and rapid-retry attacks against the daemon.

MV

Model Verification

ONNX model files are SHA256-verified at every load. Tampered models are rejected before any inference runs.

DB

D-Bus Policy

D-Bus system bus policy restricts daemon access. Only root and facelock group members can send messages to the daemon interface.

AL

Audit Logging

Every authentication attempt is logged to syslog with user, service, and outcome. Full audit trail in journald or /var/log/auth.log.

Where Facelock fits

Three places it pays for itself the first day you install it.

Sudo without typing

Every sudo prompt becomes a glance at the camera. The daemon keeps ONNX models loaded — ~600ms on a cold camera, dropping to 150–200ms on back-to-back unlocks.

Screen lock unlock

Drop-in PAM for Hyprlock, swaylock, and KDE Plasma's screen locker. Wake the display, look at the camera, you're back in.

Display manager login

GDM, SDDM, and LightDM (experimental). Camera initialization at the login screen is system-dependent — see docs for caveats.

Engineered for the Linux PAM ecosystem

A complete face authentication stack written in Rust, with sane defaults and the knobs you need when you outgrow them.

IR Anti-Spoofing

Enforces infrared cameras by default. Phone screens and printed photos lack IR skin texture, blocking the most common attack vector.

Sub-Second Auth

Persistent daemon keeps ONNX models loaded. ~600ms typical, dropping to ~150ms on back-to-back auths when the camera stays warm.

100% Local & Private

All processing happens on-device via ONNX Runtime. No cloud services, no network requests, no telemetry, no analytics. Your face data never leaves your machine, ever.

PAM Integration

Drop-in PAM module for sudo, polkit, hyprlock, swaylock, KDE, and login managers. Installs as a single pam_facelock.so — the wizard wires the rest.

TPM Encryption

Optional TPM 2.0 support for encrypting face embeddings at rest. Hardware-bound keys ensure biometric data stays protected even if the disk is copied.

Daemon + Oneshot

Choose persistent daemon mode for speed or oneshot mode for simplicity. The CLI auto-detects which mode is available.

Your face, your machine, nobody else

Facelock is designed from the ground up to keep your biometric data private.

LO

Local-Only Processing

Face detection and recognition run entirely on your CPU or GPU via ONNX Runtime. No images or embeddings are ever transmitted over the network.

NT

No Telemetry

Zero analytics, tracking, or phone-home code. Models are downloaded once during facelock setup — after that, Facelock never contacts any server.

EN

Encryption at Rest

Face embeddings can be encrypted with AES-256-GCM, optionally sealed to your TPM. Even if someone copies your database, the biometric data is unreadable.

OS

Open Source & Auditable

Every line of code is MIT/Apache-2.0 licensed. No proprietary blobs, no obfuscated network calls. Verify the privacy claims yourself.

One package. One wizard. Done.

Install the package for your distro and run sudo facelock setup. The wizard detects your camera, downloads models, sets up encryption, enrolls your face, and wires up PAM for sudo and your screen locker. No further commands needed.

terminal
# Install from AUR
$ yay -S facelock   # or: paru -S facelock
 
# Run the interactive setup wizard
$ sudo facelock setup

Need finer control? See docs for manual model paths, custom PAM stacks, GPU provider tuning, and --non-interactive automation.

Facelock vs Howdy

Howdy proved face auth on Linux was possible. Facelock is the production rewrite — Rust, hardened by default, and engineered to be safe to actually deploy.

Feature Facelock Howdy
LanguageMemory-safe at compile time; no runtime crashes on bad input. Rust Python
Daemon modeAuth completes before you finish typing your password. Yes (~150–600ms auth) No (process per auth)
IR enforcementPhone screens and printed photos are rejected without configuration. Default on Supported, not enforced
Frame variance checkA still photo can't produce two different frames — rejected automatically. Default on No
TPM encryptionA copied disk image can't decrypt your face data. Optional (sealed key) No
Model verificationSwapped or tampered models fail to load instead of mis-authenticating. SHA256 at every load No
Rate limitingRapid-retry brute force is stopped at the daemon, not the PAM stack. 5/user/60s default No
D-Bus activationDaemon only runs when something asks for auth — zero idle cost. Yes No
Constant-time matchingMatch scores can't be reconstructed by timing the response. subtle crate No
GPU accelerationDrop auth latency further on supported hardware — no rebuild needed. CUDA / ROCm / OpenVINO (runtime) No
Audit loggingEvery attempt is grep-able and SIEM-friendly. Structured JSONL + syslog syslog only
systemd hardeningDaemon runs without write access to / and without ambient capabilities. ProtectSystem, NoNewPrivileges, etc. No
PAM module sizeTiny PAM module — no Python runtime in the auth path. ~2MB (libc + toml + zbus) Full Python runtime