Skip to content

Instantly share code, notes, and snippets.

@iAugur
Last active January 8, 2021 17:13
Show Gist options
  • Save iAugur/6041867f7efe46869bcd855741560eb1 to your computer and use it in GitHub Desktop.
Save iAugur/6041867f7efe46869bcd855741560eb1 to your computer and use it in GitHub Desktop.
Configure permissions on a WordPress site. Lock files or open them for update
#!/bin/bash
#
# Configure permissions on a WordPress site. Lock files or open them for plugin/theme updates. This script configures WordPress file permissions based on recommendations
# from http://codex.wordpress.org/Hardening_WordPress#File_permissions
# USAGE: ./script.sh /path/to/wordpress/directory wp_content_folder_name close_or_open
# 👆this script name👆 👆wordpress directory👆 👆wp-content folder name👆 👆"open" only for updates then "close"👆
#
# EXAMPLE : ./script.sh /var/www/html wp-content close __OR__ ./script.sh /var/www/html wp-content open
#
# Pass open as the third variable only when you wish to update plugins/themes, run the same script again with close as third variable to set secure permissions
#
# This script configures WordPress file permissions based on recommendations
# from http://codex.wordpress.org/Hardening_WordPress#File_permissions
#
# Thanks to Michael Conigliaro for the original script: https://gist.github.com/macbleser/9136424
#
# Forked by iAugur. https://gist.github.com/iAugur/6041867f7efe46869bcd855741560eb1/edit https://www.blue-bag.com
#
# GB: Added some checks to ensure valid WP installation etc
#
# base path for www sites
WEBROOT='/var/www'
SUBDIR=$(pwd)
#check to see this is being run as root
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root" 1>&2
exit 1
fi
# OS setup
if [[ "$OSTYPE" == "darwin"* ]]; then
# Mac OSX
_apache_user="_www"
_apache_group="_www"
else
_apache_user="www-data"
_apache_group="www-data"
fi
WP_OWNER=$(id -u "$(logname)") # <-- wordpress owner (This assumes the wordpress owner is the logged in user)
WP_GROUP=$(id -g "$(logname)") # <-- wordpress group (This assumes the wordpress owner is the logged in user)
WS_OWNER=$(
source /etc/apache2/envvars 2>/dev/null && # This works on debian-based systems at least
echo "$APACHE_RUN_USER" ||
echo "${_apache_user}"
) # <-- webserver user
WS_GROUP=$(
source /etc/apache2/envvars 2>/dev/null && # This works on debian-based systems at least
echo "$APACHE_RUN_GROUP" ||
echo "${_apache_group}"
) # <-- webserver group
WP_CLOSE_OWNER=${WP_OWNER} # closed wordpress owner: root is usually the default owner. you can change this
WP_CLOSE_GROUP=${WP_GROUP} # closed wordpress group: root is usually the default group. you can change this
WP_OPEN_OWNER=${WS_OWNER} # open wordpress owner: www-data is usually the default server owner. you can change this
WP_OPEN_GROUP=${WS_GROUP} # open wordpress group: www-data is usually the default server group. you can change this
WP_ROOT="${1:-$SUBDIR}" # wordpress root directory, usually /var/www/html
WP_CONTENT=${2:-"wp-content"} # wordpress content directory, usually wp-content
METHOD=${3:-"close"} #close or open
# is the working directory
# equal to the defined webroot
if [ "$WP_ROOT" == "$WEBROOT" ];then
echo "this must be run in a subdirectory of the webroot"
exit 1
fi
WP_CFGFILE=${WP_ROOT}/wp-config.php
if [ ! -f "${WP_CFGFILE}" ]; then
echo "Please check that there is valid WP installation at ${WP_ROOT}"
fi
# make sure path exists
if [ ! -e "${WP_ROOT}/${WP_CONTENT}" ]; then
echo "WordPress folder 'wp-content' not found!: ${WP_ROOT}/${WP_CONTENT}"
exit 1
fi
echo "Fixing ${METHOD} permissions on ${WP_ROOT} and content in ${WP_CONTENT}"
echo "Wordpress owner.group: ${WP_OWNER}.${WP_GROUP}"
echo "Webserver owner.group: ${WS_OWNER}.${WS_GROUP}"
if [ "${METHOD}" == "open" ]; then
echo "Open owner.group: ${WP_OPEN_OWNER}.${WP_OPEN_GROUP}"
else
echo "Close owner.group: ${WP_CLOSE_OWNER}.${WP_CLOSE_GROUP}"
fi
# reset to safe defaults
if [ "${METHOD}" == "open" ]; then
echo "Set permissions for files: owner.group: ${WP_OPEN_OWNER}.${WP_OPEN_GROUP}"
find "${WP_ROOT}" -exec chown "${WP_OPEN_OWNER}:${WP_OPEN_GROUP}" {} \;
find "${WP_ROOT}" -type d -exec chmod 755 {} \;
find "${WP_ROOT}" -type f -exec chmod 644 {} \;
else
echo "Set permissions for files: owner.group: ${WP_CLOSE_OWNER}.${WP_CLOSE_GROUP}"
find "${WP_ROOT}" -exec chown "${WP_CLOSE_OWNER}:${WP_CLOSE_GROUP}" {} \;
find "${WP_ROOT}" -type d -exec chmod 755 {} \;
find "${WP_ROOT}" -type f -exec chmod 644 {} \;
fi
# allow wordpress to manage wp-config.php (but prevent world access)
echo "Set permissions for wp-config: owner.group: ${WS_GROUP}"
chgrp "${WS_GROUP}" "${WP_ROOT}"/wp-config.php
chmod 660 "${WP_ROOT}"/wp-config.php
# allow wordpress to manage .htaccess on apache servers. you can disable the 3 lines below on nginx servers by putting hash(#) infront of them
echo "allow wordpress to manage .htaccess"
touch "${WP_ROOT}"/.htaccess
chgrp "${WS_GROUP}" "${WP_ROOT}"/.htaccess
chmod 664 "${WP_ROOT}"/.htaccess
# allow wordpress to manage wp-content
echo "allow wordpress to manage ${WP_CONTENT}"
find "${WP_ROOT}/${WP_CONTENT}" -exec chgrp "${WS_GROUP}" {} \;
find "${WP_ROOT}/${WP_CONTENT}" -type d -exec chmod 775 {} \;
find "${WP_ROOT}/${WP_CONTENT}" -type f -exec chmod 664 {} \;
echo "Done!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment