System Contracts

Stable contracts. Do not change without updating this document.

Binaries

BinaryCratePurpose
facelockfacelock-cliUnified CLI (daemon, auth, enroll, test, setup, etc.)
pam_facelock.sopam-facelockPAM authentication module

CLI Subcommands

CommandPurpose
facelock setupDownload models, create directories
facelock setup --systemdInstall/enable systemd units
facelock setup --pamInstall PAM module to /etc/pam.d/
facelock enrollCapture and store a face
facelock testTest face recognition
facelock listList enrolled face models
facelock remove <id>Remove a specific model
facelock clearRemove all models for a user
facelock previewLive camera preview
facelock devicesList V4L2 cameras
facelock statusCheck system status
facelock configShow/edit configuration
facelock daemonRun persistent daemon
facelock auth --user XOne-shot auth (PAM helper)
facelock tpm statusTPM status
facelock benchBenchmarks
facelock restartRestart daemon

Operating Modes

ModeConfigPAM BehaviorCLI Behavior
Daemondaemon.mode = "daemon" (default)D-Bus IPC to daemonUses daemon if available, falls back to direct
Oneshotdaemon.mode = "oneshot"Spawns facelock authOperates directly (no daemon)

The CLI silently falls back to direct mode when the daemon is not available on D-Bus, regardless of config mode.

facelock auth Exit Codes

CodeMeaningPAM Code
0Face matchedPAM_SUCCESS
1No match / timeout / darkPAM_AUTH_ERR
2Error / no enrolled facesPAM_IGNORE

Filesystem Paths

PathOwnerModePurpose
/etc/facelock/config.tomlroot:root644Configuration
/var/lib/facelock/facelock.dbroot:facelock640Face embeddings
/var/lib/facelock/models/root:root755ONNX models
/var/log/facelock/snapshots/root:facelock750Auth snapshots
/usr/bin/facelockroot:root755CLI binary
/lib/security/pam_facelock.soroot:root755PAM module

All paths overridable via config. FACELOCK_CONFIG env var overrides config location.

Config Schema

TOML format. All keys optional -- camera auto-detected, sensible defaults for everything. See Configuration for the full reference.

Sections

SectionKey fields
[device]path (Option), max_height, rotation
[recognition]threshold, timeout_secs, detector_model, embedder_model, threads, execution_provider
[daemon]mode (DaemonMode enum), model_dir, idle_timeout_secs
[storage]db_path
[security]require_ir, require_frame_variance, min_auth_frames, abort_if_ssh, abort_if_lid_closed, rate_limit sub-section
[notification]mode (off/terminal/desktop/both), notify_prompt, notify_on_success, notify_on_failure
[snapshots]mode (off/all/failure/success), dir
[encryption]method (none/keyfile/tpm), key_path, sealed_key_path
[audit]enabled, path, rotate_size_mb
[tpm]pcr_binding, pcr_indices, tcti

Camera Auto-Detection

When device.path is omitted:

  1. Enumerate /dev/video0 through /dev/video63
  2. Filter to VIDEO_CAPTURE devices
  3. Prefer IR cameras (name contains "ir"/"infrared", or supports GREY/Y16 format)
  4. Fall back to first available device

Database Schema

SQLite with WAL mode and foreign keys:

CREATE TABLE face_models (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    user TEXT NOT NULL,
    label TEXT NOT NULL,
    created_at INTEGER NOT NULL,
    UNIQUE(user, label)
);

CREATE TABLE face_embeddings (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    model_id INTEGER NOT NULL REFERENCES face_models(id) ON DELETE CASCADE,
    embedding BLOB NOT NULL  -- 512 x f32 = 2048 bytes
);

IPC Protocol

D-Bus system bus (org.facelock.Daemon). Only used in daemon mode. The daemon exposes a D-Bus interface on the system bus, and both the PAM module and CLI connect as D-Bus clients. Access is controlled by D-Bus system bus policy (/etc/dbus-1/system.d/org.facelock.Daemon.conf).

Methods

Authenticate, Enroll, ListModels, RemoveModel, ClearModels, PreviewFrame, PreviewDetectFrame, ListDevices, ReleaseCamera, Ping, Shutdown

Return Types

AuthResult, Enrolled, Models, Removed, Frame, DetectFrame, Devices, Ok, Error

PAM Semantics

OutcomePAM Code
Face matchedPAM_SUCCESS (0)
No matchPAM_AUTH_ERR (7)
Daemon unavailable / errorPAM_IGNORE (25)
TimeoutPAM_AUTH_ERR (7)

PAM module never blocks indefinitely. All operations have timeouts.

Syslog Format

pam_facelock(<service>): <result> for user <username>

Anti-Spoofing

DefenseConfigDefault
IR camera enforcementsecurity.require_irtrue
Frame variance checksecurity.require_frame_variancetrue
Landmark livenesssecurity.require_landmark_livenessfalse
Minimum auth framessecurity.min_auth_frames3
Variance thresholdFRAME_VARIANCE_THRESHOLD0.998

These defaults must not be weakened without security review.

Models

ModelFileSizeDefault
SCRFD 2.5Gscrfd_2.5g_bnkps.onnx~3MBYes
ArcFace R50w600k_r50.onnx~166MBYes
SCRFD 10Gdet_10g.onnx~16MBOptional
ArcFace R100glintr100.onnx~249MBOptional

Configurable via recognition.detector_model and recognition.embedder_model.