#!/usr/bin/env bash # setup_cloud_fscrypt.sh — encrypt a cloud user's data directory with fscrypt. # # Run as root on the HOST (not inside the container) before first deployment. # Requires: fscrypt >= 0.3, Linux kernel >= 4.1, ext4/f2fs filesystem. # # Usage: # sudo ./scripts/setup_cloud_fscrypt.sh # sudo ./scripts/setup_cloud_fscrypt.sh --list # show all encrypted dirs # sudo ./scripts/setup_cloud_fscrypt.sh --status # # Environment: # PAGEPIPER_DATA_DIR — base data directory (default: /devl/pagepiper-cloud-data) # # Key management: # Keys are stored in the system protector backed by a passphrase or root keyring. # For unattended unlock on server boot, use a raw_key protector derived from a # secret in HashiCorp Vault or similar; see docs/encryption.md for details. set -euo pipefail DATA_DIR="${PAGEPIPER_DATA_DIR:-/devl/pagepiper-cloud-data}" USERS_DIR="$DATA_DIR/users" _usage() { grep '^# ' "$0" | cut -c3- exit 1 } _require_root() { if [[ "$EUID" -ne 0 ]]; then echo "ERROR: this script must be run as root" >&2 exit 1 fi } _require_fscrypt() { if ! command -v fscrypt &>/dev/null; then echo "ERROR: fscrypt not found. Install with: apt-get install fscrypt" >&2 exit 1 fi } _check_fscrypt_setup() { local mnt mnt=$(df -P "$DATA_DIR" | tail -1 | awk '{print $6}') if ! fscrypt status "$mnt" &>/dev/null; then echo "Initialising fscrypt on $mnt..." fscrypt setup --quiet "$mnt" echo "fscrypt setup complete on $mnt" fi } cmd="${1:-}" case "$cmd" in --list) _require_root _require_fscrypt echo "Encrypted user directories under $USERS_DIR:" find "$USERS_DIR" -maxdepth 1 -mindepth 1 -type d 2>/dev/null | while read -r dir; do if fscrypt status "$dir" 2>/dev/null | grep -q "Encrypted"; then echo " [encrypted] $dir" else echo " [plain] $dir" fi done ;; --status) _require_root _require_fscrypt user_id="${2:-}" [[ -z "$user_id" ]] && { echo "Usage: $0 --status " >&2; exit 1; } user_dir="$USERS_DIR/$user_id" if [[ ! -d "$user_dir" ]]; then echo "Directory $user_dir does not exist" exit 1 fi fscrypt status "$user_dir" ;; "") _usage ;; -*) _usage ;; *) # Encrypt a user's directory user_id="$1" _require_root _require_fscrypt user_dir="$USERS_DIR/$user_id" if [[ ! -d "$user_dir" ]]; then echo "Creating user directory: $user_dir" mkdir -p "$user_dir" fi if fscrypt status "$user_dir" 2>/dev/null | grep -q "Encrypted"; then echo "Directory $user_dir is already encrypted." exit 0 fi # Warn if directory contains existing data — fscrypt encrypt migrates in place if [[ -n "$(ls -A "$user_dir")" ]]; then echo "WARNING: $user_dir is non-empty. fscrypt will encrypt files in place." echo "Ensure the container is stopped and you have a backup before continuing." read -rp "Continue? [y/N] " confirm [[ "$confirm" =~ ^[Yy]$ ]] || exit 1 fi _check_fscrypt_setup echo "Encrypting $user_dir..." fscrypt encrypt "$user_dir" --source=pam_passphrase --quiet echo "Encryption set up for user $user_id. Directory: $user_dir" echo "" echo "IMPORTANT: unlock the directory before starting the container:" echo " fscrypt unlock $user_dir" ;; esac