diff --git a/README.md b/README.md index 4f110b8..eb3d817 100644 --- a/README.md +++ b/README.md @@ -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. --- diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..cf0b081 --- /dev/null +++ b/install.sh @@ -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 ""