WordPress Developer & Linux Administrator

Bash script to fix permissions on a cPanel web server

Colin at ServInt created it. Boom Shadow modified it. Now I’ve enhanced it to do more.

This version is exactly the same as Boom Shadow’s version, however, I’ve modified it to support additional /home directories so that permissions extend beyond just the default /home directory.

In our servers, we often have a surplus of RAM and CPU due to governors that we’ve put in place to protect and “keep fair” the resources on our servers, but we eventually eat up disk space before we reach a point of maxing out RAM or CPU. So we use cPanel’s ability to create additional home directories (ie., /home, /home2, /home3), each of them on their own attached storage volume.

You’ll run the script the same way, but this version of the script will automatically find the user’s “true” home directory. Once it finds that, it will continue as this script has always operated…fixing the permissions.

Some background on this script

suPHP and FastCGI require files and folders to have a specific set of permissions/ownership different from other handlers. Without these permissions set correctly you will see a lot of errors such as: “403 Forbidden”, “500 Internal Server Error”, or simply generic errors that commonly have the word ‘permission’ in them.

It can be very time consuming to track down and check file permissions across a whole server. Luckily, fixing permissions and ownership on a server running cPanel can be scripted. One of the members of our MST, Colin Roche-Dutch, created a simple script for ServInt called ‘fixperms’ that you can wget to any cPanel server. Simply run the fixperms script, specifying the user (or all users), and the errors disappear. It is a good generic fix if you cannot find your permission problem, or if you have just switched your handler and need a quick way to change every user account on the server.

!! Warning !!

The following script is intended for suPHP or FastCGI ONLY! If you are not running either of these two handlers, do not run fixperms. The script will cause problems if you are running another handler such as DSO. Furthermore, it is highly recommended that you run a full backup of your server before running fixperms or any other script that makes changes to multiple files.

The fixperms script is intended for cPanel servers only. It is dependent on cPanel’s internal scripts and file structure. If you’re on anything else (such as Plesk), it will simply fail to run. It won’t be able to do anything.

Steps to run fixperms on your VPS

wget fixperms and run for a single user

To use the fixperms script, simply log into your server as root, wget the file from our server, then run it. Type in the cPanel username and it will run only for that particular account.

It does not matter which directory you are in when you run fixperms. You can be in the user’s home directory, the server root, etc. The script will not affect anything outside of the particular user’s folder.

wget https://dropshare-uploads.s3.amazonaws.com/fixperms-multi-UfXbgdozZe/fixperms-multi.sh
chmod u+x fixperms-multi.sh
./fixperms-multi.sh -a USER-NAME

Running fixperms for all of the users

If you would like to fix the permissions for every user on your cPanel server, simply use the –all option:

./fixperms-multi.sh --all

Verbosity of fixperms

By default, the script runs in a ‘quiet’ mode with minimal display. However, if you’re like me, you may want to see everything that is happening. You can turn on verbosity using the -v flag and have the script print to the screen everything that is being changed.

This is extremely useful when fixing large accounts that have many files. You can watch the changes as a sort of ‘progress bar’ of completion. The -v flag can be used per account or with all accounts.

For one single account:

./fixperms-multi.sh -v -a USER-NAME

For all accounts:

./fixperms-multi.sh -v --all

The script

#!/bin/bash
#
#  Date: Feb 18th 2015
#  Author: Colin R.
#  Revisions: Jacob "Boom Shadow" Tirey (boomshadow.net)
#  Revisions: Will Ashworth (williamashworth.com || linuxscripts.org)
#
#  Fixperms script for cPanel servers running suPHP or FastCGI.
#  Written for ServInt.net
#  Copyright (C) 2012 Colin R.
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details. http://www.gnu.org/licenses/

# Set verbose to null
verbose=""

#Print the help text
helptext () {
    tput bold
    tput setaf 2
    echo "Fix perms script help:"
    echo "Sets file/directory permissions to match suPHP and FastCGI schemes"
    echo "USAGE: fixperms [options] -a account_name"
    echo "-------"
    echo "Options:"
    echo "-h or --help: print this screen and exit"
    echo "-v: verbose output"
    echo "-all: run on all cPanel accounts"
    echo "--account or -a: specify a cPanel account"
    tput sgr0
    exit 0
}

# Main workhorse, fix perms per account passed to it
fixperms () {

  #Get account from what is passed to the function
  account=$1

  #Check account against cPanel users file
  if ! grep $account /var/cpanel/users/*
  then
    tput bold
    tput setaf 1
    echo "Invalid cPanel account"
    tput sgr0
    exit 0
  fi

  #Make sure account isn't blank
  if [ -z $account ]
  then
    tput bold
    tput setaf 1
    echo "Need an account name!"
    tput sgr0
    helptext
  #Else, start doing work
  else

    #Get the account's homedir and use it throughout the script
    HOMEDIR=$(egrep "^${account}:" /etc/passwd | cut -d: -f6)

    tput bold
    tput setaf 4
    echo "Fixing perms for $account:"
    tput setaf 3
    echo "------------------------"
    tput setaf 4
    echo "Fixing website files...."
    tput sgr0

    #Fix individual files in public_html
    find $HOMEDIR/public_html -type d -exec chmod $verbose 755 {} \;
    find $HOMEDIR/public_html -type f | xargs -d$'\n' -r chmod $verbose 644
    find $HOMEDIR/public_html -name '*.cgi' -o -name '*.pl' | xargs -r chmod $verbose 755
    chown $verbose -R $account:$account $HOMEDIR/public_html/*
    find $HOMEDIR/* -name .htaccess -exec chown $verbose $account.$account {} \;

    tput bold
    tput setaf 4
    echo "Fixing public_html...."
    tput sgr0
    #Fix perms of public_html itself
    chown $verbose $account:nobody $HOMEDIR/public_html
    chmod $verbose 750 $HOMEDIR/public_html

    #Fix subdomains that lie outside of public_html
    tput setaf 3
    tput bold
    echo "------------------------"
    tput setaf 4
    echo "Fixing any domains with a document root outside of public_html...."
    for SUBDOMAIN in $(grep -i document /var/cpanel/userdata/$account/* | awk '{print $2}' | grep home | grep -v public_html)
    do
    tput bold
    tput setaf 4
    echo "Fixing sub/addon domain document root $SUBDOMAIN...."
    tput sgr0
    find $SUBDOMAIN -type d -exec chmod $verbose 755 {} \;
    find $SUBDOMAIN -type f | xargs -d$'\n' -r chmod $verbose 644
    find $SUBDOMAIN -name '*.cgi' -o -name '*.pl' | xargs -r chmod $verbose 755
    chown $verbose -R $account:$account $SUBDOMAIN
    find $SUBDOMAIN -name .htaccess -exec chown $verbose $account.$account {} \;
    done

    #Finished
    tput bold
    tput setaf 3
    echo "Finished!"
    echo "------------------------"
    printf "\n\n"
    tput sgr0
  fi

  return 0
}

#Parses all users through cPanel's users file
all () {
    cd /var/cpanel/users
    for user in *
    do
    fixperms $user
    done
}

#Main function, switches options passed to it
case "$1" in

    -h) helptext
    ;;
    --help) helptext
        ;;
    -v) verbose="-v"

    case "$2" in

        -all) all
               ;;
        --account) fixperms "$3"
               ;;
        -a) fixperms "$3"
            ;;
        *) tput bold
               tput setaf 1
           echo "Invalid Option!"
           helptext
           ;;
    esac
    ;;

    -all) all
      ;;
    --account) fixperms "$2"
            ;;
    -a) fixperms "$2"
    ;;
    *)
       tput bold
       tput setaf 1
       echo "Invalid Option!"
       helptext
       ;;
esac

The fixperms script is intended for cPanel servers only. It is dependent on cPanel’s internal scripts and file structure. If you’re on anything else (such as Plesk), it will simply fail to run. It won’t be able to do anything.

Comments

Your email address will not be published. Required fields are marked *