feat: single-command installer

Add install.sh that handles the full setup: dependencies, build, ONNX
models, ONNX runtime, IR emitter configuration, system installation,
face enrollment, and PAM lock screen integration. Includes --uninstall.

Simplify README to just: clone, ./install.sh, done.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-02 15:32:19 +02:00
parent e359d71db4
commit 17317d4bd8
2 changed files with 219 additions and 39 deletions

View File

@@ -43,54 +43,25 @@ Other laptops with Windows Hello-compatible IR cameras should work. If you test
- **GDM** display manager (GNOME, Zorin, Ubuntu)
- Packages: `libpam0g-dev`, `v4l-utils`, `build-essential`
### Quick install
### Install
You need [Rust](https://rustup.rs/) installed. Then:
```bash
# Install dependencies
sudo apt install libpam0g-dev v4l-utils build-essential
# Clone and build
git clone https://gitea.lab48.be/eliott/Linux-Hello.git
cd Linux-Hello
cargo build --release --features onnx
# Build PAM module
cd pam-module && make && cd ..
# Download ONNX models (RetinaFace + MobileFaceNet)
./scripts/download-models.sh
# Install ONNX Runtime (if on Ubuntu 22.04 / glibc < 2.38)
./scripts/install-onnx-runtime.sh --user
# Run the system installer
sudo ./scripts/install-system.sh
# Enable the IR emitter (interactive — follow the prompts)
pip install linux-enable-ir-emitter # or build from source
sudo linux-enable-ir-emitter configure
# Start the daemon
sudo systemctl enable --now linux-hello.service
# Enroll your face
linux-hello enroll
# Test it
linux-hello test
./install.sh
```
### Enable on lock screen
The installer handles everything: dependencies, build, ONNX models, IR emitter setup, face enrollment, and lock screen integration.
Add face auth to GDM by inserting one line in `/etc/pam.d/gdm-password`, right before `@include common-auth`:
When it's done, lock your screen and look at the camera.
### Uninstall
```bash
./install.sh --uninstall
```
auth sufficient pam_linux_hello.so timeout=5
```
That's it. Lock your screen and look at the camera.
If face auth fails for any reason, the password prompt appears normally. To undo, just remove that line.
---

209
install.sh Executable file
View File

@@ -0,0 +1,209 @@
#!/bin/bash
#
# Linux Hello — One-command installer
#
# Usage:
# git clone https://gitea.lab48.be/eliott/Linux-Hello.git && cd Linux-Hello && ./install.sh
#
# What this does:
# 1. Installs build dependencies
# 2. Builds everything (daemon, CLI, PAM module, ONNX models)
# 3. Installs system files (daemon, PAM, systemd, config)
# 4. Sets up IR emitter (interactive — you'll confirm when it lights up)
# 5. Enrolls your face
# 6. Enables face unlock on the lock screen
#
# Your password always works as fallback. To uninstall: ./install.sh --uninstall
#
set -e
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m'
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
# ─── Uninstall ────────────────────────────────────────────────────────────────
if [ "$1" = "--uninstall" ]; then
echo -e "${CYAN}${BOLD}Uninstalling Linux Hello...${NC}"
sudo sed -i '/pam_linux_hello/d' /etc/pam.d/gdm-password 2>/dev/null || true
sudo systemctl disable --now linux-hello.service 2>/dev/null || true
sudo rm -f /usr/libexec/linux-hello-daemon /usr/local/bin/linux-hello
sudo rm -f /lib/x86_64-linux-gnu/security/pam_linux_hello.so /lib/security/pam_linux_hello.so
sudo rm -f /etc/systemd/system/linux-hello.service
sudo rm -f /etc/pam.d/gdm-linux-hello
sudo rm -f /etc/dbus-1/system.d/org.linuxhello.Daemon.conf
sudo rm -rf /etc/linux-hello /var/lib/linux-hello /usr/share/linux-hello
sudo rm -rf /usr/local/lib/linux-hello
sudo systemctl daemon-reload 2>/dev/null || true
echo -e "${GREEN}Uninstalled.${NC}"
exit 0
fi
# ─── Checks ───────────────────────────────────────────────────────────────────
echo -e "${CYAN}${BOLD}"
echo " ╔═══════════════════════════════════╗"
echo " ║ Linux Hello Installer ║"
echo " ║ Face unlock for your laptop ║"
echo " ╚═══════════════════════════════════╝"
echo -e "${NC}"
# Check we're not root (we'll sudo when needed)
if [ "$EUID" -eq 0 ]; then
echo -e "${RED}Don't run as root — the script will sudo when needed.${NC}"
exit 1
fi
# Check for Rust
if ! command -v cargo &>/dev/null; then
echo -e "${RED}Rust not found. Install it first:${NC}"
echo " curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh"
exit 1
fi
# Check for IR camera
echo -e "${YELLOW}[1/8]${NC} Checking hardware..."
if ! v4l2-ctl --list-devices 2>/dev/null | grep -qi "ir\|infrared\|integrated i"; then
echo -e "${YELLOW} Warning: No IR camera detected. Face unlock will work but won't block photo attacks.${NC}"
echo -e "${YELLOW} (Tested on: Lenovo Yoga Pro 7 with Chicony IR camera)${NC}"
HAS_IR=false
else
echo -e "${GREEN} IR camera found.${NC}"
HAS_IR=true
fi
# ─── Dependencies ─────────────────────────────────────────────────────────────
echo -e "${YELLOW}[2/8]${NC} Installing dependencies..."
sudo apt-get update -qq
sudo apt-get install -y -qq libpam0g-dev v4l-utils build-essential wget >/dev/null 2>&1
echo -e "${GREEN} Done.${NC}"
# ─── Build ────────────────────────────────────────────────────────────────────
echo -e "${YELLOW}[3/8]${NC} Downloading ONNX models..."
./scripts/download-models.sh
echo -e "${YELLOW}[4/8]${NC} Building (this takes a minute)..."
cargo build --release --features onnx 2>&1 | tail -1
cd pam-module && make -s 2>&1 && cd ..
echo -e "${GREEN} Built successfully.${NC}"
# ─── ONNX Runtime ─────────────────────────────────────────────────────────────
echo -e "${YELLOW}[5/8]${NC} Setting up ONNX Runtime..."
GLIBC_VER=$(ldd --version 2>&1 | head -1 | grep -oP '\d+\.\d+$')
if [ -f "$HOME/.local/lib/linux-hello/libonnxruntime.so" ]; then
echo -e "${GREEN} Already installed.${NC}"
elif echo "$GLIBC_VER" | awk '{ exit ($1 >= 2.38) ? 0 : 1 }'; then
echo "y" | ./scripts/install-onnx-runtime.sh --user 2>&1 | grep -E "^\[|^$" | head -5
else
./scripts/install-onnx-runtime.sh --user 2>&1 | grep -E "^\[|^$" | head -5
fi
# ─── System Install ──────────────────────────────────────────────────────────
echo -e "${YELLOW}[6/8]${NC} Installing system files (needs sudo)..."
# Stop existing service if running
sudo systemctl stop linux-hello.service 2>/dev/null || true
# Binaries
sudo install -m 755 target/release/linux-hello-daemon /usr/libexec/linux-hello-daemon
sudo install -m 755 target/release/linux-hello /usr/local/bin/linux-hello
# ONNX models
sudo install -d /usr/share/linux-hello/models
for model in models/*.onnx; do
[ -f "$model" ] && sudo install -m 644 "$model" /usr/share/linux-hello/models/
done
# ONNX Runtime library
ORT_LIB="$HOME/.local/lib/linux-hello/libonnxruntime.so"
if [ -f "$ORT_LIB" ]; then
sudo install -d /usr/local/lib/linux-hello
sudo install -m 755 "$ORT_LIB" /usr/local/lib/linux-hello/libonnxruntime.so
fi
# Config
sudo install -d /etc/linux-hello
if [ ! -f /etc/linux-hello/config.toml ]; then
sudo install -m 644 dist/config.toml /etc/linux-hello/config.toml
fi
# D-Bus policy
sudo install -m 644 dist/org.linuxhello.Daemon.conf /etc/dbus-1/system.d/
# PAM module
PAM_DIR="/lib/x86_64-linux-gnu/security"
[ ! -d "$PAM_DIR" ] && PAM_DIR="/lib/security"
sudo install -m 755 pam-module/pam_linux_hello.so "$PAM_DIR/"
# Systemd service
sudo cp dist/linux-hello.service /etc/systemd/system/linux-hello.service
sudo systemctl daemon-reload
echo -e "${GREEN} Installed.${NC}"
# ─── IR Emitter ───────────────────────────────────────────────────────────────
if [ "$HAS_IR" = true ]; then
echo -e "${YELLOW}[7/8]${NC} Configuring IR emitter..."
if ! command -v linux-enable-ir-emitter &>/dev/null; then
echo " Building linux-enable-ir-emitter..."
IR_DIR=$(mktemp -d)
git clone -q https://github.com/EmixamPP/linux-enable-ir-emitter.git "$IR_DIR" 2>/dev/null
(cd "$IR_DIR" && cargo build --release -q 2>/dev/null)
sudo install -m 755 "$IR_DIR/target/release/linux-enable-ir-emitter" /usr/local/bin/
rm -rf "$IR_DIR"
fi
echo ""
echo -e "${BOLD} The IR emitter setup is interactive.${NC}"
echo -e " It will show your IR camera feed and try different settings."
echo -e " ${BOLD}Press 'y' when you see a bright red/white IR light, 'n' otherwise.${NC}"
echo ""
read -p " Ready? (press Enter) " _
sudo linux-enable-ir-emitter configure || echo -e "${YELLOW} IR emitter setup skipped or failed. You can retry later with: sudo linux-enable-ir-emitter configure${NC}"
else
echo -e "${YELLOW}[7/8]${NC} Skipping IR emitter (no IR camera detected)."
fi
# ─── Enable & Enroll ─────────────────────────────────────────────────────────
echo -e "${YELLOW}[8/8]${NC} Starting daemon and enrolling your face..."
sudo systemctl enable --now linux-hello.service
echo ""
echo -e "${BOLD} Look at the camera — enrolling your face now.${NC}"
echo ""
sudo ORT_DYLIB_PATH=/usr/local/lib/linux-hello/libonnxruntime.so linux-hello enroll --label default
# ─── PAM Integration ─────────────────────────────────────────────────────────
# Add face auth to GDM (if not already there)
if ! grep -q "pam_linux_hello" /etc/pam.d/gdm-password 2>/dev/null; then
sudo sed -i '/@include common-auth/i auth sufficient pam_linux_hello.so timeout=5' /etc/pam.d/gdm-password
fi
# ─── Done ─────────────────────────────────────────────────────────────────────
echo ""
echo -e "${GREEN}${BOLD} ╔═══════════════════════════════════╗"
echo " ║ Installation complete! ║"
echo " ╚═══════════════════════════════════╝${NC}"
echo ""
echo " Lock your screen and look at the camera to unlock."
echo " Your password always works as a fallback."
echo ""
echo " Commands:"
echo " linux-hello test — test face recognition"
echo " linux-hello enroll — re-enroll your face"
echo " linux-hello status — check system status"
echo " ./install.sh --uninstall — remove everything"
echo ""