Bash script for managing htaccess files

Had to create this for a less technical user to manage htaccess, so thought I'd share. Your mileage may vary.

Change the location of the default htpass file in the config. You can supply another location in mid script if you have more than one.

#!/bin/bash

# Configuration
HTACCESS_FILE_DEFAULT="htpass_test"

# Function to display a list of users
display_users() {
echo "--- Existing Users ---"
# Grep for lines that don't start with # and aren't empty
# Then use cut to show only the username before the colon, and number the lines
grep -vE '^(#|$)' "$HTACCESS_FILE" | cut -d':' -f1 | cat -n
echo "----------------------"
}

# Function to perform a backup
backup_file() {
if [ -f "$HTACCESS_FILE" ]; then
cp "$HTACCESS_FILE" "$HTACCESS_FILE.bak"
echo "Backup created at $HTACCESS_FILE.bak"
else
echo "No .htpasswd file to back up."
fi
}

# Function to generate a random password
generate_password() {
tr -cd '[:alnum:]' < /dev/urandom | head -c 12
}

# --- Main Script ---

# Select the .htpasswd file
read -p "Enter .htpasswd file (default: $HTACCESS_FILE_DEFAULT): " HTACCESS_FILE
HTACCESS_FILE=${HTACCESS_FILE:-$HTACCESS_FILE_DEFAULT}

# Ensure the file exists, exit if not
if [ ! -f "$HTACCESS_FILE" ]; then
echo "Password file doesn't exist"
exit 1
fi

# Main menu loop
while true; do
echo "Do you want to:"
echo "a) Add a user"
echo "r) Remove a user"
echo "u) Update a user's password"
echo "l) List users"
echo "q) Quit"
read -p "Enter your choice: " choice

case "$choice" in
a)
read -p "Enter username to add: " username
# Check if the username already exists
if grep -q "^$username:" "$HTACCESS_FILE"; then
echo "Error: User '$username' already exists. Use the 'u' option to update their password."
else
suggested_password=$(generate_password)
read -p "Enter password for '$username' (or press Enter to use suggested: $suggested_password): " password
password=${password:-$suggested_password}

backup_file
htpasswd -b "$HTACCESS_FILE" "$username" "$password"
echo "User '$username' added."
fi
;;
r)
display_users
read -p "Enter reference number of user to remove: " ref
# Use grep and sed to find the line number and get the username
username_to_remove=$(grep -vE '^(#|$)' "$HTACCESS_FILE" | sed -n "${ref}p" | cut -d':' -f1)

if [ -z "$username_to_remove" ]; then
echo "Invalid reference number."
else
backup_file
# Create a temp file without the user and then replace the original
grep -v "^$username_to_remove:" "$HTACCESS_FILE" > "$HTACCESS_FILE.tmp" && mv "$HTACCESS_FILE.tmp" "$HTACCESS_FILE"
echo "User '$username_to_remove' removed."
fi
;;
u)
display_users
read -p "Enter reference number of user to update: " ref
username_to_update=$(grep -vE '^(#|$)' "$HTACCESS_FILE" | sed -n "${ref}p" | cut -d':' -f1)

if [ -z "$username_to_update" ]; then
echo "Invalid reference number."
else
suggested_password=$(generate_password)
read -p "Enter new password for '$username_to_update' (or press Enter to use suggested: $suggested_password): " password
password=${password:-$suggested_password}

backup_file
htpasswd -b "$HTACCESS_FILE" "$username_to_update" "$password"
echo "Password for user '$username_to_update' updated."
fi
;;
l)
display_users
;;
q)
echo "Exiting."
exit 0
;;
*)
echo "Invalid option. Please try again."
;;
esac

echo # Add a newline for spacing
done

Leave a Comment