#!/bin/bash # Web Directory Permission Setup Script # Sets proper ownership and permissions for web directories # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Default web directory - current working directory DEFAULT_DIR="$(pwd)" # Function to print colored output print_status() { echo -e "${BLUE}[INFO]${NC} $1" } print_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } print_error() { echo -e "${RED}[ERROR]${NC} $1" } # Function to show usage show_usage() { echo "Usage: $0 [directory_path]" echo " $0 -h|--help" echo "" echo "Sets proper permissions for web directories:" echo " - Directories: 755 (rwxr-xr-x)" echo " - Files: 644 (rw-r--r--)" echo " - Ownership: www-data:www-data" echo " - Sets group sticky bit on directories" echo "" echo "Arguments:" echo " directory_path Path to web directory (default: current directory)" echo " -h, --help Show this help message" echo "" echo "Examples:" echo " $0 # Use current directory and all subdirectories" echo " $0 /var/www/mysite # Use custom directory" echo " $0 . # Explicitly use current directory" echo " $0 .. # Use parent directory" } # Function to check if user has sudo privileges check_sudo() { if ! sudo -n true 2>/dev/null; then print_error "This script requires sudo privileges. Please run with sudo or ensure you have sudo access." exit 1 fi } # Function to validate directory validate_directory() { local dir="$1" # Convert to absolute path dir=$(realpath "$dir" 2>/dev/null) if [[ ! -d "$dir" ]]; then print_error "Directory '$dir' does not exist." read -p "Do you want to create it? (y/N): " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then if sudo mkdir -p "$dir"; then print_success "Created directory '$dir'" else print_error "Failed to create directory '$dir'" exit 1 fi else print_error "Aborting - directory does not exist." exit 1 fi fi echo "$dir" } # Function to check if www-data user/group exists check_www_data() { if ! getent passwd www-data >/dev/null 2>&1; then print_error "User 'www-data' does not exist on this system." print_warning "This might not be a web server or you might need a different user." read -p "Continue anyway? (y/N): " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then exit 1 fi fi if ! getent group www-data >/dev/null 2>&1; then print_error "Group 'www-data' does not exist on this system." exit 1 fi } # Function to show directory info show_directory_info() { local target_dir="$1" print_status "Target directory: $target_dir" print_status "Absolute path: $(realpath "$target_dir")" # Count files and directories for progress local dir_count=$(find "$target_dir" -type d | wc -l) local file_count=$(find "$target_dir" -type f | wc -l) local total_items=$((dir_count + file_count)) echo " - Directories: $dir_count" echo " - Files: $file_count" echo " - Total items: $total_items" # Show current permissions of the root directory print_status "Current permissions of root directory:" ls -ld "$target_dir" } # Main function to set permissions set_permissions() { local target_dir="$1" print_status "Starting permission setup for current directory and all subdirectories..." # Set ownership recursively print_status "Setting ownership to www-data:www-data..." if sudo chown -R www-data:www-data "$target_dir"; then print_success "Ownership set successfully" else print_error "Failed to set ownership" exit 1 fi # Set directory permissions (755) and enable group sticky bit print_status "Setting directory permissions to 2755 with group sticky bit..." if sudo find "$target_dir" -type d -exec chmod 2755 {} \;; then print_success "Directory permissions set successfully" else print_error "Failed to set directory permissions" exit 1 fi # Set file permissions (644) print_status "Setting file permissions to 644..." if sudo find "$target_dir" -type f -exec chmod 644 {} \;; then print_success "File permissions set successfully" else print_error "Failed to set file permissions" exit 1 fi # Make shell scripts executable if any exist local script_count=$(find "$target_dir" -name "*.sh" -type f | wc -l) if [[ $script_count -gt 0 ]]; then print_status "Found $script_count shell scripts, making them executable..." sudo find "$target_dir" -name "*.sh" -type f -exec chmod 755 {} \; print_success "Shell scripts made executable" fi # Make other executable files executable (Python scripts, etc.) local py_count=$(find "$target_dir" -name "*.py" -type f | wc -l) if [[ $py_count -gt 0 ]]; then print_status "Found $py_count Python scripts, checking for executable ones..." # Only make Python files executable if they have shebang sudo find "$target_dir" -name "*.py" -type f -exec sh -c 'head -1 "$1" | grep -q "^#!" && chmod 755 "$1"' _ {} \; fi # Set special permissions for common web files if [[ -f "$target_dir/.htaccess" ]]; then print_status "Setting .htaccess permissions..." sudo chmod 644 "$target_dir/.htaccess" fi # Handle any .git directories (make them less accessible) local git_dirs=$(find "$target_dir" -name ".git" -type d | wc -l) if [[ $git_dirs -gt 0 ]]; then print_status "Found $git_dirs .git directories, setting restricted permissions..." sudo find "$target_dir" -name ".git" -type d -exec chmod 750 {} \; fi print_success "All permissions set successfully!" } # Function to show summary show_summary() { local target_dir="$1" echo "" print_status "Permission Summary for: $target_dir" echo "=========================================" echo "Ownership: www-data:www-data (all files and directories)" echo "Directories: 2755 (rwxr-sr-x) with group sticky bit" echo "Files: 644 (rw-r--r--)" echo "Shell scripts (*.sh): 755 (rwxr-xr-x)" echo "Python scripts with shebang: 755 (rwxr-xr-x)" echo ".git directories: 750 (rwxr-x---)" echo "" # Show some example permissions print_status "Sample of current permissions:" echo "Root directory:" sudo ls -ld "$target_dir" echo "" echo "Contents (first 10 items):" sudo ls -la "$target_dir" | head -11 # Show subdirectory count local subdir_count=$(find "$target_dir" -mindepth 1 -type d | wc -l) if [[ $subdir_count -gt 0 ]]; then echo "" print_status "Also processed $subdir_count subdirectories recursively" fi } # Main script execution main() { local target_dir="$DEFAULT_DIR" # Parse command line arguments case "${1:-}" in -h|--help) show_usage exit 0 ;; "") target_dir="$DEFAULT_DIR" ;; *) target_dir="$1" ;; esac # Validate inputs and prerequisites check_sudo target_dir=$(validate_directory "$target_dir") check_www_data # Show directory information echo "" show_directory_info "$target_dir" # Confirm action echo "" print_warning "WARNING: This will recursively change ownership and permissions for:" print_warning " Directory: $target_dir" print_warning " ALL subdirectories and files within it" print_warning " Ownership will change to: www-data:www-data" print_warning " Directory permissions: 2755 (with group sticky bit)" print_warning " File permissions: 644" echo "" read -p "Are you sure you want to continue? (y/N): " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then print_status "Operation cancelled by user." exit 0 fi # Execute permission changes set_permissions "$target_dir" show_summary "$target_dir" echo "" print_success "Web directory permissions have been set successfully!" print_status "You can now copy files to this directory as a member of www-data group." print_status "New files will automatically inherit the www-data group due to sticky bit." } # Run main function with all arguments main "$@"