← Back to Blog
Making a Cheap USB Fingerprint Scanner Work on Linux — The CS9711 Story
Linux & Open SourceApr 13, 2026• 7 min read

Making a Cheap USB Fingerprint Scanner Work on Linux — The CS9711 Story

I bought a $10 USB fingerprint scanner for my Linux desktop and discovered it was not supported. So I built an open-source installer with a GTK4 GUI that makes it work across Ubuntu, Fedora, Arch, and more.

The Problem

I use Linux as my daily driver — Ubuntu on my workstation at home. When I picked up a cheap Chipsailing CS9711 USB fingerprint scanner (the kind you find for $10-15 online), I expected it to just work. Plug it in, enroll a finger, done.

It did not. The stock libfprint library that Linux uses for fingerprint authentication has no support for the CS9711 chip. The scanner lights up when you plug it in, but the system does not know what to do with it.

There is a community fork of libfprint by archeYR that adds CS9711 support, but getting it working means cloning repos, installing build dependencies, patching source code, compiling from source, and configuring PAM — all manually. Miss one step and it fails silently.

I figured if I had to go through all of that, I might as well automate it so nobody else has to.

What I Built

The project is a one-command installer that handles the entire setup. You clone the repo, run install.sh, and your fingerprint works for login, lock screen, and sudo.

git clone https://github.com/mmhfarooque/chipsailing-cs9711-fingerprint-linux.git
cd chipsailing-cs9711-fingerprint-linux
./install.sh

The installer auto-detects whether you are on Ubuntu, Debian, Fedora, Arch, or openSUSE, and uses the right package manager. It clones the community driver, applies a retry delay patch (the default 250ms is way too fast — your finger gets rejected before you can reposition it), builds the patched library, and sets up PAM with sensible defaults.

The GUI Manager

The command line is fine for the initial install, but managing fingerprints afterwards — enrolling new fingers, adjusting scan timing, checking what is set up — that should be visual. So I built a GTK4/libadwaita GUI manager in Python.

It shows you everything at a glance: is the scanner connected, is the driver installed, which fingers are enrolled. You can enroll new fingerprints with a 15-touch progress bar, adjust the retry delay with a slider, configure how many attempts you get before it falls back to password, and see which auth locations (login, sudo, lock screen) are using fingerprint.

There is also a maintenance section — rebuild the driver after system updates, check for updates from GitHub and apply them with one click, or uninstall everything cleanly. The GUI even has its own activity log viewer for troubleshooting.

Bugs That Taught Me Something

The project went through more than 20 releases (v1.0.0 to v2.0.0), and a lot of the interesting work was fixing subtle bugs that only show up when a GUI runs system commands as root, or when somebody installs your software on a desktop environment you have not tested on.

A few that stand out:

Shell injection risk — Early versions wrote user variables directly into temporary shell scripts that ran via pkexec (the Linux equivalent of Run as Administrator). A carefully crafted username could have run arbitrary commands as root. Fixed it with shlex.quote() and tempfile.mkstemp().

The double password prompt — On first enrollment, the GUI asked for your password twice: once to delete existing fingerprints (there were none) and once to enroll. The fix was simple — check if the finger exists before trying to delete it. But it is the kind of thing you only notice when you watch someone use your software for the first time.

Kill the wrong process — After installing the driver from a terminal, the script ran kill $PPID to close the terminal window. Except when launched from the GUI, $PPID was not a terminal — it was the GUI process itself. Killed the app. The fix: check that the parent process is actually a shell before sending the signal.

Silent PAM skip on a fresh Ubuntu — The Debian/Ubuntu install path edited an existing pam_fprintd.so line in /etc/pam.d/common-auth. Except on a fresh install, that line does not exist yet — the libpam-fprintd profile ships disabled by default. The script silently skipped PAM and you got a working fprintd-verify while sudo, lock screen, and SDDM never even tried fingerprint. v1.8.2 switched to editing /usr/share/pam-configs/fprintd and running pam-auth-update --enable fprintd — the canonical Debian path that survives package upgrades.

The icon that was native — except where users were. v1.4.0 swapped the generic gear for a "native fingerprint icon" using auth-fingerprint-symbolic. It looked great on GNOME. Then somebody installed it on KDE Plasma and the launcher showed a blank-page glyph. Cinnamon (Mint), MATE, XFCE — same. That icon name only ships in the Adwaita icon set; on every other theme the freedesktop icon-fallback chain finds nothing under auth- and gives up. The fix in v1.8.3 is a bundled SVG referenced by absolute path — theme-independent on every freedesktop-compliant DE. The lesson: when your .desktop file assumes every user has your icon theme, half your users get the blank glyph.

The PAM panel that lied — The GUI's "where is fingerprint enabled" panel did substring matching on PAM files. Sounds reasonable until you realise that on Debian/Ubuntu, /etc/pam.d/sudo just says @include common-auth — the actual pam_fprintd.so line lives only in common-auth. Worse, on Kubuntu, /etc/pam.d/polkit-1 and /etc/pam.d/kscreenlocker are not even shipped — those services fall back to PAM defaults. The panel cheerfully reported "Not configured" while fingerprint actually worked. v1.8.3 follows @include chains recursively (and include / substack for Fedora and Arch) and falls back to checking the distro's common stack when no service-specific file exists.

v2.0.0: Surviving the Real World

The jump to v2.0.0 was about getting the installer off "works on my machine" and onto every mainstream distro — and surviving what users actually do to it.

The system update that broke fingerprint. The single most common complaint was "a system update overwrote libfprint and broke my fingerprint." v2.0.0 ships a self-healing update guard: a package-manager post-transaction hook (apt DPkg::Post-Invoke, dnf5 libdnf5-plugin-actions, dnf4 post-transaction-actions, pacman PostTransaction) that detects when the freshly installed libfprint has lost the cs9711 driver and restores it automatically from a root-owned cache at /var/lib/cs9711-fingerprint. The restore is a plain file copy — fast, and it can't fail to compile.

No building as root. An earlier guard rebuilt the driver as root from the user's home directory — a local privilege-escalation footgun. The root-owned-cache restore replaces it: nothing in a user-writable directory ever runs as root.

Won't silently break a different reader. The installer builds a CS9711-only libfprint into /usr/local that shadows the system one. On a laptop with a different fingerprint reader (Goodix, Synaptics, ELAN) that would quietly break it. So v2.0.0 aborts if the CS9711 (2541:0236) isn't detected, unless you override with CS9711_FORCE=1.

OpenCV 5 ahead of time. The sigfm matcher's OpenCV dependency now prefers opencv4 and falls back to opencv5, so it keeps building as distros move on (no shipping distro has OpenCV 5 yet — even Rawhide is still on 4.x).

Current State

The project is at v2.0.0, MIT licensed (scripts) and LGPL-2.1 (driver). It supports Ubuntu, Debian, Fedora, Arch, openSUSE, Linux Mint, and their derivatives. As of v2.0.0 the installer is container-build-verified on every current mainstream distro — Ubuntu 26.04 LTS, Fedora 44, Arch Linux, openSUSE Tumbleweed, Debian 13 (Trixie) and Linux Mint 22 — plus the bleeding-edge branches (Fedora Rawhide/F45, Debian sid, Ubuntu devel). My reference platform on real hardware is Kubuntu 26.04 (Plasma 6.6.4), where enroll, match and sudo/lock/login all work.

One thing worth being precise about: this project is the installer and setup layer. The actual driver and its fingerprint matching live upstream in archeYR/libfprint-CS9711 — the installer ships and configures that best-maintained fork and prompts you to re-enroll for a clean template, rather than claiming to improve matching quality itself.

If you have a CS9711 scanner (USB ID 2541:0236) and run Linux, give it a try:

github.com/mmhfarooque/chipsailing-cs9711-fingerprint-linux

By Mahmud Farooque468 views