#!/bin/bash # Set debug mode based on the 4th script argument. # This must be set BEFORE sourcing the logging library. export DEBUG=${4:-0} # Source the canonical logging library. # The path is relative to this script's location. source "$(dirname "$0")/scripts/logging.sh" # Source the canonical system preparation library. source "$(dirname "$0")/scripts/system_prep.sh" validate_username() { local username=$1 log_debug "Validating username: $username" if ! [[ $username =~ ^[a-zA-Z0-9_]{3,32}$ ]]; then log_error "Invalid username format. Username must be 3-32 characters long and contain only letters, numbers, and underscores." return 1 fi log_debug "Username validation passed" return 0 } # Main script USERNAME=$1 PASSWORD=$2 SSH_ENABLED=${3:-false} # Validate required parameters if [ -z "$USERNAME" ] || [ -z "$PASSWORD" ]; then echo "ERROR: Missing required parameters. Usage: $0 [ssh_enabled]" >&2 exit 1 fi # Log to file only log "======== STARTING SFTP USER SETUP ========" log "Script started with username: $USERNAME, ssh_enabled: $SSH_ENABLED" # Pre-flight checks log "Phase 0: Pre-flight environment checks" if [ ! -d "/var/www/webroot/ROOT" ]; then log_error "Web root directory /var/www/webroot/ROOT does not exist" echo "ERROR: Web root directory /var/www/webroot/ROOT does not exist" >&2 exit 1 fi if [ ! -x "/usr/sbin/useradd" ]; then log_error "useradd command not found or not executable" echo "ERROR: useradd command not found or not executable" >&2 exit 1 fi if [ ! -x "/usr/sbin/chpasswd" ]; then log_error "chpasswd command not found or not executable" echo "ERROR: chpasswd command not found or not executable" >&2 exit 1 fi log_success "Pre-flight checks passed" # Log system information log_system_info log_debug "Script Parameters: username=$USERNAME, ssh_enabled=$SSH_ENABLED" # Fix SFTP configuration log "Phase 1: Configuring SSH/SFTP service" if ! prepare_sftp_system; then log_error "Failed to configure SSH/SFTP service, exiting" echo "ERROR: Failed to configure SSH/SFTP service" >&2 exit 1 fi log_success "SSH/SFTP service configuration completed" # Validate username format log "Phase 2: Validating username" if ! validate_username "$USERNAME"; then log_error "Username validation failed, exiting" echo "ERROR: Username validation failed for: $USERNAME" >&2 exit 1 fi log_success "Username validation passed" # Check if user already exists log "Phase 3: Checking if user already exists" if id "$USERNAME" &>/dev/null; then log_error "Username $USERNAME already exists. Please choose a different username." echo "ERROR: Username $USERNAME already exists" >&2 exit 1 fi log_success "Username is available for creation" USER_HOME="/home/sftpusers/$USERNAME" ROOT_DIRECTORY="/var/www/webroot/ROOT" log_debug "Setting paths - USER_HOME: $USER_HOME, ROOT_DIRECTORY: $ROOT_DIRECTORY" # Create the sftpusers group if it doesn't exist log "Phase 4: Setting up groups" if ! getent group sftpusers > /dev/null; then log "Creating sftpusers group for SFTP-only access" log_cmd "groupadd sftpusers" "Creating sftpusers group" fi # Create the sshusers group if it doesn't exist if ! getent group sshusers > /dev/null; then log "Creating sshusers group for SFTP+SSH access" log_cmd "groupadd sshusers" "Creating sshusers group" fi log_success "Group setup completed" # Ensure the parent directory for user home directories exists log "Phase 5: Setting up directories" if [ ! -d "/home/sftpusers" ]; then log "Creating /home/sftpusers directory" log_cmd "mkdir -p /home/sftpusers" "Creating /home/sftpusers directory" log_cmd "chown root:root /home/sftpusers" "Setting ownership for /home/sftpusers" log_cmd "chmod 755 /home/sftpusers" "Setting permissions for /home/sftpusers" fi log_success "Directory setup completed" # Create the user account log "Phase 6: Creating user account" if [ "$SSH_ENABLED" = "true" ]; then log "Creating user with SSH access" if ! log_cmd "useradd -d $USER_HOME -m -s /bin/bash $USERNAME" "Creating user with bash shell"; then log_error "Failed to create user account with SSH access" echo "ERROR: Failed to create user account with SSH access" >&2 exit 1 fi else log "Creating user with SFTP-only access" if ! log_cmd "useradd -d $USER_HOME -m -s /sbin/nologin $USERNAME" "Creating user with nologin shell"; then log_error "Failed to create user account with SFTP-only access" echo "ERROR: Failed to create user account with SFTP-only access" >&2 exit 1 fi fi log_success "User account created" # Set password log "Phase 7: Setting user password" if ! log_cmd "echo '$USERNAME:$PASSWORD' | chpasswd" "Setting user password"; then log_error "Failed to set password for user $USERNAME" echo "ERROR: Failed to set password for user $USERNAME" >&2 exit 1 fi log_success "Password set for user $USERNAME" # Set up proper directory structure for chroot jail log "Phase 8: Setting up chroot jail structure" log_cmd "chown root:root $USER_HOME" "Setting ownership for chroot directory" log_cmd "chmod 755 $USER_HOME" "Setting permissions for chroot directory" # Create writable data directory for user log_cmd "mkdir -p $USER_HOME/data" "Creating data directory" log_cmd "chown $USERNAME:$USERNAME $USER_HOME/data" "Setting ownership for data directory" log_cmd "chmod 775 $USER_HOME/data" "Setting permissions for data directory" # Create mount point for webroot (using bind mount instead of symlink) log "Phase 9: Setting up webroot access via bind mount" if ! log_cmd "mkdir -p $USER_HOME/data/ROOT" "Creating ROOT mount point"; then log_error "Failed to create ROOT mount point directory" echo "ERROR: Failed to create ROOT mount point directory" >&2 exit 1 fi # Check if ROOT_DIRECTORY exists before mounting if [ ! -d "$ROOT_DIRECTORY" ]; then log_error "Root directory $ROOT_DIRECTORY does not exist" echo "ERROR: Root directory $ROOT_DIRECTORY does not exist" >&2 exit 1 fi if ! log_cmd "mount --bind $ROOT_DIRECTORY $USER_HOME/data/ROOT" "Binding webroot to user's ROOT directory"; then log_error "Failed to create bind mount for webroot access" echo "ERROR: Failed to create bind mount for webroot access" >&2 exit 1 fi # Add mount to fstab to persist across reboots if ! grep -q "$ROOT_DIRECTORY $USER_HOME/data/ROOT" /etc/fstab; then if ! log_cmd "echo \"$ROOT_DIRECTORY $USER_HOME/data/ROOT none bind 0 0\" >> /etc/fstab" "Adding bind mount to fstab"; then log_warning "Failed to add bind mount to fstab - mount may not persist across reboots" fi fi log_success "Created bind mount for webroot access" # Add user to the required groups log "Phase 10: Adding user to groups" if [ "$SSH_ENABLED" = "true" ]; then log_cmd "usermod -aG sshusers $USERNAME" "Adding user to sshusers group for SSH+SFTP access" log_success "Added $USERNAME to sshusers group" else log_cmd "usermod -aG sftpusers $USERNAME" "Adding user to sftpusers group for SFTP-only access" log_success "Added $USERNAME to sftpusers group" fi log_cmd "usermod -aG litespeed $USERNAME" "Adding user to litespeed group for file access" log_success "Added $USERNAME to litespeed group for file access" # Create welcome file log "Phase 11: Creating welcome file" cat > $USER_HOME/data/welcome.txt << EOF Welcome to your SFTP account on Jelastic! Your account has been set up with the following details: Username: $USERNAME Home Directory: $USER_HOME Web Root: $USER_HOME/data/ROOT (symlink to $ROOT_DIRECTORY) For help and support, please contact your system administrator. EOF log_cmd "chown $USERNAME:$USERNAME $USER_HOME/data/welcome.txt" "Setting welcome file ownership" log_cmd "chmod 644 $USER_HOME/data/welcome.txt" "Setting welcome file permissions" log_success "Welcome file created" # Always export variables directly with no console output export CREATED_USERNAME="$USERNAME" export CREATED_PASSWORD="$PASSWORD" # All logging should be to file only log_success "Script completed successfully for user $USERNAME" log "======== SFTP USER SETUP COMPLETE ========" exit 0