Created
September 2, 2025 01:10
-
-
Save rpstreef/e20d0048d39f7497bb99e252f0c8faae to your computer and use it in GitHub Desktop.
Setup FSCrypt folder on Arch Linux
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # fscrypt-arch-setup.sh | |
| # Usage: | |
| # sudo bash fscrypt-arch-setup.sh | |
| # sudo TEST_DIR=1 USERNAME=<your_login> bash fscrypt-arch-setup.sh # optional: create a test dir | |
| set -euo pipefail | |
| # ---- config via env vars ---- | |
| TEST_DIR="${TEST_DIR:-0}" # 1 = create ~/fscrypt_test (interactive) | |
| TARGET_USER="${USERNAME:-${SUDO_USER:-${USER}}}" # user to own the optional test dir | |
| require_root() { | |
| if [[ $EUID -ne 0 ]]; then | |
| echo "This script must run as root (use sudo)." >&2 | |
| exit 1 | |
| fi | |
| } | |
| ts() { date +%Y%m%d-%H%M%S; } | |
| pkg_install() { | |
| echo "[*] Installing fscrypt (and essentials)..." | |
| pacman -Sy --needed --noconfirm fscrypt e2fsprogs >/dev/null | |
| } | |
| backup_file() { | |
| local f="$1" | |
| [[ -f "$f" ]] || return 0 | |
| cp -a -- "$f" "${f}.bak.$(ts)" | |
| } | |
| ensure_pam_line() { | |
| # ensure a line exists in a PAM file, append if missing | |
| local file="$1" line="$2" | |
| grep -Fq -- "$line" "$file" || echo "$line" >> "$file" | |
| } | |
| configure_pam() { | |
| echo "[*] Configuring PAM (Arch style)..." | |
| local LOGIN="/etc/pam.d/system-login" | |
| local PASSWD="/etc/pam.d/passwd" | |
| [[ -f "$LOGIN" ]] || { echo "ERROR: $LOGIN not found."; exit 1; } | |
| [[ -f "$PASSWD" ]] || { echo "ERROR: $PASSWD not found."; exit 1; } | |
| backup_file "$LOGIN" | |
| backup_file "$PASSWD" | |
| # Ensure pam_fscrypt is referenced exactly once in auth & session of system-login. | |
| # We append minimal, safe 'optional' hooks; order is after includes so pam_unix has run. | |
| ensure_pam_line "$LOGIN" "auth optional pam_fscrypt.so" | |
| ensure_pam_line "$LOGIN" "session optional pam_fscrypt.so" | |
| # Keep the login protector in sync on password changes. | |
| ensure_pam_line "$PASSWD" "password optional pam_fscrypt.so" | |
| echo "[*] PAM updated:" | |
| echo " - $LOGIN has: 'auth optional pam_fscrypt.so' and 'session optional pam_fscrypt.so'" | |
| echo " - $PASSWD has: 'password optional pam_fscrypt.so'" | |
| } | |
| is_fs_supported() { | |
| local mp="$1" | |
| local fstype | |
| fstype=$(findmnt -nr -o FSTYPE --target "$mp" || true) | |
| [[ "$fstype" == "ext4" || "$fstype" == "f2fs" ]] | |
| } | |
| device_for_mount() { | |
| local mp="$1" | |
| findmnt -nr -o SOURCE --target "$mp" | |
| } | |
| enable_ext4_encrypt_flag_if_needed() { | |
| local dev="$1" | |
| # Check if encrypt feature is present | |
| if dumpe2fs -h "$dev" 2>/dev/null | grep -qi "Filesystem features:.*encrypt"; then | |
| return 0 | |
| fi | |
| echo "[*] Enabling ext4 'encrypt' feature on $dev ..." | |
| # This usually requires the FS to be unmounted; on a mounted root it will fail safely. | |
| if tune2fs -O encrypt "$dev" 2>/tmp/tune2fs.log; then | |
| echo " - 'encrypt' feature set. Running fsck..." | |
| e2fsck -f "$dev" | |
| else | |
| echo " WARNING: Could not set 'encrypt' online on $dev (likely mounted)." | |
| echo " If this partition is root, consider enabling offline from a Live ISO:" | |
| echo " tune2fs -O encrypt $dev && e2fsck -f $dev" | |
| fi | |
| } | |
| setup_fscrypt_on_mount() { | |
| local mp="$1" | |
| echo "[*] Initializing fscrypt on $mp ..." | |
| # Create /.fscrypt metadata if missing; allow all users to create login protectors | |
| fscrypt setup "$mp" >/dev/null || true | |
| fscrypt setup "$mp" --all-users >/dev/null || true | |
| } | |
| init_filesystems() { | |
| # Handle "/" and "/home" if it is a separate mount. | |
| for MP in / /home; do | |
| if mountpoint -q "$MP"; then | |
| if ! is_fs_supported "$MP"; then | |
| echo "[-] Skipping $MP: not ext4/F2FS" | |
| continue | |
| fi | |
| local DEV | |
| DEV="$(device_for_mount "$MP")" | |
| if [[ -z "$DEV" ]]; then | |
| echo "[-] Unable to resolve block device for $MP, skipping." | |
| continue | |
| fi | |
| # If ext4, try to ensure encrypt feature is set | |
| local FSTYPE | |
| FSTYPE=$(findmnt -nr -o FSTYPE --target "$MP") | |
| if [[ "$FSTYPE" == "ext4" ]]; then | |
| enable_ext4_encrypt_flag_if_needed "$DEV" | |
| fi | |
| setup_fscrypt_on_mount "$MP" | |
| echo "[*] fscrypt status for $MP:" | |
| fscrypt status "$MP" || true | |
| fi | |
| done | |
| } | |
| create_test_dir_if_requested() { | |
| [[ "$TEST_DIR" == "1" ]] || return 0 | |
| local HOME_DIR | |
| HOME_DIR=$(eval echo "~$TARGET_USER") | |
| local TEST="$HOME_DIR/fscrypt_test" | |
| echo "[*] Creating test directory for $TARGET_USER at: $TEST" | |
| install -d -m 700 -o "$TARGET_USER" -g "$(id -gn "$TARGET_USER")" "$TEST" | |
| echo | |
| echo "[i] About to encrypt $TEST with the LOGIN passphrase (interactive)." | |
| echo " Select: '1 - Your login passphrase' when prompted." | |
| echo | |
| # Run fscrypt encrypt as the target user (interactive) | |
| sudo -u "$TARGET_USER" fscrypt encrypt "$TEST" || { | |
| echo "[-] Test directory encryption was not completed." | |
| return 0 | |
| } | |
| echo "[*] Test directory status:" | |
| sudo -u "$TARGET_USER" fscrypt status "$TEST" || true | |
| echo "[*] You can now 'fscrypt lock \"$TEST\"', log out/in, and verify auto-unlock." | |
| } | |
| main() { | |
| require_root | |
| pkg_install | |
| configure_pam | |
| init_filesystems | |
| create_test_dir_if_requested | |
| echo | |
| echo "[✓] fscrypt base setup complete." | |
| echo " Re-login to test auto-unlock. For a quick check now:" | |
| echo " - If you created the test dir: fscrypt lock ~${TARGET_USER}/fscrypt_test ; log out/in ; fscrypt status ~${TARGET_USER}/fscrypt_test" | |
| echo " - Otherwise, encrypt your real dir with: fscrypt encrypt <your_dir> and choose 'Your login passphrase'." | |
| } | |
| main "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment