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:
49
README.md
49
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.
|
||||
|
||||
---
|
||||
|
||||
|
||||
209
install.sh
Executable file
209
install.sh
Executable 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 ""
|
||||
Reference in New Issue
Block a user